Ejemplo n.º 1
0
    def __init__(self, scalenode, shapenode):
        d = []
        self.data = d
        self._scalenode = scalenode
        self._shapenode = shapenode

        wt = scalenode.get_world_transform()
        v0 = wt * vec4(1, 0, 0, 0)
        v1 = wt * vec4(0, 1, 0, 0)
        v2 = wt * vec4(0, 0, 1, 0)
        nv0 = v0.normalize()
        nv1 = v1.normalize()
        nv2 = v2.normalize()
        d0, d1, d2 = map(lambda x, y: math.fabs(x * y), [nv0, nv0, nv1],
                         [nv1, nv2, nv2])
        if d0 > 0.1 or d1 > 0.1 or d2 > 0.1:
            print("Error: scale for physical shape '%s' is not orthogonal!" %
                  scalenode.getFullName())
            print(nv0, nv1, nv2)
            print(d0, d1, d2)
            print(wt)
            sys.exit(21)
        check_orthonormal = True

        if shapenode.nodetype == "polyCube":
            self.type = "box"
            check_orthonormal = False
            scale = scalenode.get_world_scale()
            x = shapenode.getAttrValue("w", "w", None, default=1.0)
            y = shapenode.getAttrValue("h", "h", None, default=1.0)
            z = shapenode.getAttrValue("d", "d", None, default=1.0)
            d += list(map(lambda x, y: x * y, [x, y, z], scale))
        elif shapenode.nodetype == "polySphere":
            self.type = "sphere"
            d.append(
                shapenode.getAttrValue("r", "r", None, default=1.0) *
                v0.length())
        else:
            print(
                "Error: primitive physics shape type '%s' on node '%s' is unknown."
                % (shapenode.nodetype, shapenode.getFullName()))
            sys.exit(22)

        if check_orthonormal:
            if math.fabs(v0.length() - v1.length()) > 0.1 or math.fabs(
                    v0.length() -
                    v2.length()) > 0.1 or math.fabs(v1.length() -
                                                    v2.length()) > 0.1:
                print(
                    "Error: scale for physical shape '%s' is not orthonormal!"
                    % scalenode.getFullName())
                sys.exit(21)
 def dowrite(self):
         self._listchildmeshes()
         filename = self.basename+".class"
         with self._fileopenwrite(filename) as f:
                 self.f = f
                 meshptrs = []
                 physidx = 0
                 for m in self.meshes:
                         def _getparentphys(m):
                                 ph = None
                                 mesh = m
                                 while mesh and not ph:
                                         for phys in self.bodies:
                                                 meshes = list(filter(None, [ch == mesh for ch in phys.childmeshes]))
                                                 if len(meshes) == 1:
                                                         if not ph:
                                                                 ph = phys
                                                         else:
                                                                 print("Error: both phys %s and %s has mesh refs to %s." % (ph.getFullName(), phys.getFullName(), mesh.getFullName()))
                                                                 print(ph.childmeshes, meshes)
                                                                 sys.exit(3)
                                                 elif len(meshes) > 1:
                                                         print("Error: phys %s has multiple mesh children refs to %s." % (phys.getFullName(), mesh.getFullName()))
                                                         sys.exit(3)
                                         mesh = mesh.getParent()
                                 if not ph:
                                         print("Warning: mesh %s is not attached to any physics object!" % m.getFullName())
                                 return ph
                         phys = _getparentphys(m)
                         if not phys:
                                 continue
                         phys.writecount = 1
                         m.writecount += 1
                         tm = m.get_world_transform()
                         tp = phys.get_world_transform()
                         tmt, tmr, _ = tm.decompose()
                         tpt, tpr, _ = tp.decompose()
                         q = quat(tpr.inverse()).normalize()
                         p = tmt-tpt
                         p = q.toMat4() * vec4(p[:])
                         q = quat(tpr.inverse() * tmr).normalize()
                         p = p[0:3]
                         t = self._normalizexform(q[:]+p[:])
                         physidx = self.bodies.index(phys)
                         meshptrs += [(CHUNK_CLASS_PHYS_MESH, PhysMeshPtr(physidx, m.meshbasename, t, m.mat))]
                 data =  (
                                 CHUNK_CLASS,
                                 (
                                         (CHUNK_CLASS_PHYSICS, self.basename),
                                         (CHUNK_CLASS_MESH_LIST, meshptrs),
                                 )
                         )
                 #pprint.pprint(data)
                 self._writechunk(data)
                 self._addfeat("class:classes", 1)
         self._verifywritten("physics->mesh links", self.meshes)
         self._addfeat("file:files", 1)
