/// <summary>
        /// Serializes the combined faces and returns a mesh
        /// </summary>
        private Tuple <string, Mesh, List <MeshInstance> > SerializeCombinedFaces(
            string parent, PrimDisplayData data,
            string materialType, string tempPath, BabylonFlatBufferOutputs outputs,
            ExportStats stats)
        {
            stats.PrimCount++;

            BabylonPrimFaceCombiner combiner = new BabylonPrimFaceCombiner();

            foreach (var face in data.Mesh.Faces)
            {
                combiner.CombineFace(face);
            }

            combiner.Complete();

            List <string> materialsList = new List <string>();

            for (int i = 0; i < combiner.Materials.Count; i++)
            {
                var   material     = combiner.Materials[i];
                float shinyPercent = ShinyToPercent(material.Shiny);

                bool hasTexture = material.TextureID != OpenMetaverse.UUID.Zero;

                //check the material tracker, if we already have this texture, don't export it again
                TrackedTexture trackedTexture = null;

                if (hasTexture)
                {
                    if (outputs.Textures.ContainsKey(material.TextureID))
                    {
                        trackedTexture = outputs.Textures[material.TextureID];
                    }
                    else
                    {
                        string materialMapName = $"tex_mat_{material.TextureID}.{materialType}";
                        var    kvp             = this.WriteMaterialTexture(material.TextureID, materialMapName, tempPath, outputs.TextureFiles);

                        outputs.Textures.Add(kvp.Key, kvp.Value);

                        trackedTexture = kvp.Value;
                    }
                }

                var matHash = _objHasher.GetMaterialFaceHash(material);
                if (!outputs.Materials.ContainsKey(matHash))
                {
                    bool hasTransparent = material.RGBA.A < 1.0f || (trackedTexture != null && trackedTexture.HasAlpha);

                    Texture texture = null;
                    if (hasTexture)
                    {
                        texture = new Texture()
                        {
                            HasAlpha = hasTransparent,
                            Name     = trackedTexture.Name
                        };
                    }

                    BabylonFlatBufferIntermediates.Material jsMaterial = new BabylonFlatBufferIntermediates.Material()
                    {
                        Alpha          = material.RGBA.A,
                        Color          = new[] { material.RGBA.R, material.RGBA.G, material.RGBA.B },
                        DiffuseTexture = hasTexture ? texture : null,
                        Id             = matHash.ToString(),
                        Name           = matHash.ToString(),
                        ShinyPercent   = shinyPercent
                    };

                    outputs.Materials.Add(matHash, jsMaterial);
                }

                materialsList.Add(matHash.ToString());
            }

            var multiMaterialName = data.MaterialHash + "_mm";

            if (!outputs.MultiMaterials.ContainsKey(data.MaterialHash))
            {
                //create the multimaterial
                var multiMaterial = new MultiMaterial()
                {
                    Id            = multiMaterialName,
                    MaterialsList = materialsList,
                    Name          = multiMaterialName
                };

                outputs.MultiMaterials[data.MaterialHash] = multiMaterial;
            }

            List <SubMesh> submeshes = new List <SubMesh>();

            foreach (var subMesh in combiner.SubMeshes)
            {
                submeshes.Add(new SubMesh()
                {
                    MaterialIndex = subMesh.MaterialIndex,
                    VerticesStart = subMesh.VerticesStart,
                    VerticesCount = subMesh.VerticesCount,
                    IndexStart    = subMesh.IndexStart,
                    IndexCount    = subMesh.IndexCount
                });

                stats.SubmeshCount++;
            }

            List <MeshInstance> instanceList = null;

            if (parent == null)
            {
                instanceList = new List <MeshInstance>();
            }

            //if this is a child prim, divide out the scale of the parent
            var scale = data.Scale;

            if (parent != null)
            {
                scale /= data.Parent.Scale;
            }

            Vector3    pos = data.OffsetPosition;
            Quaternion rot = data.OffsetRotation;

            if (parent == null)
            {
                FixCoordinateSystem(ref pos, ref rot);
            }


            var primId = data.ShapeHash + "_" + data.MaterialHash + (parent == null ? "_P" : "");

            Mesh mesh = new Mesh()
            {
                Name               = primId,
                Id                 = primId,
                ParentId           = parent,
                MaterialId         = multiMaterialName,
                Position           = new [] { pos.X, pos.Y, pos.Z },
                RotationQuaternion = new[] { rot.X, rot.Y, rot.Z, rot.W },
                Scaling            = new[] { scale.X, scale.Y, scale.Z },
                Positions          = combiner.Vertices,
                Normals            = combiner.Normals,
                UVs                = combiner.UVs,
                Indices            = combiner.Indices,
                Submeshes          = submeshes,
                Instances          = instanceList
            };

            return(new Tuple <string, Mesh, List <MeshInstance> >(primId, mesh, instanceList));
        }
