Example #1
0
        private static void BuildFace(ref Face face, LLObject.ObjectData prim, List<Vertex> vertices, Path path,
            Profile profile, LLObject.TextureEntryFace teFace)
        {
            if (teFace != null)
                face.TextureFace = teFace;
            else
                throw new ArgumentException("teFace cannot be null");

            face.Vertices.Clear();

            if ((face.Mask & FaceMask.Cap) != 0)
            {
                if (((face.Mask & FaceMask.Hollow) == 0) &&
                    ((face.Mask & FaceMask.Open) == 0) &&
                    (prim.PathBegin == 0f) &&
                    (prim.ProfileCurve == LLObject.ProfileCurve.Square) &&
                    (prim.PathCurve == LLObject.PathCurve.Line))
                {
                    CreateUnCutCubeCap(ref face, vertices, path, profile);
                }
                else
                {
                    CreateCap(ref face, vertices, path, profile);
                }
            }
            else if ((face.Mask & FaceMask.End) != 0 || (face.Mask & FaceMask.Side) != 0)
            {
                CreateSide(ref face, prim, vertices, path, profile);
            }
            else
            {
                throw new RenderingException("Unknown/uninitialized face type");
            }
        }
        /// <summary>
        /// Method for generating mesh Face from a heightmap
        /// </summary>
        /// <param name="zMap">Two dimension array of floats containing height information</param>
        /// <param name="xBegin">Starting value for X</param>
        /// <param name="xEnd">Max value for X</param>
        /// <param name="yBegin">Starting value for Y</param>
        /// <param name="yEnd">Max value of Y</param>
        /// <returns></returns>
        public OMVR.Face TerrainMesh(float[,] zMap, float xBegin, float xEnd, float yBegin, float yEnd)
        {
            PrimMesher.SculptMesh newMesh = new PrimMesher.SculptMesh(zMap, xBegin, xEnd, yBegin, yEnd, true);
            OMVR.Face             terrain = new OMVR.Face();
            int faceVertices = newMesh.coords.Count;

            terrain.Vertices = new List <Vertex>(faceVertices);
            terrain.Indices  = new List <ushort>(newMesh.faces.Count * 3);

            for (int j = 0; j < faceVertices; j++)
            {
                var vert = new OMVR.Vertex();
                vert.Position = new Vector3(newMesh.coords[j].X, newMesh.coords[j].Y, newMesh.coords[j].Z);
                vert.Normal   = new Vector3(newMesh.normals[j].X, newMesh.normals[j].Y, newMesh.normals[j].Z);
                vert.TexCoord = new Vector2(newMesh.uvs[j].U, newMesh.uvs[j].V);
                terrain.Vertices.Add(vert);
            }

            for (int j = 0; j < newMesh.faces.Count; j++)
            {
                terrain.Indices.Add((ushort)newMesh.faces[j].v1);
                terrain.Indices.Add((ushort)newMesh.faces[j].v2);
                terrain.Indices.Add((ushort)newMesh.faces[j].v3);
            }

            return(terrain);
        }
        /// <summary>
        /// Create a 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);
        }
Example #4
0
        // Returns an ExtendedPrimGroup with a mesh for the passed heightmap.
        // Note that the returned EPG does not include any face information -- the caller must add a texture.
        public DisplayableRenderable MeshFromHeightMap(float[,] pHeightMap, int regionSizeX, int regionSizeY,
                                                       IAssetFetcher assetFetcher, OMV.Primitive.TextureEntryFace defaultTexture)
        {
            // OMVR.Face rawMesh = m_mesher.TerrainMesh(pHeightMap, 0, pHeightMap.GetLength(0)-1, 0, pHeightMap.GetLength(1)-1);
            ConvOAR.Globals.log.DebugFormat("{0} MeshFromHeightMap: heightmap=<{1},{2}>, regionSize=<{3},{4}>",
                                            _logHeader, pHeightMap.GetLength(0), pHeightMap.GetLength(1), regionSizeX, regionSizeY);
            OMVR.Face rawMesh = ConvoarTerrain.TerrainMesh(pHeightMap, (float)regionSizeX, (float)regionSizeY);

            RenderableMesh rm = ConvertFaceToRenderableMesh(rawMesh, assetFetcher, defaultTexture, new OMV.Vector3(1, 1, 1));

            RenderableMeshGroup rmg = new RenderableMeshGroup();

            rmg.meshes.Add(rm);

            return(rmg);
        }
