Example #1
0
            // Find all the meshes in passed Displayable and add them to the lists indexed by their material
            //     mesh hashes.
            private void MapMaterialsAndMeshes(BScene pBs, BInstance pInst, Displayable disp)
            {
                RenderableMeshGroup rmg = disp.renderable as RenderableMeshGroup;

                if (rmg != null)
                {
                    foreach (RenderableMesh rMesh in rmg.meshes)
                    {
                        InvertedMesh imesh = new InvertedMesh(pBs, pInst, disp, rmg, rMesh);

                        BHash meshHash = rMesh.mesh.GetBHash();
                        if (!sharedMeshes.ContainsKey(meshHash))
                        {
                            sharedMeshes.Add(meshHash, new List <InvertedMesh>());
                        }
                        sharedMeshes[meshHash].Add(imesh);

                        BHash materialHash = rMesh.material.GetBHash();
                        if (!meshByMaterial.ContainsKey(materialHash))
                        {
                            meshByMaterial.Add(materialHash, new List <InvertedMesh>());
                        }
                        meshByMaterial[materialHash].Add(imesh);
                    }
                }
                foreach (Displayable child in disp.children)
                {
                    MapMaterialsAndMeshes(pBs, pInst, child);
                }
            }
Example #2
0
        private void DumpInstance(BInstance inst)
        {
            Displayable instDisplayable = inst.Representation;

            LogBProgress("{0} created instance. handle={1}, pos={2}, rot={3}",
                         _logHeader, inst.handle, inst.Position, inst.Rotation);
            DumpDisplayable(inst.Representation, "Representation", 0);
        }
Example #3
0
        // Given a list of meshes, combine them into one mesh and return a containing BInstance.
        private BInstance CreateOneInstanceFromMeshes(BHash materialHash, List <InvertedMesh> meshes)
        {
            // Pick one of the meshes to be the 'root' mesh.
            // Someday may need to find the most center mesh to work from.
            InvertedMesh rootIMesh = meshes.First();

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

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

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

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

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

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

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

            return(inst);
        }
Example #4
0
 public InvertedMesh(BScene pBs, BInstance pInst, Displayable pDisp, DisplayableRenderable pDisprend, RenderableMesh pRm)
 {
     containingScene                 = pBs;
     containingInstance              = pInst;
     containingDisplayable           = pDisp;
     containingDisplayableRenderable = pDisprend;
     renderableMesh = pRm;
     // Compute the global position of the Displayable
     globalPosition = containingDisplayable.offsetPosition * containingInstance.Rotation + containingInstance.Position;
     globalRotation = containingDisplayable.offsetRotation * containingInstance.Rotation;
 }
Example #5
0
            // Add another level of parenting
            public InvertedMesh AddDisplayableLevel(InvertedMesh imesh, Displayable pDisp, DisplayableRenderable pDispRend)
            {
                InvertedMesh newIMesh = new InvertedMesh(imesh.containingScene, imesh.containingInstance,
                                                         imesh.containingDisplayable, imesh.containingDisplayableRenderable, imesh.renderableMesh);

                globalPosition += pDisp.offsetPosition;
                globalRotation *= pDisp.offsetRotation;
                newIMesh.containingDisplayable           = pDisp;
                newIMesh.containingDisplayableRenderable = pDispRend;
                return(newIMesh);
            }
Example #6
0
        // Adds this Displayable if it's not already in the list.
        // Return 'true' if the Displayable was added to the list.
        public bool AddUniqueDisplayable(Displayable disp)
        {
            bool        ret = false;
            Displayable maybeDisp;
            BHash       dispHash = disp.GetBHash();

            lock (Displayables) {
                if (!Displayables.TryGetValue(dispHash, out maybeDisp))
                {
                    Displayables.Add(dispHash, disp);
                }
            }
            return(ret);
        }
