Пример #1
0
        private static void TransformPlanarTexCoord(ref Vector2 texCoord, Vertex vertex, Vector3 center,
            Vector3 vec)
        {
            Vector3 binormal;
            float d = Vector3.Dot(vertex.Normal, Vector3.UnitX);
            if (d >= 0.5f || d <= -0.5f)
            {
                binormal = new Vector3(0f, 1f, 0f);

                if (vertex.Normal.X < 0f)
                {
                    binormal.X = -binormal.X;
                    binormal.Y = -binormal.Y;
                    binormal.Z = -binormal.Z;
                }
            }
            else
            {
                binormal = new Vector3(1f, 0f, 0f);

                if (vertex.Normal.Y > 0f)
                {
                    binormal.X = -binormal.X;
                    binormal.Y = -binormal.Y;
                    binormal.Z = -binormal.Z;
                }
            }

            Vector3 tangent = binormal % vertex.Normal;

            texCoord.Y = -(Vector3.Dot(tangent, vec) * 2f - 0.5f);
            texCoord.X = 1f + (Vector3.Dot(binormal, vec) * 2f - 0.5f);
        }
Пример #2
0
        // I had a lot of trouble with problems with equality and GetHashCode of OMVR.Vertex
        //    so this implementation creates a proper hash for a Vertex so it can be used
        //    in a dictionary.
        public static BHash VertexBHash(OMVR.Vertex vert)
        {
            BHasher hasher = new BHasherMdjb2();

            MeshInfo.VertexBHash(vert, hasher);
            return(hasher.Finish());
        }
        /// <summary>
        /// Apply texture coordinate modifications from a
        /// <seealso cref="TextureEntryFace"/> to a list of vertices
        /// </summary>
        /// <param name="vertices">Vertex list to modify texture coordinates for</param>
        /// <param name="center">Center-point of the face</param>
        /// <param name="teFace">Face texture parameters</param>
        public void TransformTexCoords(List <OMVR.Vertex> vertices, OMV.Vector3 center, OMV.Primitive.TextureEntryFace teFace)
        {
            // compute trig stuff up front
            float cosineAngle = (float)Math.Cos(teFace.Rotation);
            float sinAngle    = (float)Math.Sin(teFace.Rotation);

            // need a check for plainer vs default
            // just do default for now (I don't know what planar is)
            for (int ii = 0; ii < vertices.Count; ii++)
            {
                // tex coord comes to us as a number between zero and one
                // transform about the center of the texture
                OMVR.Vertex vert = vertices[ii];
                // repeat, offset, rotate
                // float tX = (vert.TexCoord.X - 0.5f) * teFace.RepeatU + teFace.OffsetU;
                // float tY = (vert.TexCoord.Y - 0.5f) * teFace.RepeatV - teFace.OffsetV;
                // vert.TexCoord.X = (tX * cosineAngle - tY * sinAngle) + 0.5f;
                // vert.TexCoord.Y = (tX * sinAngle + tY * cosineAngle) + 0.5f;
                float tX = vert.TexCoord.X - 0.5f;
                float tY = vert.TexCoord.Y - 0.5f;
                // rotate, scale, offset
                vert.TexCoord.X = (tX * cosineAngle - tY * sinAngle) * teFace.RepeatU - teFace.OffsetU + 0.5f;
                vert.TexCoord.Y = (tX * sinAngle + tY * cosineAngle) * teFace.RepeatV - teFace.OffsetV + 0.5f;
                vertices[ii]    = vert;
            }
            return;
        }
Пример #4
0
        /// <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 Face TerrainMesh(float[,] zMap, float xBegin, float xEnd, float yBegin, float yEnd)
        {
            SculptMesh newMesh      = new SculptMesh(zMap, xBegin, xEnd, yBegin, yEnd, true);
            Face       terrain      = new 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
                {
                    Position = new Vector3(newMesh.coords[j].X, newMesh.coords[j].Y, newMesh.coords[j].Z),
                    Normal   = new Vector3(newMesh.normals[j].X, newMesh.normals[j].Y, newMesh.normals[j].Z),
                    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);
        }
Пример #5
0
        // Given a list of meshes, combine them into one mesh and return a containing BInstance.
        private BInstance CreateOneInstanceFromMeshes(BHash materialHash, List <InvertedMesh> meshes)
        {
            // Pick one of the meshes to be the 'root' mesh.
            // Someday may need to find the most center mesh to work from.
            InvertedMesh rootIMesh = meshes.First();

            // The new instance will be at the location of the root mesh with no rotation
            BInstance inst = new BInstance();

            inst.Position  = rootIMesh.containingInstance.Position;
            inst.Rotation  = OMV.Quaternion.Identity;
            inst.coordAxis = rootIMesh.containingInstance.coordAxis;

            try {
                // The mesh we're going to build
                MeshInfo meshInfo = new MeshInfo();
                foreach (InvertedMesh imesh in meshes)
                {
                    int indicesBase = meshInfo.vertexs.Count;
                    // Go through the mesh, map all vertices to global coordinates then convert relative to root
                    meshInfo.vertexs.AddRange(imesh.renderableMesh.mesh.vertexs.Select(vert => {
                        OMVR.Vertex newVert  = new OMVR.Vertex();
                        OMV.Vector3 worldPos = vert.Position;
                        worldPos             = worldPos * imesh.containingDisplayable.offsetRotation
                                               + imesh.containingDisplayable.offsetPosition;
                        worldPos = worldPos * imesh.containingInstance.Rotation
                                   + imesh.containingInstance.Position;
                        // Make new vert relative to the BInstance it's being added to
                        newVert.Position = worldPos - inst.Position;
                        newVert.Normal   = vert.Normal
                                           * imesh.containingDisplayable.offsetRotation
                                           * imesh.containingInstance.Rotation;
                        newVert.TexCoord = vert.TexCoord;
                        return(newVert);
                    }));
                    meshInfo.indices.AddRange(imesh.renderableMesh.mesh.indices.Select(ind => ind + indicesBase));
                }

                RenderableMesh newMesh = new RenderableMesh();
                newMesh.num      = 0;
                newMesh.material = rootIMesh.renderableMesh.material;   // The material we share
                newMesh.mesh     = meshInfo;

                RenderableMeshGroup meshGroup = new RenderableMeshGroup();
                meshGroup.meshes.Add(newMesh);

                Displayable displayable = new Displayable(meshGroup);
                displayable.name = "combinedMaterialMeshes-" + materialHash.ToString();

                inst.Representation = displayable;
            }
            catch (Exception e) {
                ConvOAR.Globals.log.ErrorFormat("{0} CreateInstanceFromSharedMaterialMeshes: exception: {1}", _logHeader, e);
            }

            return(inst);
        }
Пример #6
0
 public static void OnAllVertex(MeshInfo mi, OperateOnVertex vertOp)
 {
     for (int jj = 0; jj < mi.vertexs.Count; jj++)
     {
         OMVR.Vertex aVert = mi.vertexs[jj];
         vertOp(ref aVert);
         mi.vertexs[jj] = aVert;
     }
 }
Пример #7
0
        /// <summary>
        /// Create a faceted mesh from prim shape parameters.
        /// Generates a a series of faces, each face containing a mesh and
        /// material metadata.
        /// A prim will turn into multiple faces with each being independent
        /// meshes and each having different material information.
        /// </summary>
        /// <param name="prim">Primitive to generate the mesh from</param>
        /// <param name="lod">Level of detail to generate the mesh at</param>
        /// <returns>The generated mesh</returns >
        public OMVR.FacetedMesh GenerateFacetedMesh(OMV.Primitive prim, OMVR.DetailLevel lod)
        {
            bool isSphere = ((OMV.ProfileCurve)(prim.PrimData.profileCurve & 0x07) == OMV.ProfileCurve.HalfCircle);

            PrimMesher.PrimMesh newPrim = GeneratePrimMesh(prim, lod, true);
            if (newPrim == null)
            {
                return(null);
            }

            // 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>();
            var indexer = newPrim.GetVertexIndexer();

            for (int i = 0; i < indexer.numPrimFaces; i++)
            {
                OMVR.Face oface = new OMVR.Face();
                oface.Vertices    = new List <OMVR.Vertex>();
                oface.Indices     = new List <ushort>();
                oface.TextureFace = prim.Textures.GetFace((uint)i);

                for (int j = 0; j < indexer.viewerVertices[i].Count; j++)
                {
                    var vert = new OMVR.Vertex();
                    var m    = indexer.viewerVertices[i][j];
                    vert.Position = new Vector3(m.v.X, m.v.Y, m.v.Z);
                    vert.Normal   = new Vector3(m.n.X, m.n.Y, m.n.Z);
                    vert.TexCoord = new OMV.Vector2(m.uv.U, 1.0f - m.uv.V);
                    oface.Vertices.Add(vert);
                }

                for (int j = 0; j < indexer.viewerPolygons[i].Count; j++)
                {
                    var p = indexer.viewerPolygons[i][j];
                    // Skip "degenerate faces" where the same vertex appears twice in the same tri
                    if (p.v1 == p.v2 || p.v1 == p.v2 || p.v2 == p.v3)
                    {
                        continue;
                    }
                    oface.Indices.Add((ushort)p.v1);
                    oface.Indices.Add((ushort)p.v2);
                    oface.Indices.Add((ushort)p.v3);
                }

                omvrmesh.Faces.Add(oface);
            }

            return(omvrmesh);
        }
Пример #8
0
 private static void VertexBHash(OMVR.Vertex vert, BHasher hasher)
 {
     hasher.Add(vert.Position.X);
     hasher.Add(vert.Position.Y);
     hasher.Add(vert.Position.Z);
     hasher.Add(vert.Normal.X);
     hasher.Add(vert.Normal.Y);
     hasher.Add(vert.Normal.Z);
     hasher.Add(vert.TexCoord.X);
     hasher.Add(vert.TexCoord.Y);
 }
        /// <summary>
        /// Apply texture coordinate modifications from a
        /// <seealso cref="TextureEntryFace"/> to a list of vertices
        /// </summary>
        /// <param name="vertices">Vertex list to modify texture coordinates for</param>
        /// <param name="center">Center-point of the face</param>
        /// <param name="teFace">Face texture parameters</param>
        public void TransformTexCoords(List <OMVR.Vertex> vertices, OMV.Vector3 center, OMV.Primitive.TextureEntryFace teFace, Vector3 primScale)
        {
            // compute trig stuff up front
            float cosineAngle = (float)Math.Cos(teFace.Rotation);
            float sinAngle    = (float)Math.Sin(teFace.Rotation);

            for (int ii = 0; ii < vertices.Count; ii++)
            {
                // tex coord comes to us as a number between zero and one
                // transform about the center of the texture
                OMVR.Vertex vert = vertices[ii];

                // aply planar tranforms to the UV first if applicable
                if (teFace.TexMapType == MappingType.Planar)
                {
                    Vector3 binormal;
                    float   d = Vector3.Dot(vert.Normal, Vector3.UnitX);
                    if (d >= 0.5f || d <= -0.5f)
                    {
                        binormal = Vector3.UnitY;
                        if (vert.Normal.X < 0f)
                        {
                            binormal *= -1;
                        }
                    }
                    else
                    {
                        binormal = Vector3.UnitX;
                        if (vert.Normal.Y > 0f)
                        {
                            binormal *= -1;
                        }
                    }
                    Vector3 tangent   = binormal % vert.Normal;
                    Vector3 scaledPos = vert.Position * primScale;
                    vert.TexCoord.X = 1f + (Vector3.Dot(binormal, scaledPos) * 2f - 0.5f);
                    vert.TexCoord.Y = -(Vector3.Dot(tangent, scaledPos) * 2f - 0.5f);
                }

                float repeatU = teFace.RepeatU;
                float repeatV = teFace.RepeatV;
                float tX      = vert.TexCoord.X - 0.5f;
                float tY      = vert.TexCoord.Y - 0.5f;

                vert.TexCoord.X = (tX * cosineAngle + tY * sinAngle) * repeatU + teFace.OffsetU + 0.5f;
                vert.TexCoord.Y = (-tX * sinAngle + tY * cosineAngle) * repeatV + teFace.OffsetV + 0.5f;
                vertices[ii]    = vert;
            }
            return;
        }