Example #5
0
 public MaterialInfo(OMVR.Face face, OMV.Primitive.TextureEntryFace defaultTexture)
 {
     handle      = new EntityHandleUUID();
     faceTexture = face.TextureFace;
     if (faceTexture == null)
     {
         faceTexture = defaultTexture;
     }
     textureID = faceTexture.TextureID;
     if (faceTexture.RGBA.A != 1f)
     {
         fullAlpha = true;
     }
     RGBA     = faceTexture.RGBA;
     bump     = faceTexture.Bump;
     glow     = faceTexture.Glow;
     shiny    = faceTexture.Shiny;
     twoSided = ConvOAR.Globals.parms.P <bool>("DoubleSided");
 }
        /// <summary>
        /// Generates a sculpt mesh structure from a primitive
        /// </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.SimpleMesh GenerateSimpleSculptMesh(OMV.Primitive prim, Bitmap bits, OMVR.DetailLevel lod)
        {
            OMVR.FacetedMesh faceted = GenerateFacetedSculptMesh(prim, bits, lod);

            if (faceted != null && faceted.Faces.Count == 1)
            {
                OMVR.Face face = faceted.Faces[0];

                OMVR.SimpleMesh mesh = new OMVR.SimpleMesh();
                mesh.Indices  = face.Indices;
                mesh.Vertices = face.Vertices;
                mesh.Path     = faceted.Path;
                mesh.Prim     = prim;
                mesh.Profile  = faceted.Profile;
                mesh.Vertices = face.Vertices;

                return(mesh);
            }
            return(null);
        }
        /// <summary>
        /// Checks if VBOs are created, if they are, bind them, if not create new
        /// </summary>
        /// <param name="face">Which face's mesh is uploaded in this VBO</param>
        /// <returns>True, if face data was succesfully uploaded to the graphics card memory</returns>
        public bool CheckVBO(Face face)
        {
            //hack
            //            if (VertexVBO == -1)
            //            {
            //                Vertex[] vArray = face.Vertices.ToArray();
            //                Compat.GenBuffers(out VertexVBO);
            //                Compat.BindBuffer(BufferTarget.ArrayBuffer, VertexVBO);
            //                Compat.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vArray.Length * VertexSize), vArray, BufferUsageHint.StaticDraw);
            //                if (Compat.BufferSize(BufferTarget.ArrayBuffer) != vArray.Length * VertexSize)
            //                {
            //                    VBOFailed = true;
            //                    Compat.BindBuffer(BufferTarget.ArrayBuffer, 0);
            //                    Compat.DeleteBuffer(VertexVBO);
            //                    VertexVBO = -1;
            //                    return false;
            //                }
            //            }
            //
            //            if (IndexVBO == -1)
            //            {
            //                ushort[] iArray = face.Indices.ToArray();
            //                Compat.GenBuffers(out IndexVBO);
            //                Compat.BindBuffer(BufferTarget.ElementArrayBuffer, IndexVBO);
            //                Compat.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(iArray.Length * sizeof(ushort)), iArray, BufferUsageHint.StaticDraw);
            //                if (Compat.BufferSize(BufferTarget.ElementArrayBuffer) != iArray.Length * sizeof(ushort))
            //                {
            //                    VBOFailed = true;
            //                    Compat.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
            //                    Compat.DeleteBuffer(IndexVBO);
            //                    IndexVBO = -1;
            //                    return false;
            //                }
            //            }

            return true;
        }
Example #8
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;
        }