Ejemplo n.º 3
0
        def __init__(self, scalenode, shapenode):
                d = []
                self.data = d
                self._scalenode = scalenode
                self._shapenode = shapenode

                wt = scalenode.get_world_transform()
                v0 = wt*vec4(1,0,0,0)
                v1 = wt*vec4(0,1,0,0)
                v2 = wt*vec4(0,0,1,0)
                nv0 = v0.normalize()
                nv1 = v1.normalize()
                nv2 = v2.normalize()
                d0, d1, d2 = map(lambda x,y: math.fabs(x*y), [nv0, nv0, nv1], [nv1, nv2, nv2])
                if d0 > 0.1 or d1 > 0.1 or d2 > 0.1:
                        print("Error: scale for physical shape '%s' is not orthogonal!" % scalenode.getFullName())
                        print(nv0, nv1, nv2)
                        print(d0, d1, d2)
                        print(wt)
                        sys.exit(21)
                check_orthonormal = True

                if shapenode.nodetype == "polyCube":
                        self.type = "box"
                        check_orthonormal = False
                        scale = scalenode.get_world_scale()
                        x = shapenode.getAttrValue("w", "w", None, default=1.0)
                        y = shapenode.getAttrValue("h", "h", None, default=1.0)
                        z = shapenode.getAttrValue("d", "d", None, default=1.0)
                        d += list(map(lambda x,y: x*y, [x,y,z], scale))
                elif shapenode.nodetype == "polySphere":
                        self.type = "sphere"
                        d.append(shapenode.getAttrValue("r", "r", None, default=1.0)*v0.length())
                else:
                        print("Error: primitive physics shape type '%s' on node '%s' is unknown." % (shapenode.nodetype, shapenode.getFullName()))
                        sys.exit(22)

                if check_orthonormal:
                        if math.fabs(v0.length()-v1.length()) > 0.1 or math.fabs(v0.length()-v2.length()) > 0.1 or math.fabs(v1.length()-v2.length()) > 0.1:
                                print("Error: scale for physical shape '%s' is not orthonormal!" % scalenode.getFullName())
                                sys.exit(21)
