unsafe void MakeRoad() { if (end_make == false && HeightmapTerrain.Instances[0] != null) { Vertex[] vertices = new Vertex[vertex_count]; ushort[] indices = new ushort[index_count]; for (int i = 0; i < index_count; i++) { indices[i] = (ushort)(vertex_ind[i]); } for (int i = 0; i < vertex_count; i++) { Vertex vertex = new Vertex(); Vec3 p = ((vertex_pos[i] * attached_mesh.ScaleOffset) * Rotation) + (Position + attached_mesh.PositionOffset); Vec2 mesh_vertex_pos = new Vec2(p.X, p.Y); float terrain_height = HeightmapTerrain.Instances[0].Position.Z + HeightmapTerrain.Instances[0].GetHeight(mesh_vertex_pos, false); Vec3 terrain_norm = HeightmapTerrain.Instances[0].GetNormal(mesh_vertex_pos); vertex.position = new Vec3(vertex_pos[i].X, vertex_pos[i].Y, terrain_height); vertex.normal = terrain_norm; vertex.texCoord = vertex_tc[i]; vertices[i] = vertex; } SubMesh sub_mesh = mesh.SubMeshes[0]; { HardwareVertexBuffer vertex_buffer = sub_mesh.VertexData.VertexBufferBinding.GetBuffer(0); IntPtr buffer = vertex_buffer.Lock(HardwareBuffer.LockOptions.Discard); fixed(Vertex *pvertices = vertices) { NativeUtils.CopyMemory(buffer, (IntPtr)pvertices, vertices.Length * sizeof(Vertex)); } vertex_buffer.Unlock(); } { HardwareIndexBuffer index_buffer = sub_mesh.IndexData.IndexBuffer; IntPtr buffer = index_buffer.Lock(HardwareBuffer.LockOptions.Discard); fixed(ushort *pindices = indices) { NativeUtils.CopyMemory(buffer, (IntPtr)pindices, indices.Length * sizeof(ushort)); } index_buffer.Unlock(); } if (EngineApp.Instance.ApplicationType == EngineApp.ApplicationTypes.Simulation) { end_make = true; first_init_mesh = true; } } }
//file stream unsafe int ReadDataFromFileStream(IntPtr buffer, int needRead) { DirectFileStreamSound currentFileStreamSound = (DirectFileStreamSound)currentSound; while (streamBufferLength < needRead) { int readBytes = currentFileStreamSound.vorbisFile.read( (IntPtr)(streamBuffer + streamBufferLength), currentSound.bufferSize - streamBufferLength, 0, 2, 1, IntPtr.Zero); //convert to mono for 3D if (readBytes > 0 && currentFileStreamSound.needConvertToMono) { byte *pointer = (byte *)streamBuffer + streamBufferLength; readBytes /= 2; for (int n = 0; n < readBytes; n += 2) { *(pointer + n + 0) = *(pointer + n * 2 + 0); *(pointer + n + 1) = *(pointer + n * 2 + 1); } } if (readBytes > 0) { streamBufferLength += readBytes; } else { break; } } if (streamBufferLength == 0) { return(0); } int totalReaded = Math.Min(streamBufferLength, needRead); NativeUtils.CopyMemory(buffer, (IntPtr)streamBuffer, totalReaded); streamBufferLength -= totalReaded; if (streamBufferLength > 0) { NativeUtils.MoveMemory((IntPtr)streamBuffer, (IntPtr)(streamBuffer + totalReaded), streamBufferLength); } return(totalReaded); }
private unsafe void UpdateGeometry(float time) { //generate geometry Vertex[] vertices = new Vertex[tesselation * tesselation]; ushort[] indices = new ushort[(tesselation - 1) * (tesselation - 1) * 6]; { //vertices int vertexPosition = 0; for (int y = 0; y < tesselation; y++) { for (int x = 0; x < tesselation; x++) { Vertex vertex = new Vertex(); Vec2 pos2 = new Vec2( (float)x / (float)(tesselation - 1) - .5f, (float)y / (float)(tesselation - 1) - .5f); float posZ = MathFunctions.Sin(pos2.Length() * 30 - time * 2) / 2; MathFunctions.Clamp(ref posZ, -5f, .5f); vertex.position = new Vec3(pos2.X, pos2.Y, posZ) * Scale; vertex.normal = Vec3.Zero; vertex.texCoord = new Vec2(pos2.X + .5f, pos2.Y + .5f); //vertex.tangents = Vec4.Zero; vertices[vertexPosition] = vertex; vertexPosition++; } } //indices int indexPosition = 0; for (int y = 0; y < tesselation - 1; y++) { for (int x = 0; x < tesselation - 1; x++) { indices[indexPosition] = (ushort)(tesselation * y + x); indexPosition++; indices[indexPosition] = (ushort)(tesselation * y + x + 1); indexPosition++; indices[indexPosition] = (ushort)(tesselation * (y + 1) + x + 1); indexPosition++; indices[indexPosition] = (ushort)(tesselation * (y + 1) + x + 1); indexPosition++; indices[indexPosition] = (ushort)(tesselation * (y + 1) + x); indexPosition++; indices[indexPosition] = (ushort)(tesselation * y + x); indexPosition++; } } //calculate vertex normals fixed(Vertex *pVertices = vertices) { int triangleCount = indices.Length / 3; for (int n = 0; n < triangleCount; n++) { int index0 = indices[n * 3 + 0]; int index1 = indices[n * 3 + 1]; int index2 = indices[n * 3 + 2]; Vec3 pos0 = pVertices[index0].position; Vec3 pos1 = pVertices[index1].position; Vec3 pos2 = pVertices[index2].position; Vec3 normal = Vec3.Cross(pos1 - pos0, pos2 - pos0); normal.Normalize(); pVertices[index0].normal += normal; pVertices[index1].normal += normal; pVertices[index2].normal += normal; } //normalize for (int n = 0; n < vertices.Length; n++) { pVertices[n].normal = pVertices[n].normal.GetNormalize(); } } } SubMesh subMesh = mesh.SubMeshes[0]; //copy data to vertex buffer { HardwareVertexBuffer vertexBuffer = subMesh.VertexData.VertexBufferBinding.GetBuffer(0); IntPtr buffer = vertexBuffer.Lock(HardwareBuffer.LockOptions.Discard); fixed(Vertex *pVertices = vertices) { NativeUtils.CopyMemory(buffer, (IntPtr)pVertices, vertices.Length * sizeof(Vertex)); } vertexBuffer.Unlock(); } //copy data to index buffer { HardwareIndexBuffer indexBuffer = subMesh.IndexData.IndexBuffer; IntPtr buffer = indexBuffer.Lock(HardwareBuffer.LockOptions.Discard); fixed(ushort *pIndices = indices) { NativeUtils.CopyMemory(buffer, (IntPtr)pIndices, indices.Length * sizeof(ushort)); } indexBuffer.Unlock(); } ////calculate mesh tangent vectors //mesh.BuildTangentVectors( VertexElementSemantic.Tangent, 0, 0, true ); }
void CreateGeomDatas() { tempGeomDatasAsList.Clear(); for (int n = 0; n < Shapes.Length; n++) { tempGeomDatasAsList.Add(null); } dSpaceID bodySpaceID = scene.rootSpaceID; for (int nShape = 0; nShape < Shapes.Length; nShape++) { Shape shape = Shapes[nShape]; GeomData geomData = new GeomData(); geomData.shape = shape; geomData.odeBody = (ODEBody)shape.Body; bool identityTransform = shape.Position == Vec3.Zero && shape.Rotation == Quat.Identity; // No offset transform. if (identityTransform) { geomData.spaceID = bodySpaceID; } //create geom switch (shape.ShapeType) { case Shape.Type.Box: { BoxShape boxShape = (BoxShape)shape; geomData.geomID = Ode.dCreateBox(geomData.spaceID, boxShape.Dimensions.X, boxShape.Dimensions.Y, boxShape.Dimensions.Z); } break; case Shape.Type.Sphere: { SphereShape sphereShape = (SphereShape)shape; geomData.geomID = Ode.dCreateSphere(geomData.spaceID, sphereShape.Radius); } break; case Shape.Type.Capsule: { CapsuleShape capsuleShape = (CapsuleShape)shape; geomData.geomID = Ode.dCreateCapsule(geomData.spaceID, capsuleShape.Radius, capsuleShape.Length); } break; case Shape.Type.Cylinder: { CylinderShape cylinderShape = (CylinderShape)shape; geomData.geomID = Ode.dCreateCylinder(geomData.spaceID, cylinderShape.Radius, cylinderShape.Length); } break; case Shape.Type.Mesh: { MeshShape meshShape = (MeshShape)shape; if (!Static) { if (!notSupportedMeshesLogInformed) { notSupportedMeshesLogInformed = true; Log.Warning("ODEBody: Dynamic convex and triangle meshes are not " + "supported by ODE."); } Log.Info("ODEBody: Dynamic convex and triangle meshes are not " + "supported by ODE."); //ignore shape continue; } //get mesh geometry from cache PhysicsWorld._MeshGeometry geometry = meshShape._GetMeshGeometry(); //ignore shape if (geometry == null) { Log.Info("ODEBody: Mesh is not initialized. ({0}).", meshShape.MeshName); continue; } ODEPhysicsWorld.MeshGeometryODEData data; if (geometry.UserData == null) { data = new ODEPhysicsWorld.MeshGeometryODEData(); //generate MeshGeometryODEData data data.triMeshDataID = Ode.dGeomTriMeshDataCreate(); data.verticesCount = geometry.Vertices.Length; data.indicesCount = geometry.Indices.Length; data.vertices = (IntPtr)Ode.dAlloc((uint) (Marshal.SizeOf(typeof(float)) * 3 * data.verticesCount)); data.indices = (IntPtr)Ode.dAlloc((uint) (Marshal.SizeOf(typeof(int)) * data.indicesCount)); unsafe { fixed(Vec3 *source = geometry.Vertices) { NativeUtils.CopyMemory(data.vertices, (IntPtr)source, data.verticesCount * sizeof(Vec3)); } fixed(int *source = geometry.Indices) { NativeUtils.CopyMemory(data.indices, (IntPtr)source, data.indicesCount * sizeof(int)); } } //build ode tri mesh data Ode.dGeomTriMeshDataBuildSingleAsIntPtr( data.triMeshDataID, data.vertices, Marshal.SizeOf(typeof(float)) * 3, data.verticesCount, data.indices, data.indicesCount, Marshal.SizeOf(typeof(int)) * 3); geometry.UserData = data; } else { data = (ODEPhysicsWorld.MeshGeometryODEData)geometry.UserData; } data.checkRefCounter++; geomData.meshGeometryODEData = data; geomData.geomID = Ode.dCreateTriMesh(geomData.spaceID, data.triMeshDataID, null, null, null); Ode.SetGeomTriMeshSetRayCallback(geomData.geomID); //unsafe //{ // float[] planes = new float[] // { // 1.0f ,0.0f ,0.0f ,0.25f, // 0.0f ,1.0f ,0.0f ,0.25f, // 0.0f ,0.0f ,1.0f ,0.25f, // -1.0f,0.0f ,0.0f ,0.25f, // 0.0f ,-1.0f,0.0f ,0.25f, // 0.0f ,0.0f ,-1.0f,0.25f // }; // float[] points = new float[] // { // 0.25f,0.25f,0.25f, // -0.25f,0.25f,0.25f, // 0.25f,-0.25f,0.25f, // -0.25f,-0.25f,0.25f, // 0.25f,0.25f,-0.25f, // -0.25f,0.25f,-0.25f, // 0.25f,-0.25f,-0.25f, // -0.25f,-0.25f,-0.25f, // }; // uint[] polygons = new uint[] // { // 4,0,2,6,4, // 4,1,0,4,5, // 4,0,1,3,2, // 4,3,1,5,7, // 4,2,3,7,6, // 4,5,4,6,7, // }; // float* nativePlanes = (float*)Ode.dAlloc( (uint)( sizeof( float ) * planes.Length ) ); // for( int n = 0; n < planes.Length; n++ ) // nativePlanes[ n ] = planes[ n ]; // uint planeCount = 6; // float* nativePoints = (float*)Ode.dAlloc( (uint)( sizeof( float ) * points.Length ) ); // for( int n = 0; n < points.Length; n++ ) // nativePoints[ n ] = points[ n ]; // uint pointCount = 8; // uint* nativePolygons = (uint*)Ode.dAlloc( (uint)( sizeof( uint ) * polygons.Length ) ); // for( int n = 0; n < polygons.Length; n++ ) // nativePolygons[ n ] = polygons[ n ]; // //ODEPhysicsWorld.MeshGeometryODEData data; // //if( geometry.UserData == null ) // //{ // // data = new ODEPhysicsWorld.MeshGeometryODEData(); // //} // geomData.geomID = Ode.dCreateConvex( geomData.spaceID, nativePlanes, // planeCount, nativePoints, pointCount, nativePolygons ); //} } break; } //add geom data to list tempGeomDatasAsList[nShape] = geomData; geomData.shape = shape; geomData.odeBody = (ODEBody)shape.Body; // Use ODE's geom transform object. if (!identityTransform) { geomData.transformID = Ode.dCreateGeomTransform(bodySpaceID); } //set geom to body if (!Static) { if (geomData.transformID == dGeomID.Zero) { Ode.dGeomSetBody(geomData.geomID, bodyID); } else { Ode.dGeomSetBody(geomData.transformID, bodyID); } } if (geomData.transformID != dGeomID.Zero) { // Setup geom transform. Ode.dGeomTransformSetGeom(geomData.transformID, geomData.geomID); Ode.dQuaternion odeQuat; Convert.ToODE(shape.Rotation, out odeQuat); Ode.dGeomSetQuaternion(geomData.geomID, ref odeQuat); Ode.dGeomSetPosition(geomData.geomID, shape.Position.X, shape.Position.Y, shape.Position.Z); } // Set the GeomData reference for later use (e.g. in collision handling). geomData.shapeDictionaryIndex = scene.shapesDictionary.Add(geomData); dGeomID geomID = geomData.transformID != dGeomID.Zero ? geomData.transformID : geomData.geomID; Ode.CreateShapeData(geomID, bodyData, geomData.shapeDictionaryIndex, shape.ShapeType == Shape.Type.Mesh, shape.ContactGroup, shape.Hardness, shape.Restitution, shape.DynamicFriction, shape.StaticFriction); //shape pair flags Dictionary <Shape, ShapePairFlags> list = shape._GetShapePairFlags(); if (list != null) { foreach (KeyValuePair <Shape, ShapePairFlags> pair in list) { Shape otherShape = pair.Key; ShapePairFlags flags = pair.Value; if ((flags & ShapePairFlags.DisableContacts) != 0) { ODEBody otherBody = (ODEBody)otherShape.Body; GeomData otherGeomData = otherBody.GetGeomDataByShape(otherShape); if (otherGeomData != null) { dGeomID otherGeomID = (otherGeomData.transformID != dGeomID.Zero) ? otherGeomData.transformID : otherGeomData.geomID; Ode.SetShapePairDisableContacts(geomID, otherGeomID, true); } } } } } geomDatas = tempGeomDatasAsList.ToArray(); tempGeomDatasAsList.Clear(); if (Static) { UpdateStaticBodyGeomsTransform(); } }
unsafe void DeformationMeshParallel() { Vertex[] vertices = new Vertex[vertex_count]; ushort[] indices = new ushort[index_count]; mesh.SubMeshes[0].VertexData.GetSomeGeometry(ref changeable_vertex_pos, ref changeable_vertex_norm); if (first_init_mesh == false) { /*for (int i = 0; i < vertex_count; i++) * { * Vertex vertex = new Vertex(); * vertex.position = original_vertex_pos[i]; * vertex.normal = original_vertex_norm[i]; * vertex.texCoord = original_vertex_tc[i]; * vertices[i] = vertex; * } * for (int i = 0; i < index_count; i++) * { * indices[i] = (ushort)(original_vertex_ind[i]); * }*/ ParallelLoopResult parallel_result = Parallel.For(0, vertex_count, i => { Vertex vertex = new Vertex(); vertex.position = original_vertex_pos[i]; vertex.normal = original_vertex_norm[i]; vertex.texCoord = original_vertex_tc[i]; vertices[i] = vertex; }); if (parallel_result.IsCompleted) { for (int i = 0; i < index_count; i++) { indices[i] = (ushort)(original_vertex_ind[i]); } } SubMesh sub_mesh = mesh.SubMeshes[0]; { HardwareVertexBuffer vertex_buffer = sub_mesh.VertexData.VertexBufferBinding.GetBuffer(0); IntPtr buffer = vertex_buffer.Lock(HardwareBuffer.LockOptions.Discard); fixed(Vertex *pvertices = vertices) { NativeUtils.CopyMemory(buffer, (IntPtr)pvertices, vertices.Length * sizeof(Vertex)); } vertex_buffer.Unlock(); } { HardwareIndexBuffer index_buffer = sub_mesh.IndexData.IndexBuffer; IntPtr buffer = index_buffer.Lock(HardwareBuffer.LockOptions.Discard); fixed(ushort *pindices = indices) { NativeUtils.CopyMemory(buffer, (IntPtr)pindices, indices.Length * sizeof(ushort)); } index_buffer.Unlock(); } first_init_mesh = true; } else { if (hit_other != null) { ParallelLoopResult parallel_result = Parallel.For(0, vertex_count, i => { Vertex vertex = new Vertex(); Vec3 p = ((original_vertex_pos[i] * attached_mesh.ScaleOffset) * Rotation) + (Position + attached_mesh.PositionOffset); Vec3 pp = hit_pos; Sphere sp = new Sphere(pp, Type.CONF.DeformationRadius); Vec3 nvec = Vec3.Zero; Vec3 nnorm = Vec3.Zero; if (sp.IsContainsPoint(p)) { Ray ray = new Ray(p, changeable_vertex_norm[i] * .01f); if (!Single.IsNaN(ray.Direction.X) && !Single.IsNaN(ray.Origin.X)) { RayCastResult[] piercingResult = PhysicsWorld.Instance.RayCastPiercing( ray, (int)ContactGroup.CastOnlyDynamic);/*(int)ContactGroup.CastOnlyContact);*/ Vec3 collision_pos = Vec3.Zero; Vec3 collision_nor = Vec3.Zero; bool collision = false; foreach (RayCastResult result in piercingResult) { if (Array.IndexOf(PhysicsModel.Bodies, result.Shape.Body) != -1) { continue; } collision = true; collision_pos = result.Position; collision_nor = result.Normal; break; } if (collision) { float old_x = 0, old_y = 0, old_z = 0, new_x = 0, new_y = 0, new_z = 0; float deformation = 0, force = 0, max_deformation = Type.CONF.MaxStrengthDeformation, mass = 0, vel = 0; mass = hit_other.Body.Mass; vel = hit_other.Body.LastStepLinearVelocity.Length(); force = (((hit_this.Body.Mass * hit_this.Body.LastStepLinearVelocity.Length()) + (mass * vel)) / hit_this.Body.Mass) / 100.0f; if (force > max_deformation) { deformation = max_deformation; } else { deformation = force; } //Deform X if (changeable_vertex_pos[i].X > 0) { old_x = original_vertex_pos[i].X - deformation; if (old_x < changeable_vertex_pos[i].X) { new_x = old_x; } else { new_x = changeable_vertex_pos[i].X; } } else { old_x = original_vertex_pos[i].X + deformation; if (old_x > changeable_vertex_pos[i].X) { new_x = old_x; } else { new_x = changeable_vertex_pos[i].X; } } //Deform Y if (changeable_vertex_pos[i].Y > 0) { old_y = original_vertex_pos[i].Y - deformation; if (old_y < changeable_vertex_pos[i].Y) { new_y = old_y; } else { new_y = changeable_vertex_pos[i].Y; } } else { old_y = original_vertex_pos[i].Y + deformation; if (old_y > changeable_vertex_pos[i].Y) { new_y = old_y; } else { new_y = changeable_vertex_pos[i].Y; } } //Deform Z if (changeable_vertex_pos[i].Z > 0) { old_z = original_vertex_pos[i].Z - deformation; if (old_z < changeable_vertex_pos[i].Z) { new_z = old_z; } else { new_z = changeable_vertex_pos[i].Z; } } else { old_z = original_vertex_pos[i].Z + deformation; if (old_z > changeable_vertex_pos[i].Z) { new_z = old_z; } else { new_z = changeable_vertex_pos[i].Z; } } nvec = new Vec3(new_x, new_y, new_z); nnorm = -collision_nor; } else { nvec = changeable_vertex_pos[i]; nnorm = changeable_vertex_norm[i]; } } } else { nvec = changeable_vertex_pos[i]; nnorm = changeable_vertex_norm[i]; } vertex.position = nvec; vertex.normal = nnorm; vertex.texCoord = original_vertex_tc[i]; vertices[i] = vertex; }); if (parallel_result.IsCompleted) { for (int i = 0; i < index_count; i++) { indices[i] = (ushort)(original_vertex_ind[i]); } SubMesh sub_mesh = mesh.SubMeshes[0]; { HardwareVertexBuffer vertex_buffer = sub_mesh.VertexData.VertexBufferBinding.GetBuffer(0); IntPtr buffer = vertex_buffer.Lock(HardwareBuffer.LockOptions.Discard); fixed(Vertex *pvertices = vertices) { NativeUtils.CopyMemory(buffer, (IntPtr)pvertices, vertices.Length * sizeof(Vertex)); } vertex_buffer.Unlock(); } { HardwareIndexBuffer index_buffer = sub_mesh.IndexData.IndexBuffer; IntPtr buffer = index_buffer.Lock(HardwareBuffer.LockOptions.Discard); fixed(ushort *pindices = indices) { NativeUtils.CopyMemory(buffer, (IntPtr)pindices, indices.Length * sizeof(ushort)); } index_buffer.Unlock(); } } } hit_other = null; } }