Пример #10
0
 // Create a new MeshInfo with a copy of what is in another MeshInfo.
 // Note that we need to do a deep'ish copy since the values of the
 //     vertices may be modified in the copy.
 // OMVR.Vertex and OMV.Vextor3 are structs so they are copied.
 public MeshInfo(MeshInfo other)
 {
     handle  = new EntityHandleUUID();
     vertexs = other.vertexs.ConvertAll(v => {
         OMVR.Vertex newV = new OMVR.Vertex();
         newV.Position    = v.Position;
         newV.Normal      = v.Normal;
         newV.TexCoord    = v.TexCoord;
         return(newV);
     });
     // vertexs = new List<OMVR.Vertex>(other.vertexs);
     indices    = new List <int>(other.indices);
     scale      = new OMV.Vector3(other.scale);
     faceCenter = new OMV.Vector3(other.faceCenter);
 }
Пример #11
0
        // Walk through all the vertices and scale the included meshes
        // Returns 'true' of the mesh was changed.
        public static bool ScaleMeshes(MeshInfo meshInfo, OMV.Vector3 scale)
        {
            bool ret = false;

            if (scale.X != 1.0 || scale.Y != 1.0 || scale.Z != 1.0)
            {
                ret = true;
                for (int ii = 0; ii < meshInfo.vertexs.Count; ii++)
                {
                    OMVR.Vertex aVert = meshInfo.vertexs[ii];
                    aVert.Position      *= scale;
                    meshInfo.vertexs[ii] = aVert;
                }
            }
            return(ret);
        }
Пример #12
0
        public void AddVertex(Vertex v)
        {
            int index;

            if (LookUp.ContainsKey(v))
            {
                index = LookUp[v];
            }
            else
            {
                index = Vertices.Count;
                Vertices.Add(v);
                LookUp[v] = index;
            }

            Indices.Add((uint)index);
        }
Пример #13
0
        public SimpleMesh GenerateSimpleMesh(Primitive prim, DetailLevel lod)
        {
            Path path = GeneratePath();
            Profile profile = GenerateProfile();

            MeshmerizerMesh meshmerizer = new MeshmerizerMesh();
            meshmerizer = GenerateMeshmerizerMesh(prim);

            // Create the vertex array
            List<Vertex> vertices = new List<Vertex>(meshmerizer.primMesh.coords.Count);
            for (int i = 0; i < meshmerizer.primMesh.coords.Count; i++)
            {
                Coord c = meshmerizer.primMesh.coords[i];
                Vertex vertex = new Vertex();
                vertex.Position = new Vector3(c.X, c.Y, c.Z);
                vertices.Add(vertex);
            }

            // Create the index array
            List<ushort> indices = new List<ushort>(meshmerizer.primMesh.faces.Count * 3);
            for (int i = 0; i < meshmerizer.primMesh.faces.Count; i++)
            {
                MeshmerizerFace f = meshmerizer.primMesh.faces[i];
                indices.Add((ushort)f.v1);
                indices.Add((ushort)f.v2);
                indices.Add((ushort)f.v3);
            }

            SimpleMesh mesh = new SimpleMesh();
            mesh.Prim = prim;
            mesh.Path = path;
            mesh.Profile = profile;
            mesh.Vertices = vertices;
            mesh.Indices = indices;

            return mesh;
        }
Пример #14
0
        // PrimMesher has a terrain mesh generator but it doesn't compute normals.
        // TODO: Optimize by removing vertices that are just mid points.
        //    Having a vertex for every height is very inefficient especially for flat areas.
        public static OMVR.Face TerrainMesh(float[,] heights, float realSizeX, float realSizeY)
        {
            List <ushort> indices = new List <ushort>();

            int sizeX = heights.GetLength(0);
            int sizeY = heights.GetLength(1);

            // build the vertices in an array for computing normals and eventually for
            //    optimizations.
            Vert[,] vertices = new Vert[sizeX, sizeY];

            float stepX      = (realSizeX) / (float)sizeX; // the real dimension step for each heightmap step
            float stepY      = (realSizeY) / (float)sizeY;
            float coordStepX = 1.0f / (float)sizeX;        // the coordinate dimension step for each heightmap step
            float coordStepY = 1.0f / (float)sizeY;

            uint index = 0;

            for (int xx = 0; xx < sizeX; xx++)
            {
                for (int yy = 0; yy < sizeY; yy++)
                {
                    Vert vert = new Vert();
                    vert.Position    = new OMV.Vector3(stepX * xx, stepY * yy, heights[xx, yy]);
                    vert.Normal      = new OMV.Vector3(0f, 1f, 0f); // normal pointing up for the moment
                    vert.TexCoord    = new OMV.Vector2(coordStepX * xx, coordStepY * yy);
                    vert.index       = index++;
                    vertices[xx, yy] = vert;
                }
            }
            // Pass over the far edges and make sure the mesh streaches the whole area
            for (int xx = 0; xx < sizeX; xx++)
            {
                vertices[xx, sizeY - 1].Position.Y = realSizeY + 1;
            }
            for (int yy = 0; yy < sizeY; yy++)
            {
                vertices[sizeX - 1, yy].Position.X = realSizeY + 1;
            }

            // Compute the normals
            // Take three corners of each quad and calculate the normal for the vector
            //   a--b--e--...
            //   |  |  |
            //   d--c--h--...
            // The triangle a-b-d calculates the normal for a, etc
            for (int xx = 0; xx < sizeX - 1; xx++)
            {
                for (int yy = 0; yy < sizeY - 1; yy++)
                {
                    vertices[xx, yy].Normal = MakeNormal(vertices[xx, yy], vertices[xx + 1, yy], vertices[xx, yy + 1]);
                }
            }
            // The vertices along the edges need an extra pass to compute the normals
            for (int xx = 0; xx < sizeX - 1; xx++)
            {
                vertices[xx, sizeY - 1].Normal = MakeNormal(vertices[xx, sizeY - 1], vertices[xx + 1, sizeY - 1], vertices[xx, sizeY - 2]);
            }
            for (int yy = 0; yy < sizeY - 1; yy++)
            {
                vertices[sizeX - 1, yy].Normal = MakeNormal(vertices[sizeX - 1, yy], vertices[sizeX - 1, yy + 1], vertices[sizeX - 2, yy]);
            }
            vertices[sizeX - 1, sizeY - 1].Normal = MakeNormal(vertices[sizeX - 1, sizeY - 1], vertices[sizeX - 2, sizeY - 1], vertices[sizeX - 1, sizeY - 2]);

            // Convert our vertices into the format expected by the caller
            List <OMVR.Vertex> vertexList = new List <OMVR.Vertex>();

            for (int xx = 0; xx < sizeX; xx++)
            {
                for (int yy = 0; yy < sizeY; yy++)
                {
                    Vert        vert  = vertices[xx, yy];
                    OMVR.Vertex oVert = new OMVR.Vertex();
                    oVert.Position = vert.Position;
                    oVert.Normal   = vert.Normal;
                    oVert.TexCoord = vert.TexCoord;
                    vertexList.Add(oVert);
                }
            }

            // Make indices for all the vertices.
            // Pass over the matrix and create two triangles for each quad
            //
            //   00-----01
            //   | f1  /|
            //   |   /  |
            //   | / f2 |
            //   10-----11
            //
            // Counter Clockwise
            for (int xx = 0; xx < sizeX - 1; xx++)
            {
                for (int yy = 0; yy < sizeY - 1; yy++)
                {
                    indices.Add((ushort)vertices[xx + 0, yy + 0].index);
                    indices.Add((ushort)vertices[xx + 1, yy + 0].index);
                    indices.Add((ushort)vertices[xx + 0, yy + 1].index);
                    indices.Add((ushort)vertices[xx + 0, yy + 1].index);
                    indices.Add((ushort)vertices[xx + 1, yy + 0].index);
                    indices.Add((ushort)vertices[xx + 1, yy + 1].index);
                }
            }

            OMVR.Face aface = new OMVR.Face();
            aface.Vertices = vertexList;
            aface.Indices  = indices;
            return(aface);
        }
Пример #15
0
        /// <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;
        }
Пример #16
0
        /// <summary>
        /// Load the mesh from a stream
        /// </summary>
        /// <param name="filename">The filename and path of the file containing the mesh data</param>
        public virtual void LoadMesh(string filename)
        {
            using(FileStream meshData = new FileStream(filename, FileMode.Open, FileAccess.Read))
            using (EndianAwareBinaryReader reader = new EndianAwareBinaryReader(meshData))
            {
                Header = TrimAt0(reader.ReadString(24));
                if (!String.Equals(Header, MeshHeader))
                    throw new FileLoadException("Unrecognized mesh format");

                // Populate base mesh parameters
                HasWeights = (reader.ReadByte() != 0);
                HasDetailTexCoords = (reader.ReadByte() != 0);
                Position = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                RotationAngles = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                /* RotationOrder = */ reader.ReadByte();
                Scale = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());

                // Populate the vertex array
                NumVertices = reader.ReadUInt16();
                Vertices = new Vertex[NumVertices];
                for (int i = 0; i < NumVertices; i++)
                    Vertices[i].Coord = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());

                for (int i = 0; i < NumVertices; i++)
                    Vertices[i].Normal = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());

                for (int i = 0; i < NumVertices; i++)
                    Vertices[i].BiNormal = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());

                for (int i = 0; i < NumVertices; i++)
                    Vertices[i].TexCoord = new Vector2(reader.ReadSingle(), reader.ReadSingle());

                if (HasDetailTexCoords)
                {
                    for (int i = 0; i < NumVertices; i++)
                        Vertices[i].DetailTexCoord = new Vector2(reader.ReadSingle(), reader.ReadSingle());
                }

                if (HasWeights)
                {
                    for (int i = 0; i < NumVertices; i++)
                        Vertices[i].Weight = reader.ReadSingle();
                }

                NumFaces = reader.ReadUInt16();
                Faces = new Face[NumFaces];

                for (int i = 0; i < NumFaces; i++)
                    Faces[i].Indices = new[] { reader.ReadInt16(), reader.ReadInt16(), reader.ReadInt16() };

                if (HasWeights)
                {
                    NumSkinJoints = reader.ReadUInt16();
                    SkinJoints = new string[NumSkinJoints];

                    for (int i = 0; i < NumSkinJoints; i++)
                    {
                        SkinJoints[i] = TrimAt0(reader.ReadString(64));
                    }
                }
                else
                {
                    NumSkinJoints = 0;
                    SkinJoints = new string[0];
                }

                // Grab morphs
                List<Morph> morphs = new List<Morph>();
                string morphName = TrimAt0(reader.ReadString(64));

                while (morphName != MorphFooter)
                {
                    if (reader.BaseStream.Position + 48 >= reader.BaseStream.Length)
                        throw new FileLoadException("Encountered end of file while parsing morphs");

                    Morph morph = new Morph();
                    morph.Name = morphName;
                    morph.NumVertices = reader.ReadInt32();
                    morph.Vertices = new MorphVertex[morph.NumVertices];

                    for (int i = 0; i < morph.NumVertices; i++)
                    {
                        morph.Vertices[i].VertexIndex = reader.ReadUInt32();
                        morph.Vertices[i].Coord = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                        morph.Vertices[i].Normal = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                        morph.Vertices[i].BiNormal = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                        morph.Vertices[i].TexCoord = new Vector2(reader.ReadSingle(), reader.ReadSingle());
                    }

                    morphs.Add(morph);

                    // Grab the next name
                    morphName = TrimAt0(reader.ReadString(64));
                }

                Morphs = morphs.ToArray();

                // Check if there are remaps or if we're at the end of the file
                if (reader.BaseStream.Position < reader.BaseStream.Length - 1)
                {
                    NumRemaps = reader.ReadInt32();
                    VertexRemaps = new VertexRemap[NumRemaps];

                    for (int i = 0; i < NumRemaps; i++)
                    {
                        VertexRemaps[i].RemapSource = reader.ReadInt32();
                        VertexRemaps[i].RemapDestination = reader.ReadInt32();
                    }
                }
                else
                {
                    NumRemaps = 0;
                    VertexRemaps = new VertexRemap[0];
                }
            }

            // uncompress the skin weights
            if (Skeleton != null)
            {
                // some meshes aren't weighted, which doesn't make much sense.
                // we check for left and right eyeballs, and assign them a 100%
                // to their respective bone
                List<string> expandedJointList = Skeleton.BuildExpandedJointList(SkinJoints);
                if (expandedJointList.Count == 0)
                {
                    if (Name == "eyeBallLeftMesh")
                    {
                        expandedJointList.AddRange(new[] { "mEyeLeft", "mSkull" });
                    }
                    else if (Name == "eyeBallRightMesh")
                    {
                        expandedJointList.AddRange(new[] { "mEyeRight", "mSkull" });
                    }
                }

                if (expandedJointList.Count > 0)
                    ExpandCompressedSkinWeights(expandedJointList);
            }
        }
