示例#1
0
        public OdeSolid(dWorldID worldID, dSpaceID spaceID)
        {
            this.worldID         = worldID;
            this.spaceID         = spaceID;
            isPlaceable          = true;
            collisionCount       = 0;
            nonSymmetricInertia  = false;
            isFreelySpinning     = true;
            prevAngVelMagSquared = 0;

            data = new SolidData();

            if (!data.IsStatic)
            {
                // Create an ODE body with default ODE mass parameters (total
                // mass = 1).  This should have an initial mass of 0 until shapes
                // are added, but ODE won't allow a mass of 0.  This will be
                // adjusted appropriately when the first shape is added.

                bodyID = this.worldID.CreateBody();

                //mBodyID = new Body(mWorldID);
            }

            Init(data);
        }
示例#2
0
        public override void AddShape(ShapeData data)
        {
            if (data.Material.Density < 0)
            {
                return;
            }

            dGeomID        newGeomID        = null;
            dGeomID        newTransformID   = null;
            dTriMeshDataID newTrimeshDataID = null;
            dSpaceID       tempSpaceID      = null;

            Tao.Ode.Ode.dMass newMass = new Tao.Ode.Ode.dMass();

            if (new Matrix() == data.Offset)
            {
                // No offset transform.
                tempSpaceID    = spaceID;
                newTransformID = null;
            }
            else
            {
                // Use ODE's geom transform object.
                tempSpaceID    = IntPtr.Zero;
                newTransformID = spaceID.CreateGeomTransform();
            }

            // Allocate a new GeomData object.
            GeomData newGeomData = new GeomData();

            switch (data.Type)
            {
            case ShapeType.Box:
            {
                BoxShapeData boxData = data as BoxShapeData;

                newGeomID = tempSpaceID.CreateBoxGeom(boxData.Dimensions.X,
                                                      boxData.Dimensions.Y,
                                                      boxData.Dimensions.Z);

                Tao.Ode.Ode.dMassSetBox(ref newMass, data.Material.Density,
                                        boxData.Dimensions.X,
                                        boxData.Dimensions.Y,
                                        boxData.Dimensions.Z);
                break;
            }

            case ShapeType.Sphere:
            {
                SphereShapeData sphereData = data as SphereShapeData;

                newGeomID = tempSpaceID.CreateSphereGeom(sphereData.Radius);

                Tao.Ode.Ode.dMassSetSphere(ref newMass, data.Material.Density, sphereData.Radius);
                break;
            }

            case ShapeType.Capsule:
            {
                CapsuleShapeData capsuleData = data as CapsuleShapeData;

                newGeomID = tempSpaceID.CreateCylinderGeom(capsuleData.Radius, capsuleData.Length);

                // The "direction" parameter orients the mass along one of the
                // body's local axes; x=1, y=2, z=3.  This axis MUST
                // correspond with the axis along which the capsule is
                // initially aligned, which is the capsule's local Z axis.

                /*Tao.Ode.Ode.dMassSetCylinder(ref newMass, data.Material.Density,
                 *                      3, capsuleData.Radius, capsuleData.Length);*/
                Tao.Ode.Ode.dMassSetCapsule(ref newMass, data.Material.Density, 3,
                                            capsuleData.Radius, capsuleData.Length);
                break;
            }

            case ShapeType.Plane:
            {
                PlaneShapeData planeData = data as PlaneShapeData;
                if (!this.data.IsStatic)
                {
                    //OPAL_LOGGER( "warning" ) << "opal::ODESolid::addPlane: " <<
                    //"Plane Shape added to a non-static Solid.  " <<
                    //"The Solid will be made static." << std::endl;

                    // ODE planes can't have bodies, so make it static.
                    this.Static = true;
                }

                // TODO: make this fail gracefully and print warning: plane
                // offset transform ignored.
                if (newTransformID != null)
                {
                    break;
                }

                // ODE planes must have their normal vector (abc) normalized.
                Vector3 normal = new Vector3(planeData.Abcd[0], planeData.Abcd[1], planeData.Abcd[2]);
                normal.Normalize();

                newGeomID = tempSpaceID.CreatePlaneGeom(normal.X, normal.Y, normal.Z, planeData.Abcd[3]);

                // Note: ODE planes cannot have mass, but this is already
                // handled since static Solids ignore mass.

                // Solids with planes are the only non-"placeable" Solids.
                isPlaceable = false;
                break;
            }

            //case RAY_SHAPE:
            //{
            //	RayShapeData& rayData = (RayShapeData&)data;
            //	newGeomID = dCreateRay(spaceID,
            //		(dReal)rayData.ray.getLength());
            //	Point3r origin = rayData.ray.getOrigin();
            //	Vec3r dir = rayData.ray.getDir();
            //	dGeomRaySet(newGeomID, (dReal)origin[0], (dReal)origin[1],
            //		(dReal)origin[2], (dReal)dir[0], (dReal)dir[1],
            //		(dReal)dir[2]);
            //	// Note: rays don't have mass.
            //	break;
            //}
            case ShapeType.Mesh:
            {
                MeshShapeData meshData = data as MeshShapeData;

                // Setup trimesh data pointer.  It is critical that the
                // size of OPAL reals at this point match the size of ODE's
                // dReals.
                newTrimeshDataID = dTriMeshDataID.Create();

                // Old way... This is problematic because ODE interprets
                // the vertex array as an array of dVector3s which each
                // have 4 elements.
                //dGeomTriMeshDataBuildSimple(newTrimeshDataID,
                //	(dReal*)meshData.vertexArray, meshData.numVertices,
                //	(int*)meshData.triangleArray, 3 * meshData.numTriangles);

                //#ifdef dSINGLE
                newTrimeshDataID.BuildSingle(meshData.VertexArray, 3 * sizeof(float),
                                             meshData.NumVertices,
                                             meshData.TriangleArray,
                                             3 * meshData.NumTriangles,
                                             3 * sizeof(int));
                //#else
                //                    dGeomTriMeshDataBuildDouble( newTrimeshDataID,
                //                                                 ( void* ) meshData.vertexArray, 3 * sizeof( real ),
                //                                                 meshData.numVertices, ( void* ) meshData.triangleArray,
                //                                                 3 * meshData.numTriangles, 3 * sizeof( unsigned int ) );
                //#endif

                newGeomID = tempSpaceID.CreateTriMeshGeom(newTrimeshDataID);

                // This is a simple way to set the mass of an arbitrary
                // mesh.  Ideally we would compute the exact volume and
                // intertia tensor.  Instead we just use a box
                // inertia tensor from its axis-aligned bounding box.
                float[] aabb = newGeomID.AABB;

                //					dGeomGetAABB( newGeomID, aabb );
                Tao.Ode.Ode.dMassSetBox(ref newMass, data.Material.Density,
                                        aabb[1] - aabb[0], aabb[3] - aabb[2],
                                        aabb[5] - aabb[4]);
                break;
            }

            default:
                throw new InvalidOperationException("OdeSolid.AddShape");
            }

            // This will do nothing if this is a static Solid.
            AddMass(newMass, data.Offset);

            // Store new Shape.
            this.data.AddShape(data);

            // Update the Solid's local AABB.  The new shape's local AABB
            // must be transformed using the shape's offset from the Solid.
            BoundingBox shapeAABB = data.LocalAABB;
            //data.LocalAABBgetLocalAABB( shapeAABB );
            Vector3 minExtents = Vector3.Transform(shapeAABB.Min, data.Offset);
            Vector3 maxExtents = Vector3.Transform(shapeAABB.Max, data.Offset);

            shapeAABB.Min = minExtents;
            shapeAABB.Max = maxExtents;

            AddToLocalAABB(shapeAABB);

            if (newGeomData == null)
            {
                return;
            }

            // Setup GeomData.
            newGeomData.Solid         = this;
            newGeomData.Shape         = this.data.GetShapeData(this.data.NumShapes - 1);
            newGeomData.GeomID        = newGeomID;
            newGeomData.TransformID   = newTransformID;
            newGeomData.SpaceID       = spaceID;
            newGeomData.TrimeshDataID = newTrimeshDataID;

            // Setup the geom.
            SetupNewGeom(newGeomData);
        }