Example #9
0
        private RenderableMesh ConvertFaceToRenderableMesh(OMVR.Face face, IAssetFetcher assetFetcher,
                                                           OMV.Primitive.TextureEntryFace defaultTexture, OMV.Vector3 primScale)
        {
            RenderableMesh rmesh = new RenderableMesh();

            rmesh.num = face.ID;

            // Copy one face's mesh imformation from the FacetedMesh into a MeshInfo
            MeshInfo meshInfo = new MeshInfo {
                vertexs    = new List <OMVR.Vertex>(face.Vertices),
                indices    = face.Indices.ConvertAll(ii => (int)ii),
                faceCenter = face.Center,
                scale      = primScale
            };

            BConverterOS.LogBProgress("{0} ConvertFaceToRenderableMesh: faceId={1}, numVert={2}, numInd={3}",
                                      _logHeader, face.ID, meshInfo.vertexs.Count, meshInfo.indices.Count);

            if (!ConvOAR.Globals.parms.P <bool>("DisplayTimeScaling"))
            {
                if (ScaleMeshes(meshInfo, primScale))
                {
                    BConverterOS.LogBProgress("{0} ConvertFaceToRenderableMesh: scaled mesh to {1}",
                                              _logHeader, primScale);
                }
                meshInfo.scale = OMV.Vector3.One;
            }

            // Find or create the MaterialInfo for this face.
            MaterialInfo matInfo = new MaterialInfo(face, defaultTexture);

            if (matInfo.textureID != null &&
                matInfo.textureID != OMV.UUID.Zero &&
                matInfo.textureID != OMV.Primitive.TextureEntry.WHITE_TEXTURE)
            {
                // Textures/images use the UUID from OpenSim and the hash is just the hash of the UUID
                EntityHandleUUID textureHandle   = new EntityHandleUUID((OMV.UUID)matInfo.textureID);
                BHash            textureHash     = new BHashULong(textureHandle.GetUUID().GetHashCode());
                ImageInfo        lookupImageInfo = assetFetcher.GetImageInfo(textureHash, () => {
                    // The image is not in the cache yet so create an ImageInfo entry for it
                    // Note that image gets the same UUID as the OpenSim texture
                    ImageInfo imageInfo = new ImageInfo(textureHandle);
                    assetFetcher.FetchTextureAsImage(textureHandle)
                    .Then(img => {
                        imageInfo.SetImage(img);
                    })
                    .Catch(e => {
                        // Failure getting the image
                        ConvOAR.Globals.log.ErrorFormat("{0} Failure fetching texture. id={1}. {2}",
                                                        _logHeader, matInfo.textureID, e);
                        // Create a simple, single color image to fill in for the missing image
                        var fillInImage = new Bitmap(32, 32, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                        Color theColor  = Color.FromArgb(128, 202, 213, 170);       // 0x80CAB5AA
                        for (int xx = 0; xx < 32; xx++)
                        {
                            for (int yy = 0; yy < 32; yy++)
                            {
                                fillInImage.SetPixel(xx, yy, theColor);
                            }
                        }
                        imageInfo.SetImage(fillInImage);
                    });
                    imageInfo.imageIdentifier = (OMV.UUID)matInfo.textureID;
                    BConverterOS.LogBProgress("{0} ConvertFaceToRenderableMesh: create ImageInfo. hash={1}, id={2}",
                                              _logHeader, textureHash, imageInfo.handle);
                    return(imageInfo);
                });
                matInfo.image = lookupImageInfo;

                // Update the UV information for the texture mapping
                BConverterOS.LogBProgress("{0} ConvertFaceToRenderableMesh: Converting tex coords using {1} texture",
                                          _logHeader, face.TextureFace == null ? "default" : "face");
                _mesher.TransformTexCoords(meshInfo.vertexs, meshInfo.faceCenter,
                                           face.TextureFace == null ? defaultTexture : face.TextureFace, primScale);
            }

            // See that the material is in the cache
            MaterialInfo lookupMatInfo = assetFetcher.GetMaterialInfo(matInfo.GetBHash(), () => { return(matInfo); });

            rmesh.material = lookupMatInfo;

            // See that the mesh is in the cache
            MeshInfo lookupMeshInfo = assetFetcher.GetMeshInfo(meshInfo.GetBHash(true), () => { return(meshInfo); });

            rmesh.mesh = lookupMeshInfo;
            if (lookupMeshInfo.indices.Count == 0)      // DEBUG DEBUG
            {
                ConvOAR.Globals.log.ErrorFormat("{0} indices count of zero. rmesh={1}", _logHeader, rmesh.ToString());
            }   // DEBUG DEBUG

            BConverterOS.LogBProgress("{0} ConvertFaceToRenderableMesh: rmesh.mesh={1}, rmesh.material={2}",
                                      _logHeader, rmesh.mesh, rmesh.material);

            return(rmesh);
        }
Example #10
0
        private void UpdateTerrain()
        {
            if (Client.Network.CurrentSim == null || Client.Network.CurrentSim.Terrain == null) return;

            ThreadPool.QueueUserWorkItem(sync =>
            {
                int step = 1;

                for (int x = 0; x < 256; x += step)
                {
                    for (int y = 0; y < 256; y += step)
                    {
                        float z = 0;
                        int patchNr = ((int)x / 16) * 16 + (int)y / 16;
                        if (Client.Network.CurrentSim.Terrain[patchNr] != null
                            && Client.Network.CurrentSim.Terrain[patchNr].Data != null)
                        {
                            float[] data = Client.Network.CurrentSim.Terrain[patchNr].Data;
                            z = data[(int)x % 16 * 16 + (int)y % 16];
                        }
                        heightTable[x, y] = z;
                    }
                }

                terrainFace = renderer.TerrainMesh(heightTable, 0f, 255f, 0f, 255f);
                terrainVertices = new ColorVertex[terrainFace.Vertices.Count];
                for (int i = 0; i < terrainFace.Vertices.Count; i++)
                {
                    byte[] part = Utils.IntToBytes(i);
                    terrainVertices[i] = new ColorVertex()
                    {
                        Vertex = terrainFace.Vertices[i],
                        Color = new Color4b()
                        {
                            R = part[0],
                            G = part[1],
                            B = part[2],
                            A = 253 // terrain picking
                        }
                    };
                }
                terrainIndices = terrainFace.Indices.ToArray();
                terrainInProgress = false;
                terrainModified = false;
                terrainTextureNeedsUpdate = true;
                terrainTimeSinceUpdate = 0f;
            });
        }
Example #11
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]));
                    }
                }
            }
        }