Пример #17
0
        public RenderingMesh GetRenderingMesh(LLPrimitive prim, DetailLevel lod)
        {
            RenderingMesh mesh;
            ulong         physicsKey = prim.GetPhysicsKey();

            // Try a cache lookup first
            if (m_meshCache != null && m_meshCache.TryGetRenderingMesh(physicsKey, lod, out mesh))
            {
                return(mesh);
            }

            // Can't go any further without a prim renderer
            if (m_renderer == null)
            {
                return(null);
            }

            // Convert our DetailLevel to the OpenMetaverse.Rendering DetailLevel
            OpenMetaverse.Rendering.DetailLevel detailLevel;
            switch (lod)
            {
            case DetailLevel.Low:
                detailLevel = OpenMetaverse.Rendering.DetailLevel.Low;
                break;

            case DetailLevel.Medium:
                detailLevel = OpenMetaverse.Rendering.DetailLevel.Medium;
                break;

            case DetailLevel.High:
                detailLevel = OpenMetaverse.Rendering.DetailLevel.High;
                break;

            case DetailLevel.Highest:
            default:
                detailLevel = OpenMetaverse.Rendering.DetailLevel.Highest;
                break;
            }

            FacetedMesh facetedMesh = null;

            if (prim.Prim.Sculpt != null && prim.Prim.Sculpt.SculptTexture != UUID.Zero)
            {
                // Sculpty meshing
                Bitmap sculptTexture = GetSculptMap(prim.Prim.Sculpt.SculptTexture);
                if (sculptTexture != null)
                {
                    facetedMesh = m_renderer.GenerateFacetedSculptMesh(prim.Prim, sculptTexture, detailLevel);
                }
            }
            else
            {
                // Basic prim meshing
                facetedMesh = m_renderer.GenerateFacetedMesh(prim.Prim, detailLevel);
            }

            if (facetedMesh != null)
            {
                #region FacetedMesh to RenderingMesh Conversion

                mesh       = new RenderingMesh();
                mesh.Faces = new RenderingMesh.Face[facetedMesh.Faces.Count];
                for (int i = 0; i < facetedMesh.Faces.Count; i++)
                {
                    Face face = facetedMesh.Faces[i];

                    Vertex[] vertices = new Vertex[face.Vertices.Count];
                    for (int j = 0; j < face.Vertices.Count; j++)
                    {
                        OpenMetaverse.Rendering.Vertex omvrVertex = face.Vertices[j];
                        vertices[j] = new Vertex {
                            Position = omvrVertex.Position, Normal = omvrVertex.Normal, TexCoord = omvrVertex.TexCoord
                        };
                    }
                    ushort[] indices = face.Indices.ToArray();

                    mesh.Faces[i] = new RenderingMesh.Face {
                        Vertices = vertices, Indices = indices
                    };
                }

                #endregion FacetedMesh to RenderingMesh Conversion

                // Store the result in the mesh cache, if we have one
                if (m_meshCache != null)
                {
                    m_meshCache.StoreRenderingMesh(physicsKey, lod, mesh);
                }

                return(mesh);
            }
            else
            {
                return(null);
            }
        }
Пример #18
0
 private static void LerpPlanarVertex(Vertex v0, Vertex v1, Vertex v2, ref Vertex vout, float coef01, float coef02)
 {
     vout.Position = v0.Position + ((v1.Position - v0.Position) * coef01) + ((v2.Position - v0.Position) * coef02);
     vout.TexCoord = v0.TexCoord + ((v1.TexCoord - v0.TexCoord) * coef01) + ((v2.TexCoord - v0.TexCoord) * coef02);
     vout.Normal = v0.Normal;
     vout.Binormal = v0.Binormal;
 }
Пример #19
0
        private static void CreateSide(ref Face face, LLObject.ObjectData prim, List<Vertex> primVertices, Path path,
            Profile profile)
        {
            bool flat = (face.Mask & FaceMask.Flat) != 0;

            int maxS = profile.Positions.Count;
            int s, t, i;
            float ss, tt;

            int numVertices = face.NumS * face.NumT;
            int numIndices = (face.NumS - 1) * (face.NumT - 1) * 6;

            face.Center = Vector3.Zero;

            int beginSTex = (int)Math.Floor(profile.Positions[face.BeginS].Z);
            int numS =
                (((face.Mask & FaceMask.Inner) != 0) && ((face.Mask & FaceMask.Flat) != 0) && face.NumS > 2) ?
                    face.NumS / 2 :
                    face.NumS;

            int curVertex = 0;

            // Copy the vertices into the array
            for (t = face.BeginT; t < face.BeginT + face.NumT; t++)
            {
                tt = path.Points[t].TexT;

                for (s = 0; s < numS; s++)
                {
                    if ((face.Mask & FaceMask.End) != 0)
                    {
                        if (s != 0)
                            ss = 1f;
                        else
                            ss = 0f;
                    }
                    else
                    {
                        // Get s value for tex-coord
                        if (!flat)
                            ss = profile.Positions[face.BeginS + s].Z;
                        else
                            ss = profile.Positions[face.BeginS + s].Z - beginSTex;
                    }

                    // Check to see if this triangle wraps around the array
                    if (face.BeginS + s >= maxS)
                        i = face.BeginS + s + maxS * (t - 1); // We're wrapping
                    else
                        i = face.BeginS + s + maxS * t;

                    Vertex vertex = new Vertex();
                    vertex.Position = primVertices[i].Position;
                    vertex.TexCoord = new Vector2(ss, tt);
                    vertex.Normal = Vector3.Zero;
                    vertex.Binormal = Vector3.Zero;

                    if (curVertex == 0)
                        face.MinExtent = face.MaxExtent = primVertices[i].Position;
                    else
                        UpdateMinMax(ref face, primVertices[i].Position);

                    face.Vertices.Add(vertex);
                    ++curVertex;

                    if (((face.Mask & FaceMask.Inner) != 0) && ((face.Mask & FaceMask.Flat) != 0) && face.NumS > 2 && s > 0)
                    {
                        vertex.Position = primVertices[i].Position;
                        //vertex.TexCoord = new Vector2(ss, tt);
                        //vertex.Normal = Vector3.Zero;
                        //vertex.Binormal = Vector3.Zero;

                        face.Vertices.Add(vertex);
                        ++curVertex;
                    }
                }

                if (((face.Mask & FaceMask.Inner) != 0) && ((face.Mask & FaceMask.Flat) != 0) && face.NumS > 2)
                {
                    if ((face.Mask & FaceMask.Open) != 0)
                        s = numS - 1;
                    else
                        s = 0;

                    i = face.BeginS + s + maxS * t;
                    ss = profile.Positions[face.BeginS + s].Z - beginSTex;

                    Vertex vertex = new Vertex();
                    vertex.Position = primVertices[i].Position;
                    vertex.TexCoord = new Vector2(ss, tt);
                    vertex.Normal = Vector3.Zero;
                    vertex.Binormal = Vector3.Zero;

                    UpdateMinMax(ref face, vertex.Position);

                    face.Vertices.Add(vertex);
                    ++curVertex;
                }
            }

            face.Center = (face.MinExtent + face.MaxExtent) * 0.5f;

            bool flatFace = ((face.Mask & FaceMask.Flat) != 0);

            // Now we generate the indices
            for (t = 0; t < (face.NumT - 1); t++)
            {
                for (s = 0; s < (face.NumS - 1); s++)
                {
                    face.Indices.Add((ushort)(s + face.NumS * t)); // Bottom left
                    face.Indices.Add((ushort)(s + 1 + face.NumS * (t + 1))); // Top right
                    face.Indices.Add((ushort)(s + face.NumS * (t + 1))); // Top left
                    face.Indices.Add((ushort)(s + face.NumS * t)); // Bottom left
                    face.Indices.Add((ushort)(s + 1 + face.NumS * t)); // Bottom right
                    face.Indices.Add((ushort)(s + 1 + face.NumS * (t + 1))); // Top right

                    face.Edge.Add((face.NumS - 1) * 2 * t + s * 2 + 1); // Bottom left/top right neighbor face

                    if (t < face.NumT - 2) // Top right/top left neighbor face
                        face.Edge.Add((face.NumS - 1) * 2 * (t + 1) + s * 2 + 1);
                    else if (face.NumT <= 3 || path.Open) // No neighbor
                        face.Edge.Add(-1);
                    else // Wrap on T
                        face.Edge.Add(s * 2 + 1);

                    if (s > 0) // Top left/bottom left neighbor face
                        face.Edge.Add((face.NumS - 1) * 2 * t + s * 2 - 1);
                    else if (flatFace || profile.Open) // No neighbor
                        face.Edge.Add(-1);
                    else // Wrap on S
                        face.Edge.Add((face.NumS - 1) * 2 * t + (face.NumS - 2) * 2 + 1);

                    if (t > 0) // Bottom left/bottom right neighbor face
                        face.Edge.Add((face.NumS - 1) * 2 * (t - 1) + s * 2);
                    else if (face.NumT <= 3 || path.Open) // No neighbor
                        face.Edge.Add(-1);
                    else // Wrap on T
                        face.Edge.Add((face.NumS - 1) * 2 * (face.NumT - 2) + s * 2);

                    if (s < face.NumS - 2) // Bottom right/top right neighbor face
                        face.Edge.Add((face.NumS - 1) * 2 * t + (s + 1) * 2);
                    else if (flatFace || profile.Open) // No neighbor
                        face.Edge.Add(-1);
                    else // Wrap on S
                        face.Edge.Add((face.NumS - 1) * 2 * t);

                    face.Edge.Add((face.NumS - 1) * 2 * t + s * 2); // Top right/bottom left neighbor face	
                }
            }

            // Generate normals, loop through each triangle
            for (i = 0; i < face.Indices.Count / 3; i++)
            {
                Vertex v0 = face.Vertices[face.Indices[i * 3 + 0]];
                Vertex v1 = face.Vertices[face.Indices[i * 3 + 1]];
                Vertex v2 = face.Vertices[face.Indices[i * 3 + 2]];

                // Calculate triangle normal
                Vector3 norm = (v0.Position - v1.Position) % (v0.Position - v2.Position);

                // Calculate binormal
                Vector3 binorm = CalcBinormalFromTriangle(v0.Position, v0.TexCoord, v1.Position, v1.TexCoord,
                    v2.Position, v2.TexCoord);

                // Add triangle normal to vertices
                for (int j = 0; j < 3; j++)
                {
                    Vertex vertex = face.Vertices[face.Indices[i * 3 + j]];
                    vertex.Normal += norm;
                    vertex.Binormal += binorm;
                    face.Vertices[face.Indices[i * 3 + j]] = vertex;
                }

                // Even out quad contributions
                if (i % 2 == 0)
                {
                    Vertex vertex = face.Vertices[face.Indices[i * 3 + 2]];
                    vertex.Normal += norm;
                    vertex.Binormal += binorm;
                    face.Vertices[face.Indices[i * 3 + 2]] = vertex;
                }
                else
                {
                    Vertex vertex = face.Vertices[face.Indices[i * 3 + 1]];
                    vertex.Normal += norm;
                    vertex.Binormal += binorm;
                    face.Vertices[face.Indices[i * 3 + 1]] = vertex;
                }
            }

            // Adjust normals based on wrapping and stitching
            Vector3 test1 =
                face.Vertices[0].Position -
                face.Vertices[face.NumS * (face.NumT - 2)].Position;

            Vector3 test2 =
                face.Vertices[face.NumS - 1].Position -
                face.Vertices[face.NumS * (face.NumT - 2) +
                face.NumS - 1].Position;

            bool sBottomConverges = (test1.LengthSquared() < 0.000001f);
            bool sTopConverges = (test2.LengthSquared() < 0.000001f);

            // TODO: Sculpt support
            Primitive.SculptType sculptType = Primitive.SculptType.None;

            if (sculptType == Primitive.SculptType.None)
            {
                if (!path.Open)
                {
                    // Wrap normals on T
                    for (i = 0; i < face.NumS; i++)
                    {
                        Vector3 norm = face.Vertices[i].Normal + face.Vertices[face.NumS * (face.NumT - 1) + i].Normal;

                        Vertex vertex = face.Vertices[i];
                        vertex.Normal = norm;
                        face.Vertices[i] = vertex;

                        vertex = face.Vertices[face.NumS * (face.NumT - 1) + i];
                        vertex.Normal = norm;
                        face.Vertices[face.NumS * (face.NumT - 1) + i] = vertex;
                    }
                }

                if (!profile.Open && !sBottomConverges)
                {
                    // Wrap normals on S
                    for (i = 0; i < face.NumT; i++)
                    {
                        Vector3 norm = face.Vertices[face.NumS * i].Normal + face.Vertices[face.NumS * i + face.NumS - 1].Normal;

                        Vertex vertex = face.Vertices[face.NumS * i];
                        vertex.Normal = norm;
                        face.Vertices[face.NumS * i] = vertex;

                        vertex = face.Vertices[face.NumS * i + face.NumS - 1];
                        vertex.Normal = norm;
                        face.Vertices[face.NumS * i + face.NumS - 1] = vertex;
                    }
                }

                if (prim.PathCurve == LLObject.PathCurve.Circle &&
                    prim.ProfileCurve == LLObject.ProfileCurve.HalfCircle)
                {
                    if (sBottomConverges)
                    {
                        // All lower S have same normal
                        Vector3 unitX = new Vector3(1f, 0f, 0f);

                        for (i = 0; i < face.NumT; i++)
                        {
                            Vertex vertex = face.Vertices[face.NumS * i];
                            vertex.Normal = unitX;
                            face.Vertices[face.NumS * i] = vertex;
                        }
                    }

                    if (sTopConverges)
                    {
                        // All upper S have same normal
                        Vector3 negUnitX = new Vector3(-1f, 0f, 0f);

                        for (i = 0; i < face.NumT; i++)
                        {
                            Vertex vertex = face.Vertices[face.NumS * i + face.NumS - 1];
                            vertex.Normal = negUnitX;
                            face.Vertices[face.NumS * i + face.NumS - 1] = vertex;
                        }
                    }
                }
            }
            else
            {
                // FIXME: Sculpt support
            }

            // Normalize normals and binormals
            for (i = 0; i < face.Vertices.Count; i++)
            {
                Vertex vertex = face.Vertices[i];
                vertex.Normal.Normalize();
                vertex.Binormal.Normalize();
                face.Vertices[i] = vertex;
            }
        }
