// Make a class that will be responsible for managind the buffer lists public void InnerMakeMeshDraw(IList <Mesh> meshes, IList <Material> materials) { for (int i = 0; i < meshes.Count; i++) { _mesh_id2mesh_draw[i] = new MeshDraw(meshes[i], materials); } }
// First pass: calculate the transofmration matrix for each vertex // here we must associate a matrix with each bone (maybe with each vertex_id??) // then we multiply the current_bone matrix with the one we had before // (perhaps it was identity, perhaps it was already some matrix (if // the bone influences many vertices) ) // then we store this multiplied matrix. // in the render function we get a vertex_id, so we can find the matrix to apply // to the vertex, then we send the vertex to OpenGL public void RecursiveCalculateVertexTransform(Node nd, Matrix4x4 current) { Matrix4x4 current_node = current * nd.Transform; foreach (int mesh_id in nd.MeshIndices) { Mesh cur_mesh = _scene._inner.Meshes[mesh_id]; MeshDraw mesh_draw = _mesh_id2mesh_draw[mesh_id]; foreach (Bone bone in cur_mesh.Bones) { // a bone transform is more than by what we need to trasnform the model BoneNode armature_node = _scene.GetBoneNode(bone.Name); Matrix4x4 bone_global_mat = armature_node.GlobTrans; /// bind tells the original delta in global coord, so we can find current delta Matrix4x4 bind = bone.OffsetMatrix; Matrix4x4 delta_roto = bind * bone_global_mat; Matrix4x4 current_bone = delta_roto * current_node; foreach (var pair in bone.VertexWeights) { // Can apply bone weight here mesh_draw._vertex_id2matrix[pair.VertexID] = current_bone; } } } foreach (Node child in nd.Children) { RecursiveCalculateVertexTransform(child, current_node); } }
// Render the scene. // each vertex at most one bone policy private void RecursiveRenderSystemDrawing(Node nd) { foreach (int mesh_id in nd.MeshIndices) { MeshDraw mesh_draw = _mesh_id2mesh_draw[mesh_id]; mesh_draw.RenderVBO(); } foreach (Node child in nd.Children) { RecursiveRenderSystemDrawing(child); } }
// Second pass: transform all vertices in a mesh according to bone // just apply the previously caluclated matrix public void RecursiveTransformVertices(Node nd) { foreach (int mesh_id in nd.MeshIndices) { MeshDraw mesh_draw = _mesh_id2mesh_draw[mesh_id]; // map data from VBO IntPtr data; int qty_vertices; mesh_draw.BeginModifyVertexData(out data, out qty_vertices); // iterate over inital vertex positions Mesh cur_mesh = _scene._inner.Meshes[mesh_id]; MeshBounds aabb = _extra_geometry._mesh_id2box[mesh_id]; // go over every vertex in the mesh unsafe { // array of floats: X,Y,Z..... int sz = 3; // size of step float *coords = (float *)data; for (int vertex_id = 0; vertex_id < qty_vertices; vertex_id++) { Matrix4x4 matrix_with_offset = mesh_draw._vertex_id2matrix[vertex_id]; // get the initial position of vertex when scene was loaded Vector3D vertex_default = cur_mesh.Vertices[vertex_id]; Vector3D vertex; Entity.TransformPositionAssimp(ref vertex_default, ref matrix_with_offset, out vertex); // write new coords back into array coords[vertex_id * sz + 0] = vertex.X; coords[vertex_id * sz + 1] = vertex.Y; coords[vertex_id * sz + 2] = vertex.Z; } } mesh_draw.EndModifyVertexData(); foreach (Node child in nd.Children) { RecursiveTransformVertices(child); } } }