Example #12
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;
        }
Example #13
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;
        }
Example #14
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);
                }
            }
        }
Example #15
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;
        }
Example #16
0
        private void UpdateTerrain()
        {
            if (Client.Network.CurrentSim == null || Client.Network.CurrentSim.Terrain == null) return;
            int step = 1;

            for (int x = 0; x < 255; x += step)
            {
                for (int y = 0; y < 255; y += step)
                {
                    float z = 0;
                    int patchNr = ((int)x / 16) * 16 + (int)y / 16;
                    if (Client.Network.CurrentSim.Terrain[patchNr] != null
                        && Client.Network.CurrentSim.Terrain[patchNr].Data != null)
                    {
                        float[] data = Client.Network.CurrentSim.Terrain[patchNr].Data;
                        z = data[(int)x % 16 * 16 + (int)y % 16];
                    }
                    heightTable[x, y] = z;
                }
            }

            terrainFace = renderer.TerrainMesh(heightTable, 0f, 255f, 0f, 255f);
            terrainVertices = terrainFace.Vertices.ToArray();
            terrainIndices = terrainFace.Indices.ToArray();

            TerrainModified = false;
        }
        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);
        }
Example #18
0
        private void CreateNewPrim(LLEntityBase ent)
        {
            m_log.Log(LogLevel.DRENDERDETAIL, "Create new prim {0}", ent.Name.Name);
            // entity render info is kept per region. Get the region prim structure
            RegionRenderInfo rri = GetRegionRenderInfo(ent.RegionContext);
            IEntityAvatar    av;

            if (ent.TryGet <IEntityAvatar>(out av))
            {
                // if this entity is an avatar, just put it on the display list
                lock (rri.renderAvatarList) {
                    if (!rri.renderAvatarList.ContainsKey(av.LGID))
                    {
                        RenderableAvatar ravv = new RenderableAvatar();
                        ravv.avatar = av;
                        rri.renderAvatarList.Add(av.LGID, ravv);
                    }
                }
                return;
            }
            OMV.Primitive prim = ent.Prim;

            /* don't do foliage yet
             * if (prim.PrimData.PCode == OMV.PCode.Grass
             || prim.PrimData.PCode == OMV.PCode.Tree
             || prim.PrimData.PCode == OMV.PCode.NewTree) {
             || lock (renderFoliageList)
             ||     renderFoliageList[prim.LocalID] = prim;
             || return;
             ||}
             */

            RenderablePrim render = new RenderablePrim();

            render.Prim      = prim;
            render.acontext  = ent.AssetContext;
            render.rcontext  = ent.RegionContext;
            render.Position  = prim.Position;
            render.Rotation  = prim.Rotation;
            render.isVisible = true; // initially assume visible

            if (m_meshMaker == null)
            {
                m_meshMaker = new Renderer.Mesher.MeshmerizerR();
                m_meshMaker.ShouldScaleMesh = false;
            }

            if (prim.Sculpt != null)
            {
                EntityNameLL          textureEnt    = EntityNameLL.ConvertTextureWorldIDToEntityName(ent.AssetContext, prim.Sculpt.SculptTexture);
                System.Drawing.Bitmap textureBitmap = ent.AssetContext.GetTexture(textureEnt);
                if (textureBitmap == null)
                {
                    // the texture is not available. Request it.
                    // Note that we just call this routine again when it is available. Hope it's not recursive
                    ent.AssetContext.DoTextureLoad(textureEnt, AssetContextBase.AssetType.SculptieTexture,
                                                   delegate(string name, bool trans) {
                        CreateNewPrim(ent);
                        return;
                    }
                                                   );
                    return;
                }
                render.Mesh = m_meshMaker.GenerateSculptMesh(textureBitmap, prim, OMVR.DetailLevel.Medium);
                textureBitmap.Dispose();
            }
            else
            {
                render.Mesh = m_meshMaker.GenerateFacetedMesh(prim, OMVR.DetailLevel.High);
            }

            if (render.Mesh == null)
            {
                // mesh generation failed
                m_log.Log(LogLevel.DBADERROR, "FAILED MESH GENERATION: not generating new prim {0}", ent.Name.Name);
                return;
            }

            // Create a FaceData struct for each face that stores the 3D data
            // in an OpenGL friendly format
            for (int j = 0; j < render.Mesh.Faces.Count; j++)
            {
                OMVR.Face face = render.Mesh.Faces[j];
                FaceData  data = new FaceData();

                // Vertices for this face
                data.Vertices = new float[face.Vertices.Count * 3];
                for (int k = 0; k < face.Vertices.Count; k++)
                {
                    data.Vertices[k * 3 + 0] = face.Vertices[k].Position.X;
                    data.Vertices[k * 3 + 1] = face.Vertices[k].Position.Y;
                    data.Vertices[k * 3 + 2] = face.Vertices[k].Position.Z;
                }

                // Indices for this face
                data.Indices = face.Indices.ToArray();

                // Texture transform for this face
                OMV.Primitive.TextureEntryFace teFace = prim.Textures.GetFace((uint)j);
                m_meshMaker.TransformTexCoords(face.Vertices, face.Center, teFace);

                // Texcoords for this face
                data.TexCoords = new float[face.Vertices.Count * 2];
                for (int k = 0; k < face.Vertices.Count; k++)
                {
                    data.TexCoords[k * 2 + 0] = face.Vertices[k].TexCoord.X;
                    data.TexCoords[k * 2 + 1] = face.Vertices[k].TexCoord.Y;
                }

                data.Normals = new float[face.Vertices.Count * 3];
                for (int k = 0; k < face.Vertices.Count; k++)
                {
                    data.Normals[k * 3 + 0] = face.Vertices[k].Normal.X;
                    data.Normals[k * 3 + 1] = face.Vertices[k].Normal.Y;
                    data.Normals[k * 3 + 2] = face.Vertices[k].Normal.Z;
                }


                // m_log.Log(LogLevel.DRENDERDETAIL, "CreateNewPrim: v={0}, i={1}, t={2}",
                //     data.Vertices.GetLength(0), data.Indices.GetLength(0), data.TexCoords.GetLength(0));

                // Texture for this face
                if (teFace.TextureID != OMV.UUID.Zero &&
                    teFace.TextureID != OMV.Primitive.TextureEntry.WHITE_TEXTURE)
                {
                    lock (Textures) {
                        if (!Textures.ContainsKey(teFace.TextureID))
                        {
                            // temporarily add the entry to the table so we don't request it multiple times
                            Textures.Add(teFace.TextureID, new TextureInfo(0, true));
                            // We haven't constructed this image in OpenGL yet, get ahold of it
                            AssetContextBase.RequestTextureLoad(
                                EntityNameLL.ConvertTextureWorldIDToEntityName(ent.AssetContext, teFace.TextureID),
                                AssetContextBase.AssetType.Texture,
                                OnTextureDownloadFinished);
                        }
                    }
                }

                // Set the UserData for this face to our FaceData struct
                face.UserData        = data;
                render.Mesh.Faces[j] = face;
            }

            lock (rri.renderPrimList) {
                rri.renderPrimList[prim.LocalID] = render;
            }
        }
        //int[] CubeMapDefines = new int[]
        //{
        //    Gl.GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
        //    Gl.GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
        //    Gl.GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
        //    Gl.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
        //    Gl.GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
        //    Gl.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
        //};

        private void RenderPrims(RegionContextBase rcontext, RegionRenderInfo rri)
        {
            GL.Enable(EnableCap.DepthTest);
            GL.Enable(EnableCap.Texture2D);

            lock (rri.renderPrimList) {
                bool firstPass = true;
                // GL.Disable(EnableCap.Blend);
                GL.Enable(EnableCap.Blend);
                GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
                GL.Enable(EnableCap.DepthTest);

                GL.Enable(EnableCap.Normalize);

                GL.EnableClientState(ArrayCap.TextureCoordArray);
                GL.EnableClientState(ArrayCap.VertexArray);
                GL.EnableClientState(ArrayCap.NormalArray);


StartRender:

                List <RenderablePrim> rpList = new List <RenderablePrim>(rri.renderPrimList.Values);
                // sort back to front
                rpList.Sort(delegate(RenderablePrim rp1, RenderablePrim rp2) {
                    return((int)(((OMV.Vector3.Distance(m_renderer.Camera.Position, rp1.Prim.Position)) -
                                  (OMV.Vector3.Distance(m_renderer.Camera.Position, rp2.Prim.Position))) * 100f));
                });
                foreach (RenderablePrim rp in rpList)
                {
                    // if this prim is not visible, just loop
                    if (!rp.isVisible)
                    {
                        continue;
                    }

                    RenderablePrim prp  = RenderablePrim.Empty;
                    OMV.Primitive  prim = rp.Prim;

                    if (prim.ParentID != 0)
                    {
                        // Get the parent reference
                        if (!rri.renderPrimList.TryGetValue(prim.ParentID, out prp))
                        {
                            // Can't render a child with no parent prim, skip it
                            continue;
                        }
                    }

                    GL.PushName(prim.LocalID);
                    GL.PushMatrix();

                    if (prim.ParentID != 0)
                    {
                        // Apply parent translation and rotation
                        GL.MultMatrix(Math3D.CreateTranslationMatrix(prp.Position));
                        GL.MultMatrix(Math3D.CreateRotationMatrix(prp.Rotation));
                    }

                    // Apply prim translation and rotation
                    GL.MultMatrix(Math3D.CreateTranslationMatrix(rp.Position));
                    // apply region offset for multiple regions
                    GL.MultMatrix(Math3D.CreateTranslationMatrix(CalcRegionOffset(rp.rcontext)));
                    GL.MultMatrix(Math3D.CreateRotationMatrix(rp.Rotation));

                    // Scale the prim
                    GL.Scale(prim.Scale.X, prim.Scale.Y, prim.Scale.Z);

                    // Draw the prim faces
                    for (int j = 0; j < rp.Mesh.Faces.Count; j++)
                    {
                        OMVR.Face  face      = rp.Mesh.Faces[j];
                        FaceData   data      = (FaceData)face.UserData;
                        OMV.Color4 color     = face.TextureFace.RGBA;
                        bool       alpha     = false;
                        int        textureID = 0;

                        if (color.A < 1.0f)
                        {
                            alpha = true;
                        }

                        TextureInfo info;
                        if (face.TextureFace.TextureID != OMV.UUID.Zero &&
                            face.TextureFace.TextureID != OMV.Primitive.TextureEntry.WHITE_TEXTURE &&
                            m_renderer.Textures.TryGetValue(face.TextureFace.TextureID, out info))
                        {
                            if (info.Alpha)
                            {
                                alpha = true;
                            }

                            textureID = info.ID;
                            // if textureID has not been set, need to generate the mipmaps
                            if (textureID == 0)
                            {
                                GenerateMipMaps(rp.acontext, face.TextureFace.TextureID, out textureID);
                                info.ID = textureID;
                            }

                            // Enable texturing for this face
                            GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
                        }
                        else
                        {
                            if (face.TextureFace.TextureID == OMV.Primitive.TextureEntry.WHITE_TEXTURE ||
                                face.TextureFace.TextureID == OMV.UUID.Zero)
                            {
                                GL.PolygonMode(MaterialFace.Front, PolygonMode.Fill);
                            }
                            else
                            {
                                GL.PolygonMode(MaterialFace.Front, PolygonMode.Line);
                            }
                        }

                        // if (firstPass && !alpha || !firstPass && alpha) {
                        // GL.Color4(color.R, color.G, color.B, color.A);
                        float[] matDiffuse = { color.R, color.G, color.B, color.A };
                        GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Diffuse, matDiffuse);

                        // Bind the texture
                        if (textureID != 0)
                        {
                            GL.Enable(EnableCap.Texture2D);
                            GL.BindTexture(TextureTarget.Texture2D, textureID);
                        }
                        else
                        {
                            GL.Disable(EnableCap.Texture2D);
                        }

                        GL.TexCoordPointer(2, TexCoordPointerType.Float, 0, data.TexCoords);
                        GL.VertexPointer(3, VertexPointerType.Float, 0, data.Vertices);
                        GL.NormalPointer(NormalPointerType.Float, 0, data.Normals);
                        GL.DrawElements(BeginMode.Triangles, data.Indices.Length, DrawElementsType.UnsignedShort, data.Indices);
                        // }
                    }

                    GL.PopMatrix();
                    GL.PopName();
                }

                /*
                 * if (firstPass) {
                 *  firstPass = false;
                 *  GL.Enable(EnableCap.Blend);
                 *  GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
                 *  // GL.Disable(EnableCap.DepthTest);
                 *
                 *  goto StartRender;
                 * }
                 */
            }

            GL.Enable(EnableCap.DepthTest);
            GL.Disable(EnableCap.Texture2D);
        }