Пример #20
0
        /// <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;
        }
Пример #21
0
        /// <summary>
        /// Generates a a series of faces, each face containing a mesh and
        /// metadata
        /// </summary>
        /// <param name="prim">Primitive to generate the mesh from</param>
        /// <param name="lod">Level of detail to generate the mesh at</param>
        /// <returns>The generated mesh</returns >
        public OMVR.FacetedMesh GenerateFacetedMesh(OMV.Primitive prim, OMVR.DetailLevel lod)
        {
            bool isSphere = ((OMV.ProfileCurve)(prim.PrimData.profileCurve & 0x07) == OMV.ProfileCurve.HalfCircle);
            PrimMesher.PrimMesh newPrim = GeneratePrimMesh(prim, lod, true);
            if (newPrim == null)
                return null;

            int numViewerFaces = newPrim.viewerFaces.Count;
            int numPrimFaces = newPrim.numPrimFaces;

            for (uint i = 0; i < numViewerFaces; i++)
            {
                PrimMesher.ViewerFace vf = newPrim.viewerFaces[(int)i];

                if (isSphere)
                {
                    vf.uv1.U = (vf.uv1.U - 0.5f) * 2.0f;
                    vf.uv2.U = (vf.uv2.U - 0.5f) * 2.0f;
                    vf.uv3.U = (vf.uv3.U - 0.5f) * 2.0f;
                }
            }

            // 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<OMV.Vector3, int> vertexAccount = new Dictionary<OMV.Vector3, int>();
            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;
                vertexAccount.Clear();
                OMV.Vector3 pos;
                int indx;
                OMVR.Vertex vert;
                foreach (PrimMesher.ViewerFace vface in newPrim.viewerFaces)
                {
                    if (vface.primFaceNumber == ii)
                    {
                        faceVertices++;
                        pos = new OMV.Vector3(vface.v1.X, vface.v1.Y, vface.v1.Z);
                        if (vertexAccount.ContainsKey(pos))
                        {
                            // we aleady have this vertex in the list. Just point the index at it
                            oface.Indices.Add((ushort)vertexAccount[pos]);
                        }
                        else
                        {
                            // the vertex is not in the list. Add it and the new index.
                            vert = new OMVR.Vertex();
                            vert.Position = pos;
                            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);
                            indx = oface.Vertices.Count - 1;
                            vertexAccount.Add(pos, indx);
                            oface.Indices.Add((ushort)indx);
                        }

                        pos = new OMV.Vector3(vface.v2.X, vface.v2.Y, vface.v2.Z);
                        if (vertexAccount.ContainsKey(pos))
                        {
                            oface.Indices.Add((ushort)vertexAccount[pos]);
                        }
                        else
                        {
                            vert = new OMVR.Vertex();
                            vert.Position = pos;
                            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);
                            indx = oface.Vertices.Count - 1;
                            vertexAccount.Add(pos, indx);
                            oface.Indices.Add((ushort)indx);
                        }

                        pos = new OMV.Vector3(vface.v3.X, vface.v3.Y, vface.v3.Z);
                        if (vertexAccount.ContainsKey(pos))
                        {
                            oface.Indices.Add((ushort)vertexAccount[pos]);
                        }
                        else
                        {
                            vert = new OMVR.Vertex();
                            vert.Position = pos;
                            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);
                            indx = oface.Vertices.Count - 1;
                            vertexAccount.Add(pos, indx);
                            oface.Indices.Add((ushort)indx);
                        }
                    }
                }
                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>
        /// Generates a a series of faces, each face containing a mesh and
        /// metadata
        /// </summary>
        /// <param name="prim">Primitive to generate the mesh from</param>
        /// <param name="lod">Level of detail to generate the mesh at</param>
        /// <returns>The generated mesh</returns >
        public OMVR.FacetedMesh GenerateFacetedMesh(OMV.Primitive prim, OMVR.DetailLevel lod)
        {
            bool isSphere = ((OMV.ProfileCurve)(prim.PrimData.profileCurve & 0x07) == OMV.ProfileCurve.HalfCircle);

            PrimMesher.PrimMesh newPrim = GeneratePrimMesh(prim, lod, true);
            if (newPrim == null)
            {
                return(null);
            }

            int numViewerFaces = newPrim.viewerFaces.Count;
            int numPrimFaces   = newPrim.numPrimFaces;

            for (uint i = 0; i < numViewerFaces; i++)
            {
                PrimMesher.ViewerFace vf = newPrim.viewerFaces[(int)i];

                if (isSphere)
                {
                    vf.uv1.U = (vf.uv1.U - 0.5f) * 2.0f;
                    vf.uv2.U = (vf.uv2.U - 0.5f) * 2.0f;
                    vf.uv3.U = (vf.uv3.U - 0.5f) * 2.0f;
                }
            }

            // 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 <OMV.Vector3, int> vertexAccount = new Dictionary <OMV.Vector3, int>();

            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;
                vertexAccount.Clear();
                OMV.Vector3 pos;
                int         indx;
                OMVR.Vertex vert;
                foreach (PrimMesher.ViewerFace vface in newPrim.viewerFaces)
                {
                    if (vface.primFaceNumber == ii)
                    {
                        faceVertices++;
                        pos = new OMV.Vector3(vface.v1.X, vface.v1.Y, vface.v1.Z);
                        if (vertexAccount.ContainsKey(pos))
                        {
                            // we aleady have this vertex in the list. Just point the index at it
                            oface.Indices.Add((ushort)vertexAccount[pos]);
                        }
                        else
                        {
                            // the vertex is not in the list. Add it and the new index.
                            vert          = new OMVR.Vertex();
                            vert.Position = pos;
                            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);
                            indx = oface.Vertices.Count - 1;
                            vertexAccount.Add(pos, indx);
                            oface.Indices.Add((ushort)indx);
                        }

                        pos = new OMV.Vector3(vface.v2.X, vface.v2.Y, vface.v2.Z);
                        if (vertexAccount.ContainsKey(pos))
                        {
                            oface.Indices.Add((ushort)vertexAccount[pos]);
                        }
                        else
                        {
                            vert          = new OMVR.Vertex();
                            vert.Position = pos;
                            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);
                            indx = oface.Vertices.Count - 1;
                            vertexAccount.Add(pos, indx);
                            oface.Indices.Add((ushort)indx);
                        }

                        pos = new OMV.Vector3(vface.v3.X, vface.v3.Y, vface.v3.Z);
                        if (vertexAccount.ContainsKey(pos))
                        {
                            oface.Indices.Add((ushort)vertexAccount[pos]);
                        }
                        else
                        {
                            vert          = new OMVR.Vertex();
                            vert.Position = pos;
                            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);
                            indx = oface.Vertices.Count - 1;
                            vertexAccount.Add(pos, indx);
                            oface.Indices.Add((ushort)indx);
                        }
                    }
                }
                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);
        }
Пример #23
0
        private List<Face> GenerateFaces(Primitive prim)
        {
            MeshmerizerMesh meshmerizer = new MeshmerizerMesh();
            meshmerizer = GenerateMeshmerizerMesh(prim);

            // Create the vertex array
            List<Vertex> vertices = new List<Vertex>(meshmerizer.primMesh.coords.Count);
            for (int i = 0; i < meshmerizer.primMesh.coords.Count; i++)
            {
                Coord c = meshmerizer.primMesh.coords[i];
                Vertex vertex = new Vertex();
                vertex.Position = new Vector3(c.X, c.Y, c.Z);
                vertices.Add(vertex);
            }

            // Create the index array
            List<ushort> indices = new List<ushort>(meshmerizer.primMesh.faces.Count * 3);
            for (int i = 0; i < meshmerizer.primMesh.faces.Count; i++)
            {
                MeshmerizerFace f = meshmerizer.primMesh.faces[i];
                indices.Add((ushort)f.v1);
                indices.Add((ushort)f.v2);
                indices.Add((ushort)f.v3);
            }

            Face face = new Face();
            face.Edge = new List<int>();
            face.TextureFace = prim.Textures.DefaultTexture;
            face.Vertices = vertices;
            face.Indices = indices;

            List<Face> faces = new List<Face>(1);
            faces.Add(face);

            return faces;
        }