Example #7
0
        // Utility routine to gather all the MeshInfo's from a Displayable and all its children.
        private static List <MeshInfo> CollectMeshesFromDisplayable(Displayable disp)
        {
            List <MeshInfo> meshInfos = new List <MeshInfo>();

            if (disp.renderable is RenderableMeshGroup rmg)
            {
                meshInfos.AddRange(
                    rmg.meshes.Select(aMesh => { return(aMesh.mesh); })
                    );
            }
            disp.children.ForEach(child => {
                meshInfos.AddRange(CollectMeshesFromDisplayable(child));
            });
            return(meshInfos);
        }
Example #8
0
        private void DumpDisplayable(Displayable disp, string header, int level)
        {
            string spaces = "                                                           ";
            string spacer = spaces.Substring(0, level * 2);

            LogBProgress("{0}{1}  displayable: name={2}, pos={3}, rot={4}",
                         _logHeader, spacer, disp.name, disp.offsetPosition, disp.offsetRotation);
            RenderableMeshGroup rmg = disp.renderable as RenderableMeshGroup;

            if (rmg != null)
            {
                rmg.meshes.ForEach(mesh => {
                    LogBProgress("{0}{1}    mesh: mesh={2}. material={3}",
                                 _logHeader, spacer, mesh.mesh, mesh.material);
                });
            }
            disp.children.ForEach(child => {
                DumpDisplayable(child, "Child", level + 1);
            });
        }
Example #9
0
        private List <Displayable> PackMeshesIntoDisplayables(List <InvertedMesh> meshList, OMV.Vector3 gPos, CreateNameFunc createName)
        {
            return(meshList.Select(imesh => {
                /*
                 * ConvOAR.Globals.log.DebugFormat("{0} CreateInstanceForSharedMeshes: hash={1}, instPos={2}, dispPos={3}, numVerts={4}",
                 *              _logHeader, imesh.renderableMesh.mesh.GetBHash(),
                 *              imesh.containingInstance.Position,
                 *              imesh.containingDisplayable.offsetPosition,
                 *              imesh.renderableMesh.mesh.vertexs.Count);
                 */

                RenderableMeshGroup mesh = new RenderableMeshGroup();
                mesh.meshes.Add(imesh.renderableMesh);

                Displayable disp = new Displayable(mesh);
                disp.name = createName(imesh);
                disp.offsetPosition = imesh.globalPosition - gPos;
                disp.offsetRotation = imesh.globalRotation;
                disp.renderable = mesh;

                return disp;
            }).ToList());
        }
Example #10
0
        // Creates Instances for the shared messes in this list and also takes the meshes out of 'meshByMaterial'.
        // Current algorithm: create one instance and add all shared meshes as children.
        // When the instances are created (or copied over), the meshes must be removed from the
        //     'meshByMaterial' structure so they are not combined with other material sharing meshes.
        private List <BInstance> CreateInstancesForSharedMeshes(List <InvertedMesh> meshList)
        {
            List <BInstance> ret = new List <BInstance>();

            BInstance    inst     = new BInstance();
            InvertedMesh rootMesh = meshList.First();

            inst.Position = rootMesh.globalPosition;
            inst.Rotation = OMV.Quaternion.Identity;

            // Create Displayable for each identical mesh (so we can keep the pos and rot.
            // Take the root mesh out of the list and use it as the representation
            List <Displayable> repackagedMeshes = PackMeshesIntoDisplayables(meshList, inst.Position,
                                                                             imesh => "sharedMesh-" + imesh.renderableMesh.mesh.GetBHash().ToString() + "-" + imesh.renderableMesh.GetBHash().ToString());
            Displayable rootDisplayable = repackagedMeshes.First();

            repackagedMeshes.RemoveAt(0);
            inst.Representation      = rootDisplayable;
            rootDisplayable.children = repackagedMeshes;

            ret.Add(inst);

            return(ret);
        }