Example #20
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>
        /// 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);
            }
        }
Example #22
0
        private static List<Face> CreateVolumeFaces(Primitive prim, Path path,
            Profile profile, List<Vertex> vertices)
        {
            int numFaces = profile.Faces.Count;
            List<Face> faces = new List<Face>(numFaces);

            // Initialize faces with parameter data
            for (int i = 0; i < numFaces; i++)
            {
                ProfileFace pf = profile.Faces[i];

                Face face = new Face();
                face.Vertices = new List<Vertex>();
                face.Indices = new List<ushort>();
                face.Edge = new List<int>();

                face.BeginS = pf.Index;
                face.NumS = pf.Count;
                face.BeginT = 0;
                face.NumT = path.Points.Count;
                face.ID = i;

                // Set the type mask bits correctly
                if (prim.Data.ProfileHollow > 0f)
                    face.Mask |= FaceMask.Hollow;
                if (profile.Open)
                    face.Mask |= FaceMask.Open;
                if (pf.Cap)
                {
                    face.Mask |= FaceMask.Cap;
                    if (pf.Type == FaceType.PathBegin)
                        face.Mask |= FaceMask.Top;
                    else
                        face.Mask |= FaceMask.Bottom;
                }
                else if (pf.Type == FaceType.ProfileBegin || pf.Type == FaceType.ProfileEnd)
                {
                    face.Mask |= FaceMask.Flat;
                    face.Mask |= FaceMask.End;
                }
                else
                {
                    face.Mask |= FaceMask.Side;

                    if (pf.Flat)
                        face.Mask |= FaceMask.Flat;

                    if (pf.Type == FaceType.InnerSide)
                    {
                        face.Mask |= FaceMask.Inner;
                        if (pf.Flat && face.NumS > 2)
                            face.NumS *= 2; // Flat inner faces have to copy vert normals
                    }
                    else
                    {
                        face.Mask |= FaceMask.Outer;
                    }
                }

                faces.Add(face);
            }

            for (int i = 0; i < faces.Count; i++)
            {
                Face face = faces[i];
                BuildFace(ref face, prim.Data, vertices, path, profile, prim.Textures.GetFace((uint)i));
                faces[i] = face;
            }

            return faces;
        }