Пример #24
0
        //public void SetView(OpenMetaverse.Vector3 center, int roll, int pitch, int yaw, int zoom)
        //{
        //    this.Center = center;
        //    scrollRoll.Value = roll;
        //    scrollPitch.Value = pitch;
        //    scrollYaw.Value = yaw;
        //    scrollZoom.Value = zoom;
        //}

        public static FacetedMesh GenerateFacetedMesh(Primitive prim, OSDMap MeshData, DetailLevel LOD)
        {
            FacetedMesh ret = new FacetedMesh();

            ret.Faces = new List<Face>();
            ret.Prim = prim;
            ret.Profile = new Profile();
            ret.Profile.Faces = new List<ProfileFace>();
            ret.Profile.Positions = new List<OpenMetaverse.Vector3>();
            ret.Path = new OpenMetaverse.Rendering.Path();
            ret.Path.Points = new List<PathPoint>();

            try
            {
                OSD facesOSD = null;

                switch (LOD)
                {
                    default:
                    case DetailLevel.Highest:
                        facesOSD = MeshData["high_lod"];
                        break;

                    case DetailLevel.High:
                        facesOSD = MeshData["medium_lod"];
                        break;

                    case DetailLevel.Medium:
                        facesOSD = MeshData["low_lod"];
                        break;

                    case DetailLevel.Low:
                        facesOSD = MeshData["lowest_lod"];
                        break;
                }

                if (facesOSD == null || !(facesOSD is OSDArray))
                {
                    return ret;
                }

                OSDArray decodedMeshOsdArray = (OSDArray)facesOSD;

                for (int faceNr = 0; faceNr < decodedMeshOsdArray.Count; faceNr++)
                {
                    OSD subMeshOsd = decodedMeshOsdArray[faceNr];
                    Face oface = new Face();
                    oface.ID = faceNr;
                    oface.Vertices = new List<Vertex>();
                    oface.Indices = new List<ushort>();
                    oface.TextureFace = prim.Textures.GetFace((uint)faceNr);

                    if (subMeshOsd is OSDMap)
                    {
                        OSDMap subMeshMap = (OSDMap)subMeshOsd;

                        OpenMetaverse.Vector3 posMax = new OpenMetaverse.Vector3();
                        posMax = ((OSDMap)subMeshMap["PositionDomain"])["Max"];
                        OpenMetaverse.Vector3 posMin = new OpenMetaverse.Vector3();
                        posMin = ((OSDMap)subMeshMap["PositionDomain"])["Min"];

                        OpenMetaverse.Vector2 texPosMax = new OpenMetaverse.Vector2();
                        texPosMax = ((OSDMap)subMeshMap["TexCoord0Domain"])["Max"];
                        OpenMetaverse.Vector2 texPosMin = new OpenMetaverse.Vector2();
                        texPosMin = ((OSDMap)subMeshMap["TexCoord0Domain"])["Min"];


                        byte[] posBytes = subMeshMap["Position"];
                        byte[] norBytes = subMeshMap["Normal"];
                        byte[] texBytes = subMeshMap["TexCoord0"];

                        for (int i = 0; i < posBytes.Length; i += 6)
                        {
                            ushort uX = Utils.BytesToUInt16(posBytes, i);
                            ushort uY = Utils.BytesToUInt16(posBytes, i + 2);
                            ushort uZ = Utils.BytesToUInt16(posBytes, i + 4);

                            Vertex vx = new Vertex();

                            vx.Position = new OpenMetaverse.Vector3(
                                Utils.UInt16ToFloat(uX, posMin.X, posMax.X),
                                Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y),
                                Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z));

                            ushort nX = Utils.BytesToUInt16(norBytes, i);
                            ushort nY = Utils.BytesToUInt16(norBytes, i + 2);
                            ushort nZ = Utils.BytesToUInt16(norBytes, i + 4);

                            vx.Normal = new OpenMetaverse.Vector3(
                                Utils.UInt16ToFloat(nX, posMin.X, posMax.X),
                                Utils.UInt16ToFloat(nY, posMin.Y, posMax.Y),
                                Utils.UInt16ToFloat(nZ, posMin.Z, posMax.Z));

                            var vertexIndexOffset = oface.Vertices.Count * 4;

                            if (texBytes != null && texBytes.Length >= vertexIndexOffset + 4)
                            {
                                ushort tX = Utils.BytesToUInt16(texBytes, vertexIndexOffset);
                                ushort tY = Utils.BytesToUInt16(texBytes, vertexIndexOffset + 2);

                                vx.TexCoord = new OpenMetaverse.Vector2(
                                    Utils.UInt16ToFloat(tX, texPosMin.X, texPosMax.X),
                                    Utils.UInt16ToFloat(tY, texPosMin.Y, texPosMax.Y));
                            }

                            oface.Vertices.Add(vx);
                        }

                        byte[] triangleBytes = subMeshMap["TriangleList"];
                        for (int i = 0; i < triangleBytes.Length; i += 6)
                        {
                            ushort v1 = (ushort)(Utils.BytesToUInt16(triangleBytes, i));
                            oface.Indices.Add(v1);
                            ushort v2 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 2));
                            oface.Indices.Add(v2);
                            ushort v3 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 4));
                            oface.Indices.Add(v3);
                        }
                    }

                    ret.Faces.Add(oface);
                }

            }
            catch (Exception ex)
            {
                Logger.Log("Failed to decode mesh asset: " + ex.Message, Helpers.LogLevel.Warning);
            }

            return ret;
        }
Пример #25
0
        public RenderingMesh GetRenderingMesh(LLPrimitive prim, DetailLevel lod)
        {
            RenderingMesh mesh;
            ulong physicsKey = prim.GetPhysicsKey();

            // Try a cache lookup first
            if (m_meshCache != null && m_meshCache.TryGetRenderingMesh(physicsKey, lod, out mesh))
                return mesh;

            // Can't go any further without a prim renderer
            if (m_renderer == null)
                return null;

            // Convert our DetailLevel to the OpenMetaverse.Rendering DetailLevel
            OpenMetaverse.Rendering.DetailLevel detailLevel;
            switch (lod)
            {
                case DetailLevel.Low:
                    detailLevel = OpenMetaverse.Rendering.DetailLevel.Low;
                    break;
                case DetailLevel.Medium:
                    detailLevel = OpenMetaverse.Rendering.DetailLevel.Medium;
                    break;
                case DetailLevel.High:
                    detailLevel = OpenMetaverse.Rendering.DetailLevel.High;
                    break;
                case DetailLevel.Highest:
                default:
                    detailLevel = OpenMetaverse.Rendering.DetailLevel.Highest;
                    break;
            }

            FacetedMesh facetedMesh = null;

            if (prim.Prim.Sculpt != null && prim.Prim.Sculpt.SculptTexture != UUID.Zero)
            {
                // Sculpty meshing
                Bitmap sculptTexture = GetSculptMap(prim.Prim.Sculpt.SculptTexture);
                if (sculptTexture != null)
                    facetedMesh = m_renderer.GenerateFacetedSculptMesh(prim.Prim, sculptTexture, detailLevel);
            }
            else
            {
                // Basic prim meshing
                facetedMesh = m_renderer.GenerateFacetedMesh(prim.Prim, detailLevel);
            }

            if (facetedMesh != null)
            {
                #region FacetedMesh to RenderingMesh Conversion

                mesh = new RenderingMesh();
                mesh.Faces = new RenderingMesh.Face[facetedMesh.Faces.Count];
                for (int i = 0; i < facetedMesh.Faces.Count; i++)
                {
                    Face face = facetedMesh.Faces[i];

                    Vertex[] vertices = new Vertex[face.Vertices.Count];
                    for (int j = 0; j < face.Vertices.Count; j++)
                    {
                        OpenMetaverse.Rendering.Vertex omvrVertex = face.Vertices[j];
                        vertices[j] = new Vertex { Position = omvrVertex.Position, Normal = omvrVertex.Normal, TexCoord = omvrVertex.TexCoord };
                    }
                    ushort[] indices = face.Indices.ToArray();

                    mesh.Faces[i] = new RenderingMesh.Face { Vertices = vertices, Indices = indices };
                }

                #endregion FacetedMesh to RenderingMesh Conversion

                // Store the result in the mesh cache, if we have one
                if (m_meshCache != null)
                    m_meshCache.StoreRenderingMesh(physicsKey, lod, mesh);

                return mesh;
            }
            else
            {
                return null;
            }
        }
Пример #26
0
        /// <summary>
        /// Generates a a series of faces, each face containing a mesh and
        /// metadata
        /// </summary>
        /// <param name="prim">Primitive to generate the mesh from</param>
        /// <param name="lod">Level of detail to generate the mesh at</param>
        /// <returns>The generated mesh</returns >
        public OMVR.FacetedMesh GenerateFacetedMesh(OMV.Primitive prim, OMVR.DetailLevel lod)
        {
            bool isSphere = ((OMV.ProfileCurve)(prim.PrimData.profileCurve & 0x07) == OMV.ProfileCurve.HalfCircle);
            PrimMesher.PrimMesh newPrim = GeneratePrimMesh(prim, lod, true);
            if (newPrim == null)
                return null;

            // 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>();
            var indexer = newPrim.GetVertexIndexer();

            for (int i = 0; i < indexer.numPrimFaces; i++)
            {
                OMVR.Face oface = new OMVR.Face();
                oface.Vertices = new List<OMVR.Vertex>();
                oface.Indices = new List<ushort>();
                oface.TextureFace = prim.Textures.GetFace((uint)i);

                for (int j = 0; j < indexer.viewerVertices[i].Count; j++)
                {
                    var vert = new OMVR.Vertex();
                    var m = indexer.viewerVertices[i][j];
                    vert.Position = new Vector3(m.v.X, m.v.Y, m.v.Z);
                    vert.Normal = new Vector3(m.n.X, m.n.Y, m.n.Z);
                    vert.TexCoord = new OMV.Vector2(m.uv.U, 1.0f - m.uv.V);
                    oface.Vertices.Add(vert);
                }

                for (int j = 0; j < indexer.viewerPolygons[i].Count; j++)
                {
                    var p = indexer.viewerPolygons[i][j];
                    // Skip "degenerate faces" where the same vertex appears twice in the same tri
                    if (p.v1 == p.v2 || p.v1 == p.v2 || p.v2 == p.v3) continue;
                    oface.Indices.Add((ushort)p.v1);
                    oface.Indices.Add((ushort)p.v2);
                    oface.Indices.Add((ushort)p.v3);
                }

                omvrmesh.Faces.Add(oface);
            }

            return omvrmesh;
        }
