/// <summary> /// Method for generating mesh Face from a heightmap /// </summary> /// <param name="zMap">Two dimension array of floats containing height information</param> /// <param name="xBegin">Starting value for X</param> /// <param name="xEnd">Max value for X</param> /// <param name="yBegin">Starting value for Y</param> /// <param name="yEnd">Max value of Y</param> /// <returns></returns> public OMVR.Face TerrainMesh(float[,] zMap, float xBegin, float xEnd, float yBegin, float yEnd) { PrimMesher.SculptMesh newMesh = new PrimMesher.SculptMesh(zMap, xBegin, xEnd, yBegin, yEnd, true); OMVR.Face terrain = new OMVR.Face(); int faceVertices = newMesh.coords.Count; terrain.Vertices = new List <Vertex>(faceVertices); terrain.Indices = new List <ushort>(newMesh.faces.Count * 3); for (int j = 0; j < faceVertices; j++) { var vert = new OMVR.Vertex(); vert.Position = new Vector3(newMesh.coords[j].X, newMesh.coords[j].Y, newMesh.coords[j].Z); vert.Normal = new Vector3(newMesh.normals[j].X, newMesh.normals[j].Y, newMesh.normals[j].Z); vert.TexCoord = new Vector2(newMesh.uvs[j].U, newMesh.uvs[j].V); terrain.Vertices.Add(vert); } for (int j = 0; j < newMesh.faces.Count; j++) { terrain.Indices.Add((ushort)newMesh.faces[j].v1); terrain.Indices.Add((ushort)newMesh.faces[j].v2); terrain.Indices.Add((ushort)newMesh.faces[j].v3); } return(terrain); }
/// <summary> /// Method for generating mesh Face from a heightmap /// </summary> /// <param name="zMap">Two dimension array of floats containing height information</param> /// <param name="xBegin">Starting value for X</param> /// <param name="xEnd">Max value for X</param> /// <param name="yBegin">Starting value for Y</param> /// <param name="yEnd">Max value of Y</param> /// <returns></returns> public OMVR.Face TerrainMesh(float[,] zMap, float xBegin, float xEnd, float yBegin, float yEnd) { PrimMesher.SculptMesh newMesh = new PrimMesher.SculptMesh(zMap, xBegin, xEnd, yBegin, yEnd, true); OMVR.Face terrain = new OMVR.Face(); int faceVertices = newMesh.coords.Count; terrain.Vertices = new List<Vertex>(faceVertices); terrain.Indices = new List<ushort>(newMesh.faces.Count * 3); for (int j = 0; j < faceVertices; j++) { var vert = new OMVR.Vertex(); vert.Position = new Vector3(newMesh.coords[j].X, newMesh.coords[j].Y, newMesh.coords[j].Z); vert.Normal = new Vector3(newMesh.normals[j].X, newMesh.normals[j].Y, newMesh.normals[j].Z); vert.TexCoord = new Vector2(newMesh.uvs[j].U, newMesh.uvs[j].V); terrain.Vertices.Add(vert); } for (int j = 0; j < newMesh.faces.Count; j++) { terrain.Indices.Add((ushort)newMesh.faces[j].v1); terrain.Indices.Add((ushort)newMesh.faces[j].v2); terrain.Indices.Add((ushort)newMesh.faces[j].v3); } return terrain; }
/// <summary> /// Create a sculpty faceted mesh. The actual scuplt texture is fetched and passed to this /// routine since all the context for finding teh texture is elsewhere. /// </summary> /// <returns>The faceted mesh or null if can't do it</returns> public OMVR.FacetedMesh GenerateFacetedSculptMesh(OMV.Primitive prim, System.Drawing.Bitmap scupltTexture, OMVR.DetailLevel lod) { PrimMesher.SculptMesh.SculptType smSculptType; switch (prim.Sculpt.Type) { case OpenMetaverse.SculptType.Cylinder: smSculptType = PrimMesher.SculptMesh.SculptType.cylinder; break; case OpenMetaverse.SculptType.Plane: smSculptType = PrimMesher.SculptMesh.SculptType.plane; break; case OpenMetaverse.SculptType.Sphere: smSculptType = PrimMesher.SculptMesh.SculptType.sphere; break; case OpenMetaverse.SculptType.Torus: smSculptType = PrimMesher.SculptMesh.SculptType.torus; break; default: smSculptType = PrimMesher.SculptMesh.SculptType.plane; break; } // The lod for sculpties is the resolution of the texture passed. // The first guess is 1:1 then lower resolutions after that // int mesherLod = (int)Math.Sqrt(scupltTexture.Width * scupltTexture.Height); int mesherLod = 32; // number used in Idealist viewer switch (lod) { case OMVR.DetailLevel.Highest: break; case OMVR.DetailLevel.High: break; case OMVR.DetailLevel.Medium: mesherLod /= 2; break; case OMVR.DetailLevel.Low: mesherLod /= 4; break; } PrimMesher.SculptMesh newMesh = new PrimMesher.SculptMesh(scupltTexture, smSculptType, mesherLod, true, prim.Sculpt.Mirror, prim.Sculpt.Invert); int numPrimFaces = 1; // a scuplty has only one face // copy the vertex information into OMVR.IRendering structures OMVR.FacetedMesh omvrmesh = new OMVR.FacetedMesh(); omvrmesh.Faces = new List<OMVR.Face>(); omvrmesh.Prim = prim; omvrmesh.Profile = new OMVR.Profile(); omvrmesh.Profile.Faces = new List<OMVR.ProfileFace>(); omvrmesh.Profile.Positions = new List<OMV.Vector3>(); omvrmesh.Path = new OMVR.Path(); omvrmesh.Path.Points = new List<OMVR.PathPoint>(); Dictionary<OMVR.Vertex, int> vertexAccount = new Dictionary<OMVR.Vertex, int>(); for (int ii = 0; ii < numPrimFaces; ii++) { vertexAccount.Clear(); OMVR.Face oface = new OMVR.Face(); oface.Vertices = new List<OMVR.Vertex>(); oface.Indices = new List<ushort>(); oface.TextureFace = prim.Textures.GetFace((uint)ii); int faceVertices = newMesh.coords.Count; OMVR.Vertex vert; for (int j = 0; j < faceVertices; j++) { vert = new OMVR.Vertex(); vert.Position = new Vector3(newMesh.coords[j].X, newMesh.coords[j].Y, newMesh.coords[j].Z); vert.Normal = new Vector3(newMesh.normals[j].X, newMesh.normals[j].Y, newMesh.normals[j].Z); vert.TexCoord = new Vector2(newMesh.uvs[j].U, newMesh.uvs[j].V); oface.Vertices.Add(vert); } for (int j = 0; j < newMesh.faces.Count; j++) { oface.Indices.Add((ushort)newMesh.faces[j].v1); oface.Indices.Add((ushort)newMesh.faces[j].v2); oface.Indices.Add((ushort)newMesh.faces[j].v3); } if (faceVertices > 0) { oface.TextureFace = prim.Textures.FaceTextures[ii]; if (oface.TextureFace == null) { oface.TextureFace = prim.Textures.DefaultTexture; } oface.ID = ii; omvrmesh.Faces.Add(oface); } } return omvrmesh; }
/// <summary> /// Create a sculpty faceted mesh. The actual scuplt texture is fetched and passed to this /// routine since all the context for finding teh texture is elsewhere. /// </summary> /// <returns>The faceted mesh or null if can't do it</returns> public OMVR.FacetedMesh GenerateFacetedSculptMesh(OMV.Primitive prim, System.Drawing.Bitmap scupltTexture, OMVR.DetailLevel lod) { byte sculptType = (byte)prim.Sculpt.Type; bool mirror = ((sculptType & 128) != 0); bool invert = ((sculptType & 64) != 0); // mirror = false; // TODO: libomv doesn't support these and letting them flop around causes problems // invert = false; OMV.SculptType omSculptType = (OMV.SculptType)(sculptType & 0x07); PrimMesher.SculptMesh.SculptType smSculptType; switch (omSculptType) { case OpenMetaverse.SculptType.Cylinder: smSculptType = PrimMesher.SculptMesh.SculptType.cylinder; break; case OpenMetaverse.SculptType.Plane: smSculptType = PrimMesher.SculptMesh.SculptType.plane; break; case OpenMetaverse.SculptType.Sphere: smSculptType = PrimMesher.SculptMesh.SculptType.sphere; break; case OpenMetaverse.SculptType.Torus: smSculptType = PrimMesher.SculptMesh.SculptType.torus; break; default: smSculptType = PrimMesher.SculptMesh.SculptType.plane; break; } // The lod for sculpties is the resolution of the texture passed. // The first guess is 1:1 then lower resolutions after that // int mesherLod = (int)Math.Sqrt(scupltTexture.Width * scupltTexture.Height); int mesherLod = 32; // number used in Idealist viewer switch (lod) { case OMVR.DetailLevel.Highest: break; case OMVR.DetailLevel.High: break; case OMVR.DetailLevel.Medium: mesherLod /= 2; break; case OMVR.DetailLevel.Low: mesherLod /= 4; break; } PrimMesher.SculptMesh newMesh = new PrimMesher.SculptMesh(scupltTexture, smSculptType, mesherLod, true, mirror, invert); int numPrimFaces = 1; // a scuplty has only one face // copy the vertex information into OMVR.IRendering structures OMVR.FacetedMesh omvrmesh = new OMVR.FacetedMesh(); omvrmesh.Faces = new List<OMVR.Face>(); omvrmesh.Prim = prim; omvrmesh.Profile = new OMVR.Profile(); omvrmesh.Profile.Faces = new List<OMVR.ProfileFace>(); omvrmesh.Profile.Positions = new List<OMV.Vector3>(); omvrmesh.Path = new OMVR.Path(); omvrmesh.Path.Points = new List<OMVR.PathPoint>(); for (int ii = 0; ii < numPrimFaces; ii++) { OMVR.Face oface = new OMVR.Face(); oface.Vertices = new List<OMVR.Vertex>(); oface.Indices = new List<ushort>(); oface.TextureFace = prim.Textures.GetFace((uint)ii); int faceVertices = 0; foreach (PrimMesher.ViewerFace vface in newMesh.viewerFaces) { OMVR.Vertex vert = new OMVR.Vertex(); vert.Position = new OMV.Vector3(vface.v1.X, vface.v1.Y, vface.v1.Z); vert.TexCoord = new OMV.Vector2(vface.uv1.U, 1.0f - vface.uv1.V); vert.Normal = new OMV.Vector3(vface.n1.X, vface.n1.Y, vface.n1.Z); oface.Vertices.Add(vert); vert = new OMVR.Vertex(); vert.Position = new OMV.Vector3(vface.v2.X, vface.v2.Y, vface.v2.Z); vert.TexCoord = new OMV.Vector2(vface.uv2.U, 1.0f - vface.uv2.V); vert.Normal = new OMV.Vector3(vface.n2.X, vface.n2.Y, vface.n2.Z); oface.Vertices.Add(vert); vert = new OMVR.Vertex(); vert.Position = new OMV.Vector3(vface.v3.X, vface.v3.Y, vface.v3.Z); vert.TexCoord = new OMV.Vector2(vface.uv3.U, 1.0f - vface.uv3.V); vert.Normal = new OMV.Vector3(vface.n3.X, vface.n3.Y, vface.n3.Z); oface.Vertices.Add(vert); oface.Indices.Add((ushort)(faceVertices * 3 + 0)); oface.Indices.Add((ushort)(faceVertices * 3 + 1)); oface.Indices.Add((ushort)(faceVertices * 3 + 2)); faceVertices++; } if (faceVertices > 0) { oface.TextureFace = prim.Textures.FaceTextures[ii]; if (oface.TextureFace == null) { oface.TextureFace = prim.Textures.DefaultTexture; } oface.ID = ii; omvrmesh.Faces.Add(oface); } } return omvrmesh; }
/// <summary> /// Create a sculpty faceted mesh. The actual scuplt texture is fetched and passed to this /// routine since all the context for finding teh texture is elsewhere. /// </summary> /// <param name="scupltTexture"></param> /// <param name="prim"></param> /// <param name="lod"></param> /// <returns>the faceted mesh or null if can't do it</returns> public OMVR.FacetedMesh GenerateSculptMesh(System.Drawing.Bitmap scupltTexture, OMV.Primitive prim, OMVR.DetailLevel lod) { try { byte sculptType = (byte)prim.Sculpt.Type; bool mirror = ((sculptType & 128) != 0); bool invert = ((sculptType & 64) != 0); // bool mirror = false; // TODO: libomv doesn't support these and letting them flop around causes problems // bool invert = false; OMV.SculptType omSculptType = (OMV.SculptType)(sculptType & 0x07); PrimMesher.SculptMesh.SculptType smSculptType; switch (omSculptType) { case OpenMetaverse.SculptType.Cylinder: smSculptType = PrimMesher.SculptMesh.SculptType.cylinder; break; case OpenMetaverse.SculptType.Plane: smSculptType = PrimMesher.SculptMesh.SculptType.plane; break; case OpenMetaverse.SculptType.Sphere: smSculptType = PrimMesher.SculptMesh.SculptType.sphere; break; case OpenMetaverse.SculptType.Torus: smSculptType = PrimMesher.SculptMesh.SculptType.torus; break; default: smSculptType = PrimMesher.SculptMesh.SculptType.plane; break; } // The lod for sculpties is the resolution of the texture passed. // The first guess is 1:1 then lower resolutions after that // int mesherLod = (int)Math.Sqrt(scupltTexture.Width * scupltTexture.Height); int mesherLod = 32; // number used in Idealist viewer switch (lod) { case OMVR.DetailLevel.Highest: break; case OMVR.DetailLevel.High: break; case OMVR.DetailLevel.Medium: mesherLod /= 2; break; case OMVR.DetailLevel.Low: mesherLod /= 4; break; } PrimMesher.SculptMesh newMesh = new PrimMesher.SculptMesh(scupltTexture, smSculptType, mesherLod, true, mirror, invert); if (ShouldScaleMesh) { newMesh.Scale(prim.Scale.X, prim.Scale.Y, prim.Scale.Z); } int numPrimFaces = 1; // a scuplty has only one face return GenerateIRendererMesh(numPrimFaces, prim, newMesh.viewerFaces); } catch { // don't know why we're here but tell the caller nothing was meshed return null; } }
/// <summary> /// Create a sculpty faceted mesh. The actual scuplt texture is fetched and passed to this /// routine since all the context for finding teh texture is elsewhere. /// </summary> /// <returns>The faceted mesh or null if can't do it</returns> public OMVR.FacetedMesh GenerateFacetedSculptMesh(OMV.Primitive prim, System.Drawing.Bitmap scupltTexture, OMVR.DetailLevel lod) { PrimMesher.SculptMesh.SculptType smSculptType; switch (prim.Sculpt.Type) { case OpenMetaverse.SculptType.Cylinder: smSculptType = PrimMesher.SculptMesh.SculptType.cylinder; break; case OpenMetaverse.SculptType.Plane: smSculptType = PrimMesher.SculptMesh.SculptType.plane; break; case OpenMetaverse.SculptType.Sphere: smSculptType = PrimMesher.SculptMesh.SculptType.sphere; break; case OpenMetaverse.SculptType.Torus: smSculptType = PrimMesher.SculptMesh.SculptType.torus; break; default: smSculptType = PrimMesher.SculptMesh.SculptType.plane; break; } // The lod for sculpties is the resolution of the texture passed. // The first guess is 1:1 then lower resolutions after that // int mesherLod = (int)Math.Sqrt(scupltTexture.Width * scupltTexture.Height); int mesherLod = 32; // number used in Idealist viewer switch (lod) { case OMVR.DetailLevel.Highest: break; case OMVR.DetailLevel.High: break; case OMVR.DetailLevel.Medium: mesherLod /= 2; break; case OMVR.DetailLevel.Low: mesherLod /= 4; break; } PrimMesher.SculptMesh newMesh = new PrimMesher.SculptMesh(scupltTexture, smSculptType, mesherLod, true, prim.Sculpt.Mirror, prim.Sculpt.Invert); int numPrimFaces = 1; // a scuplty has only one face // copy the vertex information into OMVR.IRendering structures OMVR.FacetedMesh omvrmesh = new OMVR.FacetedMesh(); omvrmesh.Faces = new List <OMVR.Face>(); omvrmesh.Prim = prim; omvrmesh.Profile = new OMVR.Profile(); omvrmesh.Profile.Faces = new List <OMVR.ProfileFace>(); omvrmesh.Profile.Positions = new List <OMV.Vector3>(); omvrmesh.Path = new OMVR.Path(); omvrmesh.Path.Points = new List <OMVR.PathPoint>(); Dictionary <OMVR.Vertex, int> vertexAccount = new Dictionary <OMVR.Vertex, int>(); for (int ii = 0; ii < numPrimFaces; ii++) { vertexAccount.Clear(); OMVR.Face oface = new OMVR.Face(); oface.Vertices = new List <OMVR.Vertex>(); oface.Indices = new List <ushort>(); oface.TextureFace = prim.Textures.GetFace((uint)ii); int faceVertices = newMesh.coords.Count; OMVR.Vertex vert; for (int j = 0; j < faceVertices; j++) { vert = new OMVR.Vertex(); vert.Position = new Vector3(newMesh.coords[j].X, newMesh.coords[j].Y, newMesh.coords[j].Z); vert.Normal = new Vector3(newMesh.normals[j].X, newMesh.normals[j].Y, newMesh.normals[j].Z); vert.TexCoord = new Vector2(newMesh.uvs[j].U, newMesh.uvs[j].V); oface.Vertices.Add(vert); } for (int j = 0; j < newMesh.faces.Count; j++) { oface.Indices.Add((ushort)newMesh.faces[j].v1); oface.Indices.Add((ushort)newMesh.faces[j].v2); oface.Indices.Add((ushort)newMesh.faces[j].v3); } if (faceVertices > 0) { oface.TextureFace = prim.Textures.FaceTextures[ii]; if (oface.TextureFace == null) { oface.TextureFace = prim.Textures.DefaultTexture; } oface.ID = ii; omvrmesh.Faces.Add(oface); } } return(omvrmesh); }
/// <summary> /// Create a sculpty faceted mesh. The actual scuplt texture is fetched and passed to this /// routine since all the context for finding teh texture is elsewhere. /// </summary> /// <param name="scupltTexture"></param> /// <param name="prim"></param> /// <param name="lod"></param> /// <returns>the faceted mesh or null if can't do it</returns> public OMVR.FacetedMesh GenerateSculptMesh(System.Drawing.Bitmap scupltTexture, OMV.Primitive prim, OMVR.DetailLevel lod) { try { byte sculptType = (byte)prim.Sculpt.Type; bool mirror = ((sculptType & 128) != 0); bool invert = ((sculptType & 64) != 0); // bool mirror = false; // TODO: libomv doesn't support these and letting them flop around causes problems // bool invert = false; OMV.SculptType omSculptType = (OMV.SculptType)(sculptType & 0x07); PrimMesher.SculptMesh.SculptType smSculptType; switch (omSculptType) { case OpenMetaverse.SculptType.Cylinder: smSculptType = PrimMesher.SculptMesh.SculptType.cylinder; break; case OpenMetaverse.SculptType.Plane: smSculptType = PrimMesher.SculptMesh.SculptType.plane; break; case OpenMetaverse.SculptType.Sphere: smSculptType = PrimMesher.SculptMesh.SculptType.sphere; break; case OpenMetaverse.SculptType.Torus: smSculptType = PrimMesher.SculptMesh.SculptType.torus; break; default: smSculptType = PrimMesher.SculptMesh.SculptType.plane; break; } // The lod for sculpties is the resolution of the texture passed. // The first guess is 1:1 then lower resolutions after that // int mesherLod = (int)Math.Sqrt(scupltTexture.Width * scupltTexture.Height); int mesherLod = 32; // number used in Idealist viewer switch (lod) { case OMVR.DetailLevel.Highest: break; case OMVR.DetailLevel.High: break; case OMVR.DetailLevel.Medium: mesherLod /= 2; break; case OMVR.DetailLevel.Low: mesherLod /= 4; break; } PrimMesher.SculptMesh newMesh = new PrimMesher.SculptMesh(scupltTexture, smSculptType, mesherLod, true, mirror, invert); if (ShouldScaleMesh) { newMesh.Scale(prim.Scale.X, prim.Scale.Y, prim.Scale.Z); } int numPrimFaces = 1; // a scuplty has only one face return(GenerateIRendererMesh(numPrimFaces, prim, newMesh.viewerFaces)); } catch { // don't know why we're here but tell the caller nothing was meshed return(null); } }
/// <summary> /// Create a sculpty faceted mesh. The actual scuplt texture is fetched and passed to this /// routine since all the context for finding teh texture is elsewhere. /// </summary> /// <returns>The faceted mesh or null if can't do it</returns> public OMVR.FacetedMesh GenerateFacetedSculptMesh(OMV.Primitive prim, System.Drawing.Bitmap scupltTexture, OMVR.DetailLevel lod) { byte sculptType = (byte)prim.Sculpt.Type; bool mirror = ((sculptType & 128) != 0); bool invert = ((sculptType & 64) != 0); // mirror = false; // TODO: libomv doesn't support these and letting them flop around causes problems // invert = false; OMV.SculptType omSculptType = (OMV.SculptType)(sculptType & 0x07); PrimMesher.SculptMesh.SculptType smSculptType; switch (omSculptType) { case OpenMetaverse.SculptType.Cylinder: smSculptType = PrimMesher.SculptMesh.SculptType.cylinder; break; case OpenMetaverse.SculptType.Plane: smSculptType = PrimMesher.SculptMesh.SculptType.plane; break; case OpenMetaverse.SculptType.Sphere: smSculptType = PrimMesher.SculptMesh.SculptType.sphere; break; case OpenMetaverse.SculptType.Torus: smSculptType = PrimMesher.SculptMesh.SculptType.torus; break; default: smSculptType = PrimMesher.SculptMesh.SculptType.plane; break; } // The lod for sculpties is the resolution of the texture passed. // The first guess is 1:1 then lower resolutions after that // int mesherLod = (int)Math.Sqrt(scupltTexture.Width * scupltTexture.Height); int mesherLod = 32; // number used in Idealist viewer switch (lod) { case OMVR.DetailLevel.Highest: break; case OMVR.DetailLevel.High: break; case OMVR.DetailLevel.Medium: mesherLod /= 2; break; case OMVR.DetailLevel.Low: mesherLod /= 4; break; } PrimMesher.SculptMesh newMesh = new PrimMesher.SculptMesh(scupltTexture, smSculptType, mesherLod, true, mirror, invert); int numPrimFaces = 1; // a scuplty has only one face // copy the vertex information into OMVR.IRendering structures OMVR.FacetedMesh omvrmesh = new OMVR.FacetedMesh(); omvrmesh.Faces = new List <OMVR.Face>(); omvrmesh.Prim = prim; omvrmesh.Profile = new OMVR.Profile(); omvrmesh.Profile.Faces = new List <OMVR.ProfileFace>(); omvrmesh.Profile.Positions = new List <OMV.Vector3>(); omvrmesh.Path = new OMVR.Path(); omvrmesh.Path.Points = new List <OMVR.PathPoint>(); for (int ii = 0; ii < numPrimFaces; ii++) { OMVR.Face oface = new OMVR.Face(); oface.Vertices = new List <OMVR.Vertex>(); oface.Indices = new List <ushort>(); oface.TextureFace = prim.Textures.GetFace((uint)ii); int faceVertices = 0; foreach (PrimMesher.ViewerFace vface in newMesh.viewerFaces) { OMVR.Vertex vert = new OMVR.Vertex(); vert.Position = new OMV.Vector3(vface.v1.X, vface.v1.Y, vface.v1.Z); vert.TexCoord = new OMV.Vector2(vface.uv1.U, 1.0f - vface.uv1.V); vert.Normal = new OMV.Vector3(vface.n1.X, vface.n1.Y, vface.n1.Z); oface.Vertices.Add(vert); vert = new OMVR.Vertex(); vert.Position = new OMV.Vector3(vface.v2.X, vface.v2.Y, vface.v2.Z); vert.TexCoord = new OMV.Vector2(vface.uv2.U, 1.0f - vface.uv2.V); vert.Normal = new OMV.Vector3(vface.n2.X, vface.n2.Y, vface.n2.Z); oface.Vertices.Add(vert); vert = new OMVR.Vertex(); vert.Position = new OMV.Vector3(vface.v3.X, vface.v3.Y, vface.v3.Z); vert.TexCoord = new OMV.Vector2(vface.uv3.U, 1.0f - vface.uv3.V); vert.Normal = new OMV.Vector3(vface.n3.X, vface.n3.Y, vface.n3.Z); oface.Vertices.Add(vert); oface.Indices.Add((ushort)(faceVertices * 3 + 0)); oface.Indices.Add((ushort)(faceVertices * 3 + 1)); oface.Indices.Add((ushort)(faceVertices * 3 + 2)); faceVertices++; } if (faceVertices > 0) { oface.TextureFace = prim.Textures.FaceTextures[ii]; if (oface.TextureFace == null) { oface.TextureFace = prim.Textures.DefaultTexture; } oface.ID = ii; omvrmesh.Faces.Add(oface); } } return(omvrmesh); }