예제 #2
0
        /// <summary>
        /// Serializes the combined faces and returns a mesh
        /// </summary>
        private Tuple <string, object, List <object> > SerializeCombinedFaces(
            string parent, PrimDisplayData data,
            string materialType, string tempPath, BabylonOutputs outputs,
            ExportStats stats)
        {
            stats.PrimCount++;

            BabylonPrimFaceCombiner combiner = new BabylonPrimFaceCombiner();

            foreach (var face in data.Mesh.Faces)
            {
                combiner.CombineFace(face);
            }

            combiner.Complete();

            List <string> materialsList = new List <string>();

            for (int i = 0; i < combiner.Materials.Count; i++)
            {
                var   material     = combiner.Materials[i];
                float shinyPercent = ShinyToPercent(material.Shiny);

                bool hasTexture = material.TextureID != OpenMetaverse.UUID.Zero;

                //check the material tracker, if we already have this texture, don't export it again
                TrackedTexture trackedTexture = null;

                if (hasTexture)
                {
                    if (outputs.Textures.ContainsKey(material.TextureID))
                    {
                        trackedTexture = outputs.Textures[material.TextureID];
                    }
                    else
                    {
                        string materialMapName = $"tex_mat_{material.TextureID}.{materialType}";
                        var    kvp             = this.WriteMaterialTexture(material.TextureID, materialMapName, tempPath, outputs.TextureFiles);

                        outputs.Textures.Add(kvp.Key, kvp.Value);

                        trackedTexture = kvp.Value;
                    }
                }

                var matHash = _objHasher.GetMaterialFaceHash(material);
                if (!outputs.Materials.ContainsKey(matHash))
                {
                    bool hasTransparent = material.RGBA.A < 1.0f || (trackedTexture != null && trackedTexture.HasAlpha);

                    object texture = null;
                    if (hasTexture)
                    {
                        texture = new
                        {
                            name             = trackedTexture.Name,
                            level            = 1,
                            hasAlpha         = hasTransparent,
                            getAlphaFromRGB  = false,
                            coordinatesMode  = 0,
                            uOffset          = 0,
                            vOffset          = 0,
                            uScale           = 1,
                            vScale           = 1,
                            uAng             = 0,
                            vAng             = 0,
                            wAng             = 0,
                            wrapU            = true,
                            wrapV            = true,
                            coordinatesIndex = 0
                        };
                    }

                    var jsMaterial = new
                    {
                        name                   = matHash.ToString(),
                        id                     = matHash.ToString(),
                        ambient                = new[] { material.RGBA.R, material.RGBA.G, material.RGBA.B },
                        diffuse                = new[] { material.RGBA.R, material.RGBA.G, material.RGBA.B },
                        specular               = new[] { material.RGBA.R *shinyPercent, material.RGBA.G *shinyPercent, material.RGBA.B *shinyPercent },
                        specularPower          = 50,
                        emissive               = new[] { 0.01f, 0.01f, 0.01f },
                        alpha                  = material.RGBA.A,
                        backFaceCulling        = true,
                        wireframe              = false,
                        diffuseTexture         = hasTexture ? texture : null,
                        useLightmapAsShadowmap = false,
                        checkReadOnlyOnce      = true
                    };

                    outputs.Materials.Add(matHash, jsMaterial);
                }

                materialsList.Add(matHash.ToString());
            }

            var multiMaterialName = data.MaterialHash + "_mm";

            if (!outputs.MultiMaterials.ContainsKey(data.MaterialHash))
            {
                //create the multimaterial
                var multiMaterial = new
                {
                    name      = multiMaterialName,
                    id        = multiMaterialName,
                    materials = materialsList
                };

                outputs.MultiMaterials[data.MaterialHash] = multiMaterial;
            }

            //finally serialize the mesh
            float[] identity4x4 =
            {
                1.0f, 0.0f, 0.0f, 0.0f,
                0.0f, 1.0f, 0.0f, 0.0f,
                0.0f, 0.0f, 1.0f, 0.0f,
                0.0f, 0.0f, 0.0f, 1.0f
            };

            List <object> submeshes = new List <object>();

            foreach (var subMesh in combiner.SubMeshes)
            {
                submeshes.Add(new
                {
                    materialIndex = subMesh.MaterialIndex,
                    verticesStart = subMesh.VerticesStart,
                    verticesCount = subMesh.VerticesCount,
                    indexStart    = subMesh.IndexStart,
                    indexCount    = subMesh.IndexCount
                });

                stats.SubmeshCount++;
            }

            List <object> instanceList = null;

            if (parent == null)
            {
                instanceList = new List <object>();
            }

            //if this is a child prim, decouple its coordinate system from the parent
            //it seems like babylon loads the object, and then applies the parentage
            //after the object is already in world

            /*if (parent != null)
             * {
             *  Quaternion parentRot = data.Parent.OffsetRotation;
             *
             *  Vector3 axPos = data.OffsetPosition;
             *  axPos *= parentRot;
             *  Vector3 translationOffsetPosition = axPos;
             *
             *  pos = data.Parent.OffsetPosition + translationOffsetPosition;
             *  rot = data.Parent.OffsetRotation * data.OffsetRotation;
             * }*/

            //if this is a child prim, divide out the scale of the parent
            var scale = data.Scale;

            if (parent != null)
            {
                scale /= data.Parent.Scale;
            }

            Vector3    pos = data.OffsetPosition;
            Quaternion rot = data.OffsetRotation;

            if (parent == null)
            {
                FixCoordinateSystem(ref pos, ref rot);
            }


            var primId = data.ShapeHash + "_" + data.MaterialHash + (parent == null ? "_P" : "");
            var mesh   = new
            {
                name                     = primId,
                id                       = primId,
                parentId                 = parent,
                materialId               = multiMaterialName,
                position                 = new [] { pos.X, pos.Y, pos.Z },
                rotationQuaternion       = new[] { rot.X, rot.Y, rot.Z, rot.W },
                scaling                  = new[] { scale.X, scale.Y, scale.Z },
                pivotMatrix              = identity4x4,
                infiniteDistance         = false,
                showBoundingBox          = false,
                showSubMeshesBoundingBox = false,
                isVisible                = true,
                isEnabled                = true,
                pickable                 = true,
                applyFog                 = false,
                checkCollisions          = false,
                receiveShadows           = false,
                positions                = combiner.Vertices,
                normals                  = combiner.Normals,
                uvs                      = combiner.UVs,
                indices                  = combiner.Indices,
                subMeshes                = submeshes,
                autoAnimate              = false,
                billboardMode            = 0,
                instances                = instanceList
            };

            return(new Tuple <string, object, List <object> >(primId, mesh, instanceList));
        }