Example #23
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);
        }
Example #24
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;
        }
Example #25
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;
        }
        /// <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);
        }
Example #27
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;
        }
        public void CheckVBO(Face face)
        {
            if (VertexVBO == -1)
            {
                Vertex[] vArray = face.Vertices.ToArray();
                GL.GenBuffers(1, out VertexVBO);
                GL.BindBuffer(BufferTarget.ArrayBuffer, VertexVBO);
                GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vArray.Length * VertexSize), vArray, BufferUsageHint.StaticDraw);
            }

            if (IndexVBO == -1)
            {
                ushort[] iArray = face.Indices.ToArray();
                GL.GenBuffers(1, out IndexVBO);
                GL.BindBuffer(BufferTarget.ElementArrayBuffer, IndexVBO);
                GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(iArray.Length * sizeof(ushort)), iArray, BufferUsageHint.StaticDraw);
            }
        }
Example #29
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));
                }
            }
        }
Example #30
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;
        }
Example #31
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;
            }
        }
        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;
        }
Example #33
0
        private static void UpdateMinMax(ref Face face, Vector3 position)
        {
            if (face.MinExtent.X > position.X)
                face.MinExtent.X = position.X;
            if (face.MinExtent.Y > position.Y)
                face.MinExtent.Y = position.Y;
            if (face.MinExtent.Z > position.Z)
                face.MinExtent.Z = position.Z;

            if (face.MaxExtent.X < position.X)
                face.MaxExtent.X = position.X;
            if (face.MaxExtent.Y < position.Y)
                face.MaxExtent.Y = position.Y;
            if (face.MaxExtent.Z < position.Z)
                face.MaxExtent.Z = position.Z;
        }
Example #34
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);
        }
Example #35
0
        private List<Face> GenerateFaces(Primitive.TextureEntry te)
        {
            Face face = new Face();
            face.Edge = new List<int>();
            face.TextureFace = te.DefaultTexture;
            face.Vertices = GenerateVertices();
            face.Indices = GenerateIndices();

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

            return faces;
        }
Example #36
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);
        }