Пример #27
0
        /// <summary>
        /// Generates a a series of faces, each face containing a mesh and
        /// metadata
        /// </summary>
        /// <param name="prim">Primitive to generate the mesh from</param>
        /// <param name="lod">Level of detail to generate the mesh at</param>
        /// <returns>The generated mesh</returns >
        public OMVR.FacetedMesh GenerateFacetedMesh(OMV.Primitive prim, OMVR.DetailLevel lod)
        {

            OMV.Primitive.ConstructionData primData = prim.PrimData;
            int sides = 4;
            int hollowsides = 4;

            float profileBegin = primData.ProfileBegin;
            float profileEnd = primData.ProfileEnd;
            bool isSphere = false;

            if ((OMV.ProfileCurve)(primData.profileCurve & 0x07) == OMV.ProfileCurve.Circle)
            {
                switch (lod)
                {
                    case OMVR.DetailLevel.Low:
                        sides = 6;
                        break;
                    case OMVR.DetailLevel.Medium:
                        sides = 12;
                        break;
                    default:
                        sides = 24;
                        break;
                }
            }
            else if ((OMV.ProfileCurve)(primData.profileCurve & 0x07) == OMV.ProfileCurve.EqualTriangle)
                sides = 3;
            else if ((OMV.ProfileCurve)(primData.profileCurve & 0x07) == OMV.ProfileCurve.HalfCircle)
            {
                // half circle, prim is a sphere
                isSphere = true;
                switch (lod)
                {
                    case OMVR.DetailLevel.Low:
                        sides = 6;
                        break;
                    case OMVR.DetailLevel.Medium:
                        sides = 12;
                        break;
                    default:
                        sides = 24;
                        break;
                }
                profileBegin = 0.5f * profileBegin + 0.5f;
                profileEnd = 0.5f * profileEnd + 0.5f;
            }

            if ((OMV.HoleType)primData.ProfileHole == OMV.HoleType.Same)
                hollowsides = sides;
            else if ((OMV.HoleType)primData.ProfileHole == OMV.HoleType.Circle)
            {
                switch (lod)
                {
                    case OMVR.DetailLevel.Low:
                        hollowsides = 6;
                        break;
                    case OMVR.DetailLevel.Medium:
                        hollowsides = 12;
                        break;
                    default:
                        hollowsides = 24;
                        break;
                }
            }
            else if ((OMV.HoleType)primData.ProfileHole == OMV.HoleType.Triangle)
                hollowsides = 3;

            PrimMesher.PrimMesh newPrim = new PrimMesher.PrimMesh(sides, profileBegin, profileEnd, (float)primData.ProfileHollow, hollowsides);
            newPrim.viewerMode = true;
            newPrim.holeSizeX = primData.PathScaleX;
            newPrim.holeSizeY = primData.PathScaleY;
            newPrim.pathCutBegin = primData.PathBegin;
            newPrim.pathCutEnd = primData.PathEnd;
            newPrim.topShearX = primData.PathShearX;
            newPrim.topShearY = primData.PathShearY;
            newPrim.radius = primData.PathRadiusOffset;
            newPrim.revolutions = primData.PathRevolutions;
            newPrim.skew = primData.PathSkew;
            switch (lod)
            {
                case OMVR.DetailLevel.Low:
                    newPrim.stepsPerRevolution = 6;
                    break;
                case OMVR.DetailLevel.Medium:
                    newPrim.stepsPerRevolution = 12;
                    break;
                default:
                    newPrim.stepsPerRevolution = 24;
                    break;
            }

            if ((primData.PathCurve == OMV.PathCurve.Line) || (primData.PathCurve == OMV.PathCurve.Flexible))
            {
                newPrim.taperX = 1.0f - primData.PathScaleX;
                newPrim.taperY = 1.0f - primData.PathScaleY;
                newPrim.twistBegin = (int)(180 * primData.PathTwistBegin);
                newPrim.twistEnd = (int)(180 * primData.PathTwist);
                newPrim.ExtrudeLinear();
            }
            else
            {
                newPrim.taperX = primData.PathTaperX;
                newPrim.taperY = primData.PathTaperY;
                newPrim.twistBegin = (int)(360 * primData.PathTwistBegin);
                newPrim.twistEnd = (int)(360 * primData.PathTwist);
                newPrim.ExtrudeCircular();
            }

            int numViewerFaces = newPrim.viewerFaces.Count;
            int numPrimFaces = newPrim.numPrimFaces;

            for (uint i = 0; i < numViewerFaces; i++)
            {
                PrimMesher.ViewerFace vf = newPrim.viewerFaces[(int)i];

                if (isSphere)
                {
                    vf.uv1.U = (vf.uv1.U - 0.5f) * 2.0f;
                    vf.uv2.U = (vf.uv2.U - 0.5f) * 2.0f;
                    vf.uv3.U = (vf.uv3.U - 0.5f) * 2.0f;
                }
            }
            if (m_shouldScale)
            {
                newPrim.Scale(prim.Scale.X, prim.Scale.Y, prim.Scale.Z);
            }

            // 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<OMV.Vector3, int> vertexAccount = new Dictionary<OMV.Vector3, int>();
            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;
                vertexAccount.Clear();
                OMV.Vector3 pos;
                int indx;
                OMVR.Vertex vert;
                foreach (PrimMesher.ViewerFace vface in newPrim.viewerFaces)
                {
                    if (vface.primFaceNumber == ii)
                    {
                        faceVertices++;
                        pos = new OMV.Vector3(vface.v1.X, vface.v1.Y, vface.v1.Z);
                        if (vertexAccount.ContainsKey(pos))
                        {
                            // we aleady have this vertex in the list. Just point the index at it
                            oface.Indices.Add((ushort)vertexAccount[pos]);
                        }
                        else
                        {
                            // the vertex is not in the list. Add it and the new index.
                            vert = new OMVR.Vertex();
                            vert.Position = pos;
                            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);
                            indx = oface.Vertices.Count - 1;
                            vertexAccount.Add(pos, indx);
                            oface.Indices.Add((ushort)indx);
                        }

                        pos = new OMV.Vector3(vface.v2.X, vface.v2.Y, vface.v2.Z);
                        if (vertexAccount.ContainsKey(pos))
                        {
                            oface.Indices.Add((ushort)vertexAccount[pos]);
                        }
                        else
                        {
                            vert = new OMVR.Vertex();
                            vert.Position = pos;
                            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);
                            indx = oface.Vertices.Count - 1;
                            vertexAccount.Add(pos, indx);
                            oface.Indices.Add((ushort)indx);
                        }

                        pos = new OMV.Vector3(vface.v3.X, vface.v3.Y, vface.v3.Z);
                        if (vertexAccount.ContainsKey(pos))
                        {
                            oface.Indices.Add((ushort)vertexAccount[pos]);
                        }
                        else
                        {
                            vert = new OMVR.Vertex();
                            vert.Position = pos;
                            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);
                            indx = oface.Vertices.Count - 1;
                            vertexAccount.Add(pos, indx);
                            oface.Indices.Add((ushort)indx);
                        }
                    }
                }
                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;
        }
Пример #28
0
        void AddFacesFromPolyList(polylist list, mesh mesh, ModelPrim prim, Matrix4 transform)
        {
            string material = list.material;
            source posSrc = null;
            source normalSrc = null;
            source uvSrc = null;

            ulong stride = 0;
            int posOffset = -1;
            int norOffset = -1;
            int uvOffset = -1;

            foreach (var inp in list.input)
            {
                stride = Math.Max(stride, inp.offset);

                if (inp.semantic == "VERTEX")
                {
                    posSrc = FindSource(mesh.source, mesh.vertices.input[0].source);
                    posOffset = (int)inp.offset;
                }
                else if (inp.semantic == "NORMAL")
                {
                    normalSrc = FindSource(mesh.source, inp.source);
                    norOffset = (int)inp.offset;
                }
                else if (inp.semantic == "TEXCOORD")
                {
                    uvSrc = FindSource(mesh.source, inp.source);
                    uvOffset = (int)inp.offset;
                }
            }

            stride += 1;

            if (posSrc == null) return;

            var vcount = StrToArray(list.vcount);
            var idx = StrToArray(list.p);

            Vector3[] normals = null;
            if (normalSrc != null)
            {
                var norVal = ((float_array)normalSrc.Item).Values;
                normals = new Vector3[norVal.Length / 3];

                for (int i = 0; i < normals.Length; i++)
                {
                    normals[i] = new Vector3((float)norVal[i * 3 + 0], (float)norVal[i * 3 + 1], (float)norVal[i * 3 + 2]);
                    normals[i] = Vector3.TransformNormal(normals[i], transform);
                    normals[i].Normalize();
                }
            }

            Vector2[] uvs = null;
            if (uvSrc != null)
            {
                var uvVal = ((float_array)uvSrc.Item).Values;
                uvs = new Vector2[uvVal.Length / 2];

                for (int i = 0; i < uvs.Length; i++)
                {
                    uvs[i] = new Vector2((float)uvVal[i * 2 + 0], (float)uvVal[i * 2 + 1]);
                }

            }

            ModelFace face = new ModelFace();
            face.MaterialID = list.material;
            if (face.MaterialID != null)
            {
                if (MatSymTarget.ContainsKey(list.material))
                {
                    ModelMaterial mat = Materials.Find(m => m.ID == MatSymTarget[list.material]);
                    if (mat != null)
                    {
                        face.Material = mat;
                    }
                }
            }

            int curIdx = 0;

            for (int i = 0; i < vcount.Length; i++)
            {
                var nvert = vcount[i];
                if (nvert < 3 || nvert > 4)
                {
                    throw new InvalidDataException("Only triangles and quads supported");
                }

                Vertex[] verts = new Vertex[nvert];
                for (int j = 0; j < nvert; j++)
                {
                    verts[j].Position = prim.Positions[idx[curIdx + posOffset + (int)stride * j]];

                    if (normals != null)
                    {
                        verts[j].Normal = normals[idx[curIdx + norOffset + (int)stride * j]];
                    }

                    if (uvs != null)
                    {
                        verts[j].TexCoord = uvs[idx[curIdx + uvOffset + (int)stride * j]];
                    }
                }


                if (nvert == 3) // add the triangle
                {
                    face.AddVertex(verts[0]);
                    face.AddVertex(verts[1]);
                    face.AddVertex(verts[2]);
                }
                else if (nvert == 4) // quad, add two triangles
                {
                    face.AddVertex(verts[0]);
                    face.AddVertex(verts[1]);
                    face.AddVertex(verts[2]);

                    face.AddVertex(verts[0]);
                    face.AddVertex(verts[2]);
                    face.AddVertex(verts[3]);
                }

                curIdx += (int)stride * nvert;
            }

            prim.Faces.Add(face);


        }
        private OMVR.FacetedMesh GenerateIRendererMesh(int numPrimFaces, OMV.Primitive prim,
                                                       List <PrimMesher.ViewerFace> viewerFaces)
        {
            // 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 <OMV.Vector3, int> vertexAccount = new Dictionary <OMV.Vector3, int>();

            OMV.Vector3 pos;
            int         indx;

            OMVR.Vertex vert;
            for (int ii = 0; ii < numPrimFaces; ii++)
            {
                OMVR.Face oface = new OMVR.Face();
                oface.Vertices = new List <OMVR.Vertex>();
                oface.Indices  = new List <ushort>();
                if (prim.Textures == null)
                {
                    oface.TextureFace = null;
                }
                else
                {
                    oface.TextureFace = prim.Textures.GetFace((uint)ii);
                }
                int faceVertices = 0;
                vertexAccount.Clear();
                foreach (PrimMesher.ViewerFace vface in viewerFaces)
                {
                    if (vface.primFaceNumber == ii)
                    {
                        faceVertices++;
                        pos = new OMV.Vector3(vface.v1.X, vface.v1.Y, vface.v1.Z);
                        if (vertexAccount.ContainsKey(pos))
                        {
                            oface.Indices.Add((ushort)vertexAccount[pos]);
                        }
                        else
                        {
                            vert          = new OMVR.Vertex();
                            vert.Position = pos;
                            vert.TexCoord = new OMV.Vector2(vface.uv1.U, vface.uv1.V);
                            vert.Normal   = new OMV.Vector3(vface.n1.X, vface.n1.Y, vface.n1.Z);
                            vert.Normal.Normalize();
                            oface.Vertices.Add(vert);
                            indx = oface.Vertices.Count - 1;
                            vertexAccount.Add(pos, indx);
                            oface.Indices.Add((ushort)indx);
                        }

                        pos = new OMV.Vector3(vface.v2.X, vface.v2.Y, vface.v2.Z);
                        if (vertexAccount.ContainsKey(pos))
                        {
                            oface.Indices.Add((ushort)vertexAccount[pos]);
                        }
                        else
                        {
                            vert          = new OMVR.Vertex();
                            vert.Position = pos;
                            vert.TexCoord = new OMV.Vector2(vface.uv2.U, vface.uv2.V);
                            vert.Normal   = new OMV.Vector3(vface.n2.X, vface.n2.Y, vface.n2.Z);
                            vert.Normal.Normalize();
                            oface.Vertices.Add(vert);
                            indx = oface.Vertices.Count - 1;
                            vertexAccount.Add(pos, indx);
                            oface.Indices.Add((ushort)indx);
                        }

                        pos = new OMV.Vector3(vface.v3.X, vface.v3.Y, vface.v3.Z);
                        if (vertexAccount.ContainsKey(pos))
                        {
                            oface.Indices.Add((ushort)vertexAccount[pos]);
                        }
                        else
                        {
                            vert          = new OMVR.Vertex();
                            vert.Position = pos;
                            vert.TexCoord = new OMV.Vector2(vface.uv3.U, vface.uv3.V);
                            vert.Normal   = new OMV.Vector3(vface.n3.X, vface.n3.Y, vface.n3.Z);
                            vert.Normal.Normalize();
                            oface.Vertices.Add(vert);
                            indx = oface.Vertices.Count - 1;
                            vertexAccount.Add(pos, indx);
                            oface.Indices.Add((ushort)indx);
                        }
                    }
                }
                if (faceVertices > 0)
                {
                    oface.TextureFace = null;
                    if (prim.Textures != null)
                    {
                        oface.TextureFace = prim.Textures.FaceTextures[ii];
                        if (oface.TextureFace == null)
                        {
                            oface.TextureFace = prim.Textures.DefaultTexture;
                        }
                    }
                    oface.ID = ii;
                    omvrmesh.Faces.Add(oface);
                }
            }

            return(omvrmesh);
        }
