예제 #1
0
        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);
        }
예제 #3
0
        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 );
        }
예제 #4
0
        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();
            }
        }
예제 #5
0
        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;
            }
        }