public static void AddMeshTo3DS(Lib3dsFile res, PSKFile f, Matrix m) { Lib3dsMesh mesh = new Lib3dsMesh(); string name = "Box00" + res.meshes.Count.ToString(); mesh.name = name; mesh.matrix = Matrix2FA(Matrix.Identity); mesh.vertices = new List<Lib3dsVertex>(); foreach (PSKFile.PSKPoint p in f.psk.points) { Vector3 v = p.ToVector3(); v = Vector3.TransformCoordinate(v, m); mesh.vertices.Add(new Lib3dsVertex(v.X, -v.Y, v.Z)); } mesh.texcos = new List<Lib3dsTexturecoordinate>(); for (int i = 0; i < f.psk.points.Count; i++) foreach (PSKFile.PSKEdge e in f.psk.edges) if (e.index == i) mesh.texcos.Add(new Lib3dsTexturecoordinate(e.U, e.V)); mesh.faces = new List<Lib3dsFace>(); foreach (PSKFile.PSKFace face in f.psk.faces) { Lib3dsFace ff = new Lib3dsFace(); ff.flags = 6; ff.index = new ushort[3]; ff.index[0] = (ushort)f.psk.edges[face.v0].index; ff.index[1] = (ushort)f.psk.edges[face.v2].index; ff.index[2] = (ushort)f.psk.edges[face.v1].index; mesh.faces.Add(ff); } mesh.nfaces = (ushort)mesh.faces.Count; mesh.nvertices = (ushort)mesh.vertices.Count; mesh.map_type = Lib3dsMapType.LIB3DS_MAP_NONE; mesh.object_flags = 0; mesh.color = 128; res.meshes.Add(mesh); Lib3dsNode node = new Lib3dsMeshInstanceNode(); node.matrixNode = Matrix2FA(Matrix.Identity); node.parent = null; node.parent_id = 0xffff; node.hasNodeID = true; node.type = Lib3dsNodeType.LIB3DS_NODE_MESH_INSTANCE; node.flags = res.nodes[0].flags; node.node_id = (ushort)(res.meshes.Count() - 1); node.name = name; res.nodes.Add(node); }
// Calculates the vertex normals corresponding to the smoothing group // settings for each face of a mesh. // // \param mesh A pointer to the mesh to calculate the normals for. // \param normals A pointer to a buffer to store the calculated // normals. The buffer must have the size: // 3*3*sizeof(float)*mesh.nfaces. // // To allocate the normal buffer do for example the following: // \code // Lib3dsVector *normals = malloc(3*3*sizeof(float)*mesh.nfaces); // \endcode // // To access the normal of the i-th vertex of the j-th face do the // following: // \code // normals[3*j+i] // \endcode public static void lib3ds_mesh_calculate_vertex_normals(Lib3dsMesh mesh, float[][] normals) { if (mesh.nfaces == 0) { return; } Lib3dsFaces[] fl = new Lib3dsFaces[mesh.nvertices]; Lib3dsFaces[] fa = new Lib3dsFaces[3 * mesh.nfaces]; for (int i = 0; i < fa.Length; i++) { fa[i] = new Lib3dsFaces(); } for (int i = 0; i < mesh.nfaces; i++) { for (int j = 0; j < 3; j++) { Lib3dsFaces l = fa[3 * i + j]; float[] p = new float[3], q = new float[3], n = new float[3]; float len, weight; l.index = i; l.next = fl[mesh.faces[i].index[j]]; fl[mesh.faces[i].index[j]] = l; lib3ds_vector_sub(p, mesh.vertices[mesh.faces[i].index[j < 2?j + 1:0]], mesh.vertices[mesh.faces[i].index[j]]); lib3ds_vector_sub(q, mesh.vertices[mesh.faces[i].index[j > 0?j - 1:2]], mesh.vertices[mesh.faces[i].index[j]]); lib3ds_vector_cross(n, p, q); len = lib3ds_vector_length(n); if (len > 0) { weight = (float)Math.Atan2(len, lib3ds_vector_dot(p, q)); lib3ds_vector_scalar_mul(l.normal, n, weight / len); } else { lib3ds_vector_zero(l.normal); } } } for (int i = 0; i < mesh.nfaces; i++) { Lib3dsFace f = mesh.faces[i]; for (int j = 0; j < 3; j++) { float[] n = new float[3]; Lib3dsFaces p; Lib3dsFace pf; Debug.Assert(mesh.faces[i].index[j] < mesh.nvertices); if (f.smoothing_group != 0) { uint smoothing_group = f.smoothing_group; lib3ds_vector_zero(n); for (p = fl[mesh.faces[i].index[j]]; p != null; p = p.next) { pf = mesh.faces[p.index]; if ((pf.smoothing_group & f.smoothing_group) != 0) { smoothing_group |= pf.smoothing_group; } } for (p = fl[mesh.faces[i].index[j]]; p != null; p = p.next) { pf = mesh.faces[p.index]; if ((smoothing_group & pf.smoothing_group) != 0) { lib3ds_vector_add(n, n, p.normal); } } } else { lib3ds_vector_copy(n, fa[3 * i + j].normal); } lib3ds_vector_normalize(n); lib3ds_vector_copy(normals[3 * i + j], n); } } }