Пример #30
0
        /// <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;
        }
Пример #31
0
        /// <summary>
        /// Decodes mesh asset into FacetedMesh
        /// </summary>
        /// <param name="prim">Mesh primitive</param>
        /// <param name="meshAsset">Asset retrieved from the asset server</param>
        /// <param name="LOD">Level of detail</param>
        /// <param name="mesh">Resulting decoded FacetedMesh</param>
        /// <returns>True if mesh asset decoding was successful</returns>
        public static bool TryDecodeFromAsset(Primitive prim, AssetMesh meshAsset, DetailLevel LOD, out FacetedMesh mesh)
        {
            mesh = null;

            try
            {
                if (!meshAsset.Decode())
                {
                    return false;
                }

                OSDMap MeshData = meshAsset.MeshData;

                mesh = new FacetedMesh();

                mesh.Faces = new List<Face>();
                mesh.Prim = prim;
                mesh.Profile.Faces = new List<ProfileFace>();
                mesh.Profile.Positions = new List<Vector3>();
                mesh.Path.Points = new List<PathPoint>();

                OSD facesOSD = null;

                switch (LOD)
                {
                    default:
                    case DetailLevel.Highest:
                        facesOSD = MeshData["high_lod"];
                        break;

                    case DetailLevel.High:
                        facesOSD = MeshData["medium_lod"];
                        break;

                    case DetailLevel.Medium:
                        facesOSD = MeshData["low_lod"];
                        break;

                    case DetailLevel.Low:
                        facesOSD = MeshData["lowest_lod"];
                        break;
                }

                if (facesOSD == null || !(facesOSD is OSDArray))
                {
                    return false;
                }

                OSDArray decodedMeshOsdArray = (OSDArray)facesOSD;

                for (int faceNr = 0; faceNr < decodedMeshOsdArray.Count; faceNr++)
                {
                    OSD subMeshOsd = decodedMeshOsdArray[faceNr];

                    // Decode each individual face
                    if (subMeshOsd is OSDMap)
                    {
                        Face oface = new Face();
                        oface.ID = faceNr;
                        oface.Vertices = new List<Vertex>();
                        oface.Indices = new List<ushort>();
                        oface.TextureFace = prim.Textures.GetFace((uint)faceNr);

                        OSDMap subMeshMap = (OSDMap)subMeshOsd;

                        Vector3 posMax;
                        Vector3 posMin;

                        // If PositionDomain is not specified, the default is from -0.5 to 0.5
                        if (subMeshMap.ContainsKey("PositionDomain"))
                        {
                            posMax = ((OSDMap)subMeshMap["PositionDomain"])["Max"];
                            posMin = ((OSDMap)subMeshMap["PositionDomain"])["Min"];
                        }
                        else
                        {
                            posMax = new Vector3(0.5f, 0.5f, 0.5f);
                            posMin = new Vector3(-0.5f, -0.5f, -0.5f);
                        }

                        // Vertex positions
                        byte[] posBytes = subMeshMap["Position"];

                        // Normals
                        byte[] norBytes = null;
                        if (subMeshMap.ContainsKey("Normal"))
                        {
                            norBytes = subMeshMap["Normal"];
                        }

                        // UV texture map
                        Vector2 texPosMax = Vector2.Zero;
                        Vector2 texPosMin = Vector2.Zero;
                        byte[] texBytes = null;
                        if (subMeshMap.ContainsKey("TexCoord0"))
                        {
                            texBytes = subMeshMap["TexCoord0"];
                            texPosMax = ((OSDMap)subMeshMap["TexCoord0Domain"])["Max"];
                            texPosMin = ((OSDMap)subMeshMap["TexCoord0Domain"])["Min"];
                        }

                        // Extract the vertex position data
                        // If present normals and texture coordinates too
                        for (int i = 0; i < posBytes.Length; i += 6)
                        {
                            ushort uX = Utils.BytesToUInt16(posBytes, i);
                            ushort uY = Utils.BytesToUInt16(posBytes, i + 2);
                            ushort uZ = Utils.BytesToUInt16(posBytes, i + 4);

                            Vertex vx = new Vertex();

                            vx.Position = new Vector3(
                                Utils.UInt16ToFloat(uX, posMin.X, posMax.X),
                                Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y),
                                Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z));

                            if (norBytes != null && norBytes.Length >= i + 4)
                            {
                                ushort nX = Utils.BytesToUInt16(norBytes, i);
                                ushort nY = Utils.BytesToUInt16(norBytes, i + 2);
                                ushort nZ = Utils.BytesToUInt16(norBytes, i + 4);

                                vx.Normal = new Vector3(
                                    Utils.UInt16ToFloat(nX, posMin.X, posMax.X),
                                    Utils.UInt16ToFloat(nY, posMin.Y, posMax.Y),
                                    Utils.UInt16ToFloat(nZ, posMin.Z, posMax.Z));
                            }

                            var vertexIndexOffset = oface.Vertices.Count * 4;

                            if (texBytes != null && texBytes.Length >= vertexIndexOffset + 4)
                            {
                                ushort tX = Utils.BytesToUInt16(texBytes, vertexIndexOffset);
                                ushort tY = Utils.BytesToUInt16(texBytes, vertexIndexOffset + 2);

                                vx.TexCoord = new Vector2(
                                    Utils.UInt16ToFloat(tX, texPosMin.X, texPosMax.X),
                                    Utils.UInt16ToFloat(tY, texPosMin.Y, texPosMax.Y));
                            }

                            oface.Vertices.Add(vx);
                        }

                        byte[] triangleBytes = subMeshMap["TriangleList"];
                        for (int i = 0; i < triangleBytes.Length; i += 6)
                        {
                            ushort v1 = (ushort)(Utils.BytesToUInt16(triangleBytes, i));
                            oface.Indices.Add(v1);
                            ushort v2 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 2));
                            oface.Indices.Add(v2);
                            ushort v3 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 4));
                            oface.Indices.Add(v3);
                        }

                        mesh.Faces.Add(oface);
                    }
                }

            }
            catch (Exception ex)
            {
                Logger.Log("Failed to decode mesh asset: " + ex.Message, Helpers.LogLevel.Warning);
                return false;
            }

            return true;
        }
Пример #32
0
        private static void CreateCap(ref Face face, List<Vertex> primVertices, Path path, Profile profile)
        {
            int i;
            int numVertices = profile.Positions.Count;
            //int numIndices = (numVertices - 2) * 3;

            int maxS = profile.Positions.Count;
            int maxT = path.Points.Count;

            face.Center = Vector3.Zero;

            int offset = 0;
            if ((face.Mask & FaceMask.Top) != 0)
                offset = (maxT - 1) * maxS;
            else
                offset = face.BeginS;

            // Figure out the normal, assume all caps are flat faces.
            // Cross product to get normals
            Vector2 cuv;
            Vector2 minUV = Vector2.Zero;
            Vector2 maxUV = Vector2.Zero;

            // Copy the vertices into the array
            for (i = 0; i < numVertices; i++)
            {
                Vertex vertex = new Vertex();

                if ((face.Mask & FaceMask.Top) != 0)
                {
                    vertex.Position = primVertices[i + offset].Position;
                    vertex.TexCoord.X = profile.Positions[i].X + 0.5f;
                    vertex.TexCoord.Y = profile.Positions[i].Y + 0.5f;
                }
                else
                {
                    // Mirror for underside
                    vertex.Position = primVertices[(numVertices - 1) - i].Position;
                    vertex.TexCoord.X = profile.Positions[i].X + 0.5f;
                    vertex.TexCoord.Y = 0.5f - profile.Positions[i].Y;
                }

                if (i == 0)
                {
                    face.MinExtent = face.MaxExtent = primVertices[offset].Position;
                    minUV = maxUV = primVertices[offset].TexCoord;
                }
                else
                {
                    UpdateMinMax(ref face, vertex.Position);
                    UpdateMinMax(ref minUV, ref maxUV, vertex.TexCoord);
                }

                face.Vertices.Add(vertex);
            }

            face.Center = (face.MinExtent + face.MaxExtent) * 0.5f;
            cuv = (minUV + maxUV) * 0.5f;

            Vector3 binormal = CalcBinormalFromTriangle(
                face.Center, cuv,
                face.Vertices[0].Position, face.Vertices[0].TexCoord,
                face.Vertices[1].Position, face.Vertices[1].TexCoord);
            binormal.Normalize();

            Vector3 d0 = face.Center - face.Vertices[0].Position;
            Vector3 d1 = face.Center - face.Vertices[1].Position;
            Vector3 normal = ((face.Mask & FaceMask.Top) != 0) ? (d0 % d1) : (d1 % d0);
            normal.Normalize();

            // If not hollow and not open create a center point in the cap
            if ((face.Mask & FaceMask.Hollow) == 0 && (face.Mask & FaceMask.Open) == 0)
            {
                Vertex vertex = new Vertex();
                vertex.Position = face.Center;
                vertex.Normal = normal;
                vertex.Binormal = binormal;
                vertex.TexCoord = cuv;

                face.Vertices.Add(vertex);
                numVertices++;
            }

            for (i = 0; i < numVertices; i++)
            {
                Vertex vertex = face.Vertices[i];
                vertex.Binormal = binormal;
                vertex.Normal = normal;
                face.Vertices[i] = vertex;
            }

            if ((face.Mask & FaceMask.Hollow) != 0)
            {
                if ((face.Mask & FaceMask.Top) != 0)
                {
                    // HOLLOW TOP
                    int pt1 = 0;
                    int pt2 = numVertices - 1;
                    i = 0;

                    while (pt2 - pt1 > 1)
                    {
                        if (use_tri_1a2(profile, pt1, pt2))
                        {
                            face.Indices.Add((ushort)pt1);
                            face.Indices.Add((ushort)(pt1 + 1));
                            face.Indices.Add((ushort)pt2);
                            pt1++;
                        }
                        else
                        {
                            face.Indices.Add((ushort)pt1);
                            face.Indices.Add((ushort)(pt2 - 1));
                            face.Indices.Add((ushort)pt2);
                            pt2--;
                        }
                    }
                }
                else
                {
                    // HOLLOW BOTTOM
                    int pt1 = 0;
                    int pt2 = numVertices - 1;
                    i = 0;

                    while (pt2 - pt1 > 1)
                    {
                        // Flipped backfacing from top
                        if (use_tri_1a2(profile, pt1, pt2))
                        {
                            face.Indices.Add((ushort)pt1);
                            face.Indices.Add((ushort)pt2);
                            face.Indices.Add((ushort)(pt1 + 1));
                            pt1++;
                        }
                        else
                        {
                            face.Indices.Add((ushort)pt1);
                            face.Indices.Add((ushort)pt2);
                            face.Indices.Add((ushort)(pt2 - 1));
                            pt2--;
                        }
                    }
                }
            }
            else
            {
                // SOLID OPEN TOP
                // SOLID CLOSED TOP
                // SOLID OPEN BOTTOM
                // SOLID CLOSED BOTTOM

                // Not hollow, generate the triangle fan.
                // This is a tri-fan, so we reuse the same first point for all triangles
                for (i = 0; i < numVertices - 2; i++)
                {
                    face.Indices.Add((ushort)(numVertices - 1));
                    face.Indices.Add((ushort)i);
                    face.Indices.Add((ushort)(i + 1));
                }
            }
        }