Ejemplo n.º 4
0
	def _writeshape(self, shape):
		# Write all general parameters first.
		types = {"capsule":1, "cylinder":2, "sphere":3, "box":4, "mesh":5}
		self._writeint(types[shape.type])
		node = shape.getnode()
		totalmass = self._gettotalmass()
		self._writefloat(float(node.get_fixed_attribute("mass")))
		friction = float(node.get_fixed_attribute("friction"))
		if self.config["type"] == "dynamic":
			friction *= totalmass / 1000.0
		self._writefloat(friction)
		bounce = node.get_fixed_attribute("bounce")
		self._writefloat(float(bounce))
		if options.options.verbose:
			print("Writing shape %s friction=%f, bounce=%f." % (node.getName(), friction, bounce))
		rootindex = -1 if not node.phys_root else self.bodies.index(node.phys_root)
		self._writeint(rootindex)
		jointtype = node.get_fixed_attribute("joint", True)
		jointvalue = joints[jointtype]
		#print(node.getName(), "is jointed by type", jointvalue)
		if jointtype:
			self._addfeat("joint:joints", 1)
		self._writeint(jointvalue)
		is_affected_by_gravity = 1 if node.get_fixed_attribute("affected_by_gravity") else 0
		if options.options.verbose and is_affected_by_gravity:
			print("Writing shape %s as affected by gravity." % node.getName())
		self._writeint(is_affected_by_gravity)
		type_body, type_trigger, type_position = 1, 2, 3
		if node.getName().startswith("phys_trig_"):
			phys_type = type_trigger
			if options.options.verbose:
				print("Writing shape %s as trigger." % node.getName())
		elif node.getName().startswith("phys_pos_"):
			phys_type = type_position
			if options.options.verbose:
				print("Writing shape %s as position." % node.getName())
		else:
			phys_type = type_body
		self._writeint(phys_type)
		# Write joint parameters.
		parameters = [0.0]*16
		#print("Total mass:", totalmass)
		parameters[0] = node.get_fixed_attribute("joint_spring_constant", True, 0.0) * totalmass
		parameters[1] = node.get_fixed_attribute("joint_spring_damping", True, 0.0) * totalmass

		ir = node.getabsirot()

		yaw = node.get_fixed_attribute("joint_yaw", True, 0.0)*math.pi/180
		pitch = node.get_fixed_attribute("joint_pitch", True, 0.0)*math.pi/180
		if options.options.verbose and jointvalue >= 2:
			print("Joint %s euler angles are %s, damping is %f." % (node.getName(), (yaw, pitch), parameters[1]))
		parameters[2:4] = yaw, pitch

		joint_min, joint_max = node.get_fixed_attribute("joint_stops", True, [0.0,0.0])
		if jointtype == "slider":
			parameters[4:6] = joint_min, joint_max
		else:
			parameters[4:6] = math.radians(joint_min), math.radians(joint_max)

		mp = node.get_world_pivot_transform()
		mt = node.get_world_transform()
		wp = mp * vec4(0,0,0,1)
		wt = mt * vec4(0,0,0,1)
		#j = wt-wp
		j = wp-wt
		j = ir * j
		if node.is_phys_root and node.xformparent == node.getphysmaster():
			j = node._pointup_adjust_mat() * j
		j -= self.physrootpos

		#print(node.getName(), "\n", mp, "\n", mt, "\n", wp, "\n", wt, "\n", ir, "\n", j)
		parameters[6:9] = j[:3]

		parameters[9] = node.get_fixed_attribute("impact_factor", True, 1.0)
		parameters[10] = 1.0 if node.get_fixed_attribute("collide_with_self", True, False) else 0.0

		detachable = any(node == mesh.get_mesh_parentphys(self.bodies) for mesh in self.meshes)
		if options.options.verbose:
			print('%s %s detachable.' % (node.getFullName(), 'is' if detachable else 'is not'))
		parameters[11] = 1.0 if detachable else 0.0

		if options.options.verbose:
			print("%s parameters:" % node.getName(), parameters)

		for x in parameters:
			self._writefloat(float(x))
		# Write connecor type (may hook other stuff, may get hooked by hookers :).
		connectors = node.get_fixed_attribute("connector_types", True)
		if connectors:
			if not type(connectors) == list and not type(connetors) == tuple:
				print("Error: connector_types for '%s' must be a list." % node.getFullName())
				sys.exit(19)
			self._writeint(len(connectors))
			for c in connectors:
				self._writeint(connector_types[c])
		else:
			self._writeint(0)

		# Write material.
		material = node.get_fixed_attribute("material")
		if options.options.verbose:
			print("Writing physical material", material);
		self._writestr(material)

		# Write shape data (dimensions of shape).
		scale = node.get_fixed_attribute("scale", default=1)
		shape.data = [type(x)(scale*x) for x in shape.data]
		if options.options.verbose:
			print("Writing shape %s with rootindex %i: %s (scale=%f)." % (node.getName(), rootindex, str(shape.data), scale))
		if node == self.bodies[0]:
			shape.adjustmesh(self.physrootpos)
		for x in shape.data:
			self._writenumber(x)
		self._addfeat("physical geometry:physical geometries", 1)
