/// <summary> /// Trimesh class constructor. /// /// The Data member defines the vertex data the newly created triangle mesh will use. /// </summary> /// <param name="Data"></param> /// <returns></returns> public dGeomID CreateTriMeshGeom(dTriMeshDataID Data) { return(Tao.Ode.Ode.dCreateTriMesh(this, Data, null, null, null)); }
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); }
/// <summary> /// Trimesh class constructor. /// /// The Data member defines the vertex data the newly created triangle mesh will use. /// /// Callbacks are optional. /// </summary> /// <param name="Data"></param> /// <param name="Callback"></param> /// <param name="ArrayCallback"></param> /// <param name="RayCallback"></param> /// <returns></returns> public dGeomID CreateTriMeshGeom(dTriMeshDataID Data, Tao.Ode.Ode.dTriCallback Callback, Tao.Ode.Ode.dTriArrayCallback ArrayCallback, Tao.Ode.Ode.dTriRayCallback RayCallback) { return(Tao.Ode.Ode.dCreateTriMesh(this, Data, Callback, ArrayCallback, RayCallback)); }