Пример #33
0
        private OMVR.FacetedMesh GenerateIRendererMesh(int numPrimFaces, OMV.Primitive prim, 
                                             List<PrimMesher.ViewerFace> viewerFaces)
        {
            // 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<OMV.Vector3, int> vertexAccount = new Dictionary<OMV.Vector3, int>();
            OMV.Vector3 pos;
            int indx;
            OMVR.Vertex vert;
            for (int ii=0; ii<numPrimFaces; ii++) {
            OMVR.Face oface = new OMVR.Face();
            oface.Vertices = new List<OMVR.Vertex>();
            oface.Indices = new List<ushort>();
            if (prim.Textures == null) {
                oface.TextureFace = null;
            }
            else {
                oface.TextureFace = prim.Textures.GetFace((uint)ii);
            }
            int faceVertices = 0;
            vertexAccount.Clear();
            foreach (PrimMesher.ViewerFace vface in viewerFaces) {
                if (vface.primFaceNumber == ii) {
                    faceVertices++;
                    pos = new OMV.Vector3(vface.v1.X, vface.v1.Y, vface.v1.Z);
                    if (vertexAccount.ContainsKey(pos)) {
                        oface.Indices.Add((ushort)vertexAccount[pos]);
                    }
                    else {
                        vert = new OMVR.Vertex();
                        vert.Position = pos;
                        vert.TexCoord = new OMV.Vector2(vface.uv1.U, vface.uv1.V);
                        vert.Normal = new OMV.Vector3(vface.n1.X, vface.n1.Y, vface.n1.Z);
                        vert.Normal.Normalize();
                        oface.Vertices.Add(vert);
                        indx = oface.Vertices.Count - 1;
                        vertexAccount.Add(pos, indx);
                        oface.Indices.Add((ushort)indx);
                    }

                    pos = new OMV.Vector3(vface.v2.X, vface.v2.Y, vface.v2.Z);
                    if (vertexAccount.ContainsKey(pos)) {
                        oface.Indices.Add((ushort)vertexAccount[pos]);
                    }
                    else {
                        vert = new OMVR.Vertex();
                        vert.Position = pos;
                        vert.TexCoord = new OMV.Vector2(vface.uv2.U, vface.uv2.V);
                        vert.Normal = new OMV.Vector3(vface.n2.X, vface.n2.Y, vface.n2.Z);
                        vert.Normal.Normalize();
                        oface.Vertices.Add(vert);
                        indx = oface.Vertices.Count - 1;
                        vertexAccount.Add(pos, indx);
                        oface.Indices.Add((ushort)indx);
                    }

                    pos = new OMV.Vector3(vface.v3.X, vface.v3.Y, vface.v3.Z);
                    if (vertexAccount.ContainsKey(pos)) {
                        oface.Indices.Add((ushort)vertexAccount[pos]);
                    }
                    else {
                        vert = new OMVR.Vertex();
                        vert.Position = pos;
                        vert.TexCoord = new OMV.Vector2(vface.uv3.U, vface.uv3.V);
                        vert.Normal = new OMV.Vector3(vface.n3.X, vface.n3.Y, vface.n3.Z);
                        vert.Normal.Normalize();
                        oface.Vertices.Add(vert);
                        indx = oface.Vertices.Count - 1;
                        vertexAccount.Add(pos, indx);
                        oface.Indices.Add((ushort)indx);
                    }
                }
            }
            if (faceVertices > 0) {
                oface.TextureFace = null;
                if (prim.Textures != null) {
                    oface.TextureFace = prim.Textures.FaceTextures[ii];
                    if (oface.TextureFace == null) {
                        oface.TextureFace = prim.Textures.DefaultTexture;
                    }
                }
                oface.ID = ii;
                omvrmesh.Faces.Add(oface);
            }
            }

            return omvrmesh;
        }
Пример #34
0
        private static void CreateUnCutCubeCap(ref Face face, List<Vertex> primVertices, Path path, Profile profile)
        {
            int maxS = profile.Positions.Count;
            int maxT = path.Points.Count;

            int gridSize = (profile.Positions.Count - 1) / 4;
            int quadCount = gridSize * gridSize;
            //int numVertices = (gridSize + 1) * (gridSize + 1);
            //int numIndices = quadCount * 4;

            int offset = 0;
            if ((face.Mask & FaceMask.Top) != 0)
                offset = (maxT - 1) * maxS;
            else
                offset = face.BeginS;

            Vertex[] corners = new Vertex[4];
            Vertex baseVert;

            for (int t = 0; t < 4; t++)
            {
                corners[t].Position = primVertices[offset + (gridSize * t)].Position;
                corners[t].TexCoord.X = profile.Positions[gridSize * t].X + 0.5f;
                corners[t].TexCoord.Y = 0.5f - profile.Positions[gridSize * t].Y;
            }

            baseVert.Normal =
                ((corners[1].Position - corners[0].Position) %
                (corners[2].Position - corners[1].Position));
            baseVert.Normal = Vector3.Normalize(baseVert.Normal);

            if ((face.Mask & FaceMask.Top) != 0)
            {
                baseVert.Normal *= -1f;
            }
            else
            {
                // Swap the UVs on the U(X) axis for top face
                Vector2 swap;

                swap = corners[0].TexCoord;
                corners[0].TexCoord = corners[3].TexCoord;
                corners[3].TexCoord = swap;

                swap = corners[1].TexCoord;
                corners[1].TexCoord = corners[2].TexCoord;
                corners[2].TexCoord = swap;
            }

            baseVert.Binormal = CalcBinormalFromTriangle(
                corners[0].Position, corners[0].TexCoord,
                corners[1].Position, corners[1].TexCoord,
                corners[2].Position, corners[2].TexCoord);

            for (int t = 0; t < 4; t++)
            {
                corners[t].Binormal = baseVert.Binormal;
                corners[t].Normal = baseVert.Normal;
            }

            int vtop = face.Vertices.Count;

            for (int gx = 0; gx < gridSize + 1; gx++)
            {
                for (int gy = 0; gy < gridSize + 1; gy++)
                {
                    Vertex newVert = new Vertex();
                    LerpPlanarVertex(
                        corners[0],
                        corners[1],
                        corners[3],
                        ref newVert,
                        (float)gx / (float)gridSize,
                        (float)gy / (float)gridSize);

                    face.Vertices.Add(newVert);

                    if (gx == 0 && gy == 0)
                        face.MinExtent = face.MaxExtent = newVert.Position;
                    else
                        UpdateMinMax(ref face, newVert.Position);
                }
            }

            face.Center = (face.MinExtent + face.MaxExtent) * 0.5f;

            int[] idxs = new int[] { 0, 1, gridSize + 2, gridSize + 2, gridSize + 1, 0 };

            for (int gx = 0; gx < gridSize; gx++)
            {
                for (int gy = 0; gy < gridSize; gy++)
                {
                    if ((face.Mask & FaceMask.Top) != 0)
                    {
                        for (int i = 5; i >= 0; i--)
                            face.Indices.Add((ushort)(vtop + (gy * (gridSize + 1)) + gx + idxs[i]));
                    }
                    else
                    {
                        for (int i = 0; i < 6; i++)
                            face.Indices.Add((ushort)(vtop + (gy * (gridSize + 1)) + gx + idxs[i]));
                    }
                }
            }
        }
Пример #35
0
        /// <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(Primitive prim, Bitmap scupltTexture, DetailLevel lod)
        {
            LibreMetaverse.PrimMesher.SculptMesh.SculptType smSculptType;
            switch (prim.Sculpt.Type)
            {
            case SculptType.Cylinder:
                smSculptType = LibreMetaverse.PrimMesher.SculptMesh.SculptType.cylinder;
                break;

            case SculptType.Plane:
                smSculptType = LibreMetaverse.PrimMesher.SculptMesh.SculptType.plane;
                break;

            case SculptType.Sphere:
                smSculptType = LibreMetaverse.PrimMesher.SculptMesh.SculptType.sphere;
                break;

            case SculptType.Torus:
                smSculptType = LibreMetaverse.PrimMesher.SculptMesh.SculptType.torus;
                break;

            default:
                smSculptType = LibreMetaverse.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;
            }
            LibreMetaverse.PrimMesher.SculptMesh newMesh =
                new LibreMetaverse.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
            FacetedMesh omvrmesh = new OMVR.FacetedMesh
            {
                Faces   = new List <OMVR.Face>(),
                Prim    = prim,
                Profile = new OMVR.Profile
                {
                    Faces     = new List <OMVR.ProfileFace>(),
                    Positions = new List <OMV.Vector3>()
                },
                Path = new OMVR.Path {
                    Points = new List <OMVR.PathPoint>()
                }
            };

            for (int ii = 0; ii < numPrimFaces; ii++)
            {
                Face oface = new OMVR.Face
                {
                    Vertices    = new List <OMVR.Vertex>(),
                    Indices     = new List <ushort>(),
                    TextureFace = prim.Textures.GetFace((uint)ii)
                };
                int faceVertices = newMesh.coords.Count;

                for (int j = 0; j < faceVertices; j++)
                {
                    var vert = new OMVR.Vertex
                    {
                        Position = new Vector3(newMesh.coords[j].X, newMesh.coords[j].Y, newMesh.coords[j].Z),
                        Normal   = new Vector3(newMesh.normals[j].X, newMesh.normals[j].Y, newMesh.normals[j].Z),
                        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] ?? prim.Textures.DefaultTexture;
                    oface.ID          = ii;
                    omvrmesh.Faces.Add(oface);
                }
            }

            return(omvrmesh);
        }
Пример #36
0
        private List<Vertex> GenerateVertices()
        {
            List<Vertex> vertices = new List<Vertex>(8);

            Vertex v = new Vertex();

            // FIXME: Implement these
            v.Normal = Vector3.Zero;
            v.TexCoord = Vector2.Zero;

            v.Position = new Vector3(0.5f, 0.5f, -0.5f);
            vertices.Add(v);
            v.Position = new Vector3(0.5f, -0.5f, -0.5f);
            vertices.Add(v);
            v.Position = new Vector3(-0.5f, -0.5f, -0.5f);
            vertices.Add(v);
            v.Position = new Vector3(-0.5f, 0.5f, -0.5f);
            vertices.Add(v);
            v.Position = new Vector3(0.5f, 0.5f, 0.5f);
            vertices.Add(v);
            v.Position = new Vector3(0.5f, -0.5f, 0.5f);
            vertices.Add(v);
            v.Position = new Vector3(-0.5f, -0.5f, 0.5f);
            vertices.Add(v);
            v.Position = new Vector3(-0.5f, 0.5f, 0.5f);
            vertices.Add(v);

            return vertices;
        }
Пример #37
0
        /// <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);
        }