Ejemplo n.º 5
0
    def dowrite(self):
        self._listchildmeshes()
        filename = self.basename + ".class"
        with self._fileopenwrite(filename) as f:
            self.f = f
            meshptrs = []
            physidx = 0
            for m in self.meshes:

                def _getparentphys(m):
                    ph = None
                    mesh = m
                    while mesh and not ph:
                        for phys in self.bodies:
                            meshes = list(
                                filter(None,
                                       [ch == mesh
                                        for ch in phys.childmeshes]))
                            if len(meshes) == 1:
                                if not ph:
                                    ph = phys
                                else:
                                    print(
                                        "Error: both phys %s and %s has mesh refs to %s."
                                        %
                                        (ph.getFullName(), phys.getFullName(),
                                         mesh.getFullName()))
                                    print(ph.childmeshes, meshes)
                                    sys.exit(3)
                            elif len(meshes) > 1:
                                print(
                                    "Error: phys %s has multiple mesh children refs to %s."
                                    % (phys.getFullName(), mesh.getFullName()))
                                sys.exit(3)
                        mesh = mesh.getParent()
                    if not ph:
                        print(
                            "Warning: mesh %s is not attached to any physics object!"
                            % m.getFullName())
                    return ph

                phys = _getparentphys(m)
                if not phys:
                    continue
                phys.writecount = 1
                m.writecount += 1
                tm = m.get_world_transform()
                tp = phys.get_world_transform()
                tmt, tmr, _ = tm.decompose()
                tpt, tpr, _ = tp.decompose()
                q = quat(tpr.inverse()).normalize()
                p = tmt - tpt
                p = q.toMat4() * vec4(p[:])
                q = quat(tpr.inverse() * tmr).normalize()
                p = p[0:3]
                t = self._normalizexform(q[:] + p[:])
                physidx = self.bodies.index(phys)
                meshptrs += [(CHUNK_CLASS_PHYS_MESH,
                              PhysMeshPtr(physidx, m.meshbasename, t, m.mat))]
            data = (CHUNK_CLASS, (
                (CHUNK_CLASS_PHYSICS, self.basename),
                (CHUNK_CLASS_MESH_LIST, meshptrs),
            ))
            #pprint.pprint(data)
            self._writechunk(data)
            self._addfeat("class:classes", 1)
        self._verifywritten("physics->mesh links", self.meshes)
        self._addfeat("file:files", 1)
Ejemplo n.º 6
0
    def _writeshape(self, shape):
        # Write all general parameters first.
        types = {"capsule": 1, "sphere": 2, "box": 3}
        self._writeint(types[shape.type])
        node = shape.getnode()
        totalmass = self._gettotalmass()
        self._writefloat(float(node.get_fixed_attribute("mass")))
        friction = node.get_fixed_attribute("friction") * totalmass / 1000.0
        self._writefloat(friction)
        self._writefloat(float(node.get_fixed_attribute("bounce")))
        rootindex = -1 if not node.phys_root else self.bodies.index(
            node.phys_root)
        self._writeint(rootindex)
        joints = {
            None: 1,
            "exclude": 1,
            "suspend_hinge": 2,
            "hinge2": 3,
            "hinge": 4,
            "ball": 5,
            "universal": 6
        }
        jointtype = node.get_fixed_attribute("joint", True)
        jointvalue = joints[jointtype]
        #print(node.getName(), "is jointed by type", jointvalue)
        if jointtype:
            self._addfeat("joint:joints", 1)
        self._writeint(jointvalue)
        self._writeint(
            1 if node.get_fixed_attribute("affected_by_gravity") else 0)
        # Write joint parameters.
        parameters = [0.0] * 16
        #print("Total mass:", totalmass)
        parameters[0] = node.get_fixed_attribute("joint_spring_constant", True,
                                                 0.0) * totalmass
        parameters[1] = node.get_fixed_attribute("joint_spring_damping", True,
                                                 0.0) * totalmass

        ir = node.getabsirot()

        yaw = node.get_fixed_attribute("joint_yaw", True, 0.0) * math.pi / 180
        pitch = node.get_fixed_attribute("joint_pitch", True,
                                         0.0) * math.pi / 180
        ##                m = mat4.identity()
        ##                m.setMat3(mat3.fromEulerXZY(0, pitch, yaw))
        ##                v = ir * m * vec4(0,0,1,0)
        ##                # Project onto XY plane.
        ##                xyv = vec3(v[:3])
        ##                xyv[2] = 0
        ##                if xyv.length() < 1e-12:
        ##                        yaw = 0
        ##                        if v[2] < 0:
        ##                                pitch = math.pi
        ##                        else:
        ##                                pitch = 0
        ##                else:
        ##                        xyv = xyv.normalize()
        ##                        # Yaw is angle of projection on the XY plane.
        ##                        if xyv.length():
        ##                                yaw = math.asin(xyv.y/xyv.length())
        ##                        else:
        ##                                yaw = 0
        ##                        v = v.normalize()
        ##                        v = vec3(v[:3])
        ##                        pitch = math.asin(v*xyv)
        if options.options.verbose and jointvalue >= 2:
            print("Joint %s euler angles are: %s." % (node.getName(),
                                                      (yaw, pitch)))
        parameters[2:4] = yaw, pitch

        joint_min, joint_max = node.get_fixed_attribute(
            "joint_angles", True, [0.0, 0.0])
        parameters[4:6] = math.radians(joint_min), math.radians(joint_max)

        mp = node.get_world_pivot_transform()
        mt = node.get_world_transform()
        wp = mp * vec4(0, 0, 0, 1)
        wt = mt * vec4(0, 0, 0, 1)
        j = wp - wt
        j = ir * j

        parameters[6:9] = j[:3]
        for x in parameters:
            self._writefloat(float(x))
        # Write connecor type (may hook other stuff, may get hooked by hookers :).
        connectors = node.get_fixed_attribute("connector_types", True)
        if connectors:
            if not type(connectors) == list and not type(connetors) == tuple:
                print("Error: connector_types for '%s' must be a list." %
                      node.getFullName())
                sys.exit(19)
            self._writeint(len(connectors))
            connector_types = {"connector_3dof": 1, "connectee_3dof": 2}
            for c in connectors:
                self._writeint(connector_types[c])
        else:
            self._writeint(0)
        # Write shape data (dimensions of shape).
        if options.options.verbose:
            print("Writing shape %s with rootindex %i." %
                  (node.getName(), rootindex))
        for x in shape.data:
            self._writefloat(math.fabs(x))
        self._addfeat("physical geometry:physical geometries", 1)
        def _writeshape(self, shape):
                # Write all general parameters first.
                types = {"capsule":1, "sphere":2, "box":3}
                self._writeint(types[shape.type])
                node = shape.getnode()
                totalmass = self._gettotalmass()
                self._writefloat(float(node.get_fixed_attribute("mass")))
                friction = node.get_fixed_attribute("friction") * totalmass / 1000.0
                self._writefloat(friction)
                self._writefloat(float(node.get_fixed_attribute("bounce")))
                rootindex = -1 if not node.phys_root else self.bodies.index(node.phys_root)
                self._writeint(rootindex)
                joints = {None:1, "exclude":1, "suspend_hinge":2, "hinge2":3, "hinge":4, "ball":5, "universal":6}
                jointtype = node.get_fixed_attribute("joint", True)
                jointvalue = joints[jointtype]
                #print(node.getName(), "is jointed by type", jointvalue)
                if jointtype:
                        self._addfeat("joint:joints", 1)
                self._writeint(jointvalue)
                self._writeint(1 if node.get_fixed_attribute("affected_by_gravity") else 0)
                # Write joint parameters.
                parameters = [0.0]*16
                #print("Total mass:", totalmass)
                parameters[0] = node.get_fixed_attribute("joint_spring_constant", True, 0.0) * totalmass
                parameters[1] = node.get_fixed_attribute("joint_spring_damping", True, 0.0) * totalmass

                ir = node.getabsirot()

                yaw = node.get_fixed_attribute("joint_yaw", True, 0.0)*math.pi/180
                pitch = node.get_fixed_attribute("joint_pitch", True, 0.0)*math.pi/180