Example #11
0
        // Create a mesh for the terrain of the current scene
        public static BInstance CreateTerrainMesh(
            Scene scene,
            PrimToMesh assetMesher, IAssetFetcher assetFetcher)
        {
            ITerrainChannel terrainDef = scene.Heightmap;
            int             XSize      = terrainDef.Width;
            int             YSize      = terrainDef.Height;

            float[,] heightMap = new float[XSize, YSize];
            if (ConvOAR.Globals.parms.P <bool>("HalfRezTerrain"))
            {
                ConvOAR.Globals.log.DebugFormat("{0}: CreateTerrainMesh. creating half sized terrain sized <{1},{2}>", LogHeader, XSize / 2, YSize / 2);
                // Half resolution mesh that approximates the heightmap
                heightMap = new float[XSize / 2, YSize / 2];
                for (int xx = 0; xx < XSize; xx += 2)
                {
                    for (int yy = 0; yy < YSize; yy += 2)
                    {
                        float here = terrainDef.GetHeightAtXYZ(xx + 0, yy + 0, 26);
                        float ln   = terrainDef.GetHeightAtXYZ(xx + 1, yy + 0, 26);
                        float ll   = terrainDef.GetHeightAtXYZ(xx + 0, yy + 1, 26);
                        float lr   = terrainDef.GetHeightAtXYZ(xx + 1, yy + 1, 26);
                        heightMap[xx / 2, yy / 2] = (here + ln + ll + lr) / 4;
                    }
                }
            }
            else
            {
                ConvOAR.Globals.log.DebugFormat("{0}: CreateTerrainMesh. creating terrain sized <{1},{2}>", LogHeader, XSize / 2, YSize / 2);
                for (int xx = 0; xx < XSize; xx++)
                {
                    for (int yy = 0; yy < YSize; yy++)
                    {
                        heightMap[xx, yy] = terrainDef.GetHeightAtXYZ(xx, yy, 26);
                    }
                }
            }

            // Number found in RegionSettings.cs as DEFAULT_TERRAIN_TEXTURE_3
            OMV.UUID convoarID = new OMV.UUID(ConvOAR.Globals.parms.P <string>("ConvoarID"));

            OMV.UUID defaultTextureID = new OMV.UUID("179cdabd-398a-9b6b-1391-4dc333ba321f");
            OMV.Primitive.TextureEntryFace terrainFace = new OMV.Primitive.TextureEntryFace(null);
            terrainFace.TextureID = defaultTextureID;

            EntityHandleUUID terrainTextureHandle = new EntityHandleUUID();
            MaterialInfo     terrainMaterialInfo  = new MaterialInfo(terrainFace);

            if (ConvOAR.Globals.parms.P <bool>("CreateTerrainSplat"))
            {
                // Use the OpenSim maptile generator to create a texture for the terrain
                var terrainRenderer = new TexturedMapTileRenderer();
                Nini.Config.IConfigSource config = new Nini.Config.IniConfigSource();
                terrainRenderer.Initialise(scene, config);

                var mapbmp = new Bitmap(terrainDef.Width, terrainDef.Height,
                                        System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                terrainRenderer.TerrainToBitmap(mapbmp);

                // Place the newly created image into the Displayable caches
                ImageInfo terrainImageInfo = new ImageInfo();
                terrainImageInfo.handle    = terrainTextureHandle;
                terrainImageInfo.image     = mapbmp;
                terrainImageInfo.resizable = false; // terrain image resolution is not reduced
                assetFetcher.Images.Add(new BHashULong(terrainTextureHandle.GetHashCode()), terrainTextureHandle, terrainImageInfo);
                // Store the new image into the asset system so it can be read later.
                assetFetcher.StoreTextureImage(terrainTextureHandle, scene.Name + " Terrain", convoarID, mapbmp);
                // Link this image to the material
                terrainFace.TextureID = terrainTextureHandle.GetUUID();
            }
            else
            {
                // Use the default texture code for terrain
                terrainTextureHandle = new EntityHandleUUID(defaultTextureID);
                BHash terrainHash = new BHashULong(defaultTextureID.GetHashCode());
                assetFetcher.GetImageInfo(terrainHash, () => {
                    ImageInfo terrainImageInfo = new ImageInfo();
                    terrainImageInfo.handle    = terrainTextureHandle;
                    assetFetcher.FetchTextureAsImage(terrainTextureHandle)
                    .Then(img => {
                        terrainImageInfo.image = img;
                    });
                    return(terrainImageInfo);
                });
            }

            // The above has created a MaterialInfo for the terrain texture

            ConvOAR.Globals.log.DebugFormat("{0}: CreateTerrainMesh. calling MeshFromHeightMap", LogHeader);
            DisplayableRenderable terrainDisplayable = assetMesher.MeshFromHeightMap(heightMap,
                                                                                     terrainDef.Width, terrainDef.Height, assetFetcher, terrainFace);

            BInstance   terrainInstance = new BInstance();
            Displayable terrainDisp     = new Displayable(terrainDisplayable);

            terrainDisp.name               = "Terrain";
            terrainDisp.baseUUID           = OMV.UUID.Random();
            terrainInstance.Representation = terrainDisp;

            return(terrainInstance);
        }
Example #12
0
 public bool GetDisplayable(BHash hash, out Displayable disp)
 {
     return(Displayables.TryGetValue(hash, out disp));
 }
Example #13
0
        // Convert a SceneObjectGroup into an instance with displayables
        public IPromise <BInstance> ConvertSogToInstance(SceneObjectGroup sog, IAssetFetcher assetFetcher, PrimToMesh mesher)
        {
            var prom = new Promise <BInstance>();

            LogBProgress("{0} ConvertSogToInstance: name={1}, id={2}, SOPs={3}",
                         _logHeader, sog.Name, sog.UUID, sog.Parts.Length);
            // Create meshes for all the parts of the SOG
            Promise <Displayable> .All(
                sog.Parts.Select(sop => {
                LogBProgress("{0} ConvertSOGToInstance: Calling CreateMeshResource for sog={1}, sop={2}",
                             _logHeader, sog.UUID, sop.UUID);
                OMV.Primitive aPrim = sop.Shape.ToOmvPrimitive();
                return(mesher.CreateMeshResource(sog, sop, aPrim, assetFetcher, OMVR.DetailLevel.Highest));
            })
                )
            .Then(renderables => {
                // Remove any failed SOG/SOP conversions.
                List <Displayable> filteredRenderables = renderables.Where(rend => rend != null).ToList();

                // 'filteredRenderables' are the DisplayRenderables for all the SOPs in the SOG
                // Get the root prim of the SOG
                List <Displayable> rootDisplayableList = filteredRenderables.Where(disp => {
                    return(disp.baseSOP.IsRoot);
                }).ToList();
                if (rootDisplayableList.Count != 1)
                {
                    // There should be only one root prim
                    ConvOAR.Globals.log.ErrorFormat("{0} ConvertSOGToInstance: Found not one root prim in SOG. ID={1}, numRoots={2}",
                                                    _logHeader, sog.UUID, rootDisplayableList.Count);
                    prom.Reject(new Exception(String.Format("Found more than one root prim in SOG. ID={0}", sog.UUID)));
                    return(null);
                }

                // The root of the SOG
                Displayable rootDisplayable = rootDisplayableList.First();

                // Collect all the children prims and add them to the root Displayable
                rootDisplayable.children = filteredRenderables.Where(disp => {
                    return(!disp.baseSOP.IsRoot);
                }).Select(disp => {
                    return(disp);
                }).ToList();

                return(rootDisplayable);
            })
            .Done(rootDisplayable => {
                // Add the Displayable into the collection of known Displayables for instancing
                assetFetcher.AddUniqueDisplayable(rootDisplayable);

                // Package the Displayable into an instance that is position in the world
                BInstance inst      = new BInstance();
                inst.Position       = sog.AbsolutePosition;
                inst.Rotation       = sog.GroupRotation;
                inst.Representation = rootDisplayable;

                if (ConvOAR.Globals.parms.P <bool>("LogBuilding"))
                {
                    DumpInstance(inst);
                }

                prom.Resolve(inst);
            }, e => {
                ConvOAR.Globals.log.ErrorFormat("{0} Failed meshing of SOG. ID={1}: {2}", _logHeader, sog.UUID, e);
                prom.Reject(new Exception(String.Format("failed meshing of SOG. ID={0}: {1}", sog.UUID, e)));
            });

            return(prom);
        }