##                m = mat4.identity()
##                m.setMat3(mat3.fromEulerXZY(0, pitch, yaw))
##                v = ir * m * vec4(0,0,1,0)
##                # Project onto XY plane.
##                xyv = vec3(v[:3])
##                xyv[2] = 0
##                if xyv.length() < 1e-12:
##                        yaw = 0
##                        if v[2] < 0:
##                                pitch = math.pi
##                        else:
##                                pitch = 0
##                else:
##                        xyv = xyv.normalize()
##                        # Yaw is angle of projection on the XY plane.
##                        if xyv.length():
##                                yaw = math.asin(xyv.y/xyv.length())
##                        else:
##                                yaw = 0
##                        v = v.normalize()
##                        v = vec3(v[:3])
##                        pitch = math.asin(v*xyv)
                if options.options.verbose and jointvalue >= 2:
                        print("Joint %s euler angles are: %s." % (node.getName(), (yaw, pitch)))
                parameters[2:4] = yaw, pitch

                joint_min, joint_max = node.get_fixed_attribute("joint_angles", True, [0.0,0.0])
                parameters[4:6] = math.radians(joint_min), math.radians(joint_max)

                mp = node.get_world_pivot_transform()
                mt = node.get_world_transform()
                wp = mp * vec4(0,0,0,1)
                wt = mt * vec4(0,0,0,1)
                j = wp-wt
                j = ir * j

                parameters[6:9] = j[:3]
                for x in parameters:
                        self._writefloat(float(x))
                # Write connecor type (may hook other stuff, may get hooked by hookers :).
                connectors = node.get_fixed_attribute("connector_types", True)
                if connectors:
                        if not type(connectors) == list and not type(connetors) == tuple:
                                print("Error: connector_types for '%s' must be a list." % node.getFullName())
                                sys.exit(19)
                        self._writeint(len(connectors))
                        connector_types = {"connector_3dof":1, "connectee_3dof":2}
                        for c in connectors:
                                self._writeint(connector_types[c])
                else:
                        self._writeint(0)
                # Write shape data (dimensions of shape).
                if options.options.verbose:
                        print("Writing shape %s with rootindex %i." % (node.getName(), rootindex))
                for x in shape.data:
                        self._writefloat(math.fabs(x))
                self._addfeat("physical geometry:physical geometries", 1)
Ejemplo n.º 8
0
	def __init__(self, scalenode, shapenode):
		d = []
		self.data = d
		self._scalenode = scalenode
		self._shapenode = shapenode

		scalenode.pointup = False

		wt = scalenode.get_world_transform()
		v0 = wt*vec4(1,0,0,0)
		v1 = wt*vec4(0,1,0,0)
		v2 = wt*vec4(0,0,1,0)
		nv0 = v0.normalize()
		nv1 = v1.normalize()
		nv2 = v2.normalize()
		d0, d1, d2 = map(lambda x,y: math.fabs(x*y), [nv0, nv0, nv1], [nv1, nv2, nv2])
		global disable_ortho_check
		if not disable_ortho_check and (d0 > 0.1 or d1 > 0.1 or d2 > 0.1):
			print("Error: scale for physical shape '%s' is not orthogonal!" % scalenode.getFullName())
			print(nv0, nv1, nv2)
			print(d0, d1, d2)
			print(wt)
			sys.exit(21)
		check_orthonormal = True

		if shapenode.nodetype == "polyCube":
			self.type = "box"
			check_orthonormal = False
			scale = scalenode.get_world_scale()
			x = shapenode.getAttrValue("w", "w", None, default=1.0)
			y = shapenode.getAttrValue("h", "h", None, default=1.0)
			z = shapenode.getAttrValue("d", "d", None, default=1.0)
			d += list(map(lambda x,y: x*y, [x,y,z], scale))
		elif shapenode.nodetype == "polySphere":
			self.type = "sphere"
			d.append(shapenode.getAttrValue("r", "r", None, default=1.0)*v0.length())
		elif shapenode.nodetype == "polyCylinder":
			self.type = "cylinder"
			scalenode.pointup = True
			r = shapenode.getAttrValue("r", "r", None, default=1.0)*v0.length()
			h = shapenode.getAttrValue("h", "h", None, default=2.0)*v0.length()
			d += [r, h]
		elif shapenode.nodetype == "mesh":
			self.type = "mesh"
			vtx = shapenode.get_fixed_attribute("rgvtx")
			tri = shapenode.get_fixed_attribute("rgtri")
			d += [len(vtx)//3, len(tri)//3]
			d += list(map(lambda x: float(x), vtx))
			d += list(map(lambda x: int(x), tri))
		else:
			print("Error: primitive physics shape type '%s' on node '%s' is unknown." % (shapenode.nodetype, shapenode.getName()))
			sys.exit(22)

		override_shapetype = scalenode.get_fixed_attribute("override_shapetype", optional=True)
		if override_shapetype:
			self.type = override_shapetype
			if self.type == "capsule":
				r = shapenode.getAttrValue("r", "r", None, default=1.0)*v0.length()
				# Reduce height by the radius in each end, so it won't bulge out.
				h = shapenode.getAttrValue("h", "h", None, default=2.0)*v0.length() - 2*r
				if r <= 0 or h <= 0:
					print("Error: the %s shape is used as a capsule for %s, and must have a greater height than radius*2. (r=%f, h=%f)" %
						(shapenode.nodetype, scalenode.getFullName(), r, h))
				d[-1] = h

		if not disable_ortho_check and check_orthonormal:
			if math.fabs(v0.length()-v1.length()) > 0.1 or math.fabs(v0.length()-v2.length()) > 0.1 or math.fabs(v1.length()-v2.length()) > 0.1:
				print("Error: scale for physical shape '%s' is not orthonormal!" % scalenode.getFullName())
				print(v0, v1, v2)
				print(scalenode, scalenode.get_world_transform())
				print(disable_ortho_check)
				sys.exit(21)