Beispiel #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);
                }
            }
Beispiel #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);
        }
Beispiel #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);
        }
Beispiel #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;
 }
Beispiel #5
0
        // Convert the positions and all the vertices in an ExtendedPrim from one
        //     coordinate space to another. ExtendedPrim.coordSpace gives the current
        //     coordinates and we specify a new one here.
        // This is not a general solution -- it pretty much only works to convert
        //     right-handed,Z-up coordinates (OpenSimulator) to right-handed,Y-up
        //     (OpenGL).
        public static void FixCoordinates(BInstance inst, CoordAxis newCoords)
        {
            if (inst.coordAxis.system != newCoords.system)
            {
                OMV.Matrix4    coordTransform  = OMV.Matrix4.Identity;
                OMV.Quaternion coordTransformQ = OMV.Quaternion.Identity;
                if (inst.coordAxis.getUpDimension == CoordAxis.Zup &&
                    newCoords.getUpDimension == CoordAxis.Yup)
                {
                    // The one thing we know to do is change from Zup to Yup
                    coordTransformQ = OMV.Quaternion.CreateFromAxisAngle(1.0f, 0.0f, 0.0f, -(float)Math.PI / 2f);
                    // Make a clean matrix version.
                    // The libraries tend to create matrices with small numbers (1.119093e-07) for zero.
                    coordTransform = new OMV.Matrix4(
                        1, 0, 0, 0,
                        0, 0, -1, 0,
                        0, 1, 0, 0,
                        0, 0, 0, 1);
                }

                OMV.Vector3    oldPos = inst.Position; // DEBUG DEBUG
                OMV.Quaternion oldRot = inst.Rotation; // DEBUG DEBUG
                // Fix the location in space
                inst.Position = inst.Position * coordTransformQ;
                inst.Rotation = coordTransformQ * inst.Rotation;

                inst.coordAxis = newCoords;
                // ConvOAR.Globals.log.DebugFormat("{0} FixCoordinates. dispID={1}, oldPos={2}, newPos={3}, oldRot={4}, newRot={5}",
                //     _logHeader, inst.handle, oldPos, inst.Position, oldRot, inst.Rotation);

                // Go through all the vertices and change the UV coords if necessary
                List <MeshInfo> meshInfos = CollectMeshesFromDisplayable(inst.Representation);

                meshInfos.ForEach(meshInfo => {
                    if (meshInfo.coordAxis.getUVOrigin != newCoords.getUVOrigin)
                    {
                        for (int ii = 0; ii < meshInfo.vertexs.Count; ii++)
                        {
                            var vert             = meshInfo.vertexs[ii];
                            vert.TexCoord.Y      = 1f - vert.TexCoord.Y;
                            meshInfo.vertexs[ii] = vert;
                        }
                        meshInfo.coordAxis = newCoords;
                    }
                });
            }
            else
            {
                ConvOAR.Globals.log.DebugFormat("FixCoordinates. Not converting coord system. dispID={0}", inst.handle);
            }
        }
Beispiel #6
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);
        }
Beispiel #7
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);
        }
Beispiel #8
0
 // Create a new scene based on an existing scene.
 // NOTE: this is NOT a clone. Instances are not copied and other things just
 //    have their pointers moved so the items are shared.
 public BScene(BScene bScene)
 {
     name            = bScene.name;
     attributes      = bScene.attributes;
     terrainInstance = bScene.terrainInstance;
 }
Beispiel #9
0
        public Promise <BScene> ConvertOarToScene(IAssetService assetService, IAssetFetcher assetFetcher)
        {
            Promise <BScene> prom = new Promise <BScene>();

            // Assemble all the parameters that loadoar takes and uses
            Dictionary <string, object> options = new Dictionary <string, object>();

            // options.Add("merge", false);
            options.Add("displacement", ConvOAR.Globals.parms.P <OMV.Vector3>("Displacement"));
            string optRotation = ConvOAR.Globals.parms.P <string>("Rotation");

            if (optRotation != null)
            {
                options.Add("rotation", float.Parse(optRotation, System.Threading.Thread.CurrentThread.CurrentCulture));
            }
            // options.Add("default-user", OMV.UUID.Random());
            // if (optSkipAssets != null) options.Add('skipAssets', true);
            // if (optForceTerrain != null) options.Add("force-terrain", true);
            // if (optNoObjects != null) options.Add("no-objects", true);
            string optSubRegion = ConvOAR.Globals.parms.P <string>("SubRegion");

            if (optSubRegion != null)
            {
                List <float> bounds = optSubRegion.Split(',').Select <string, float>(x => { return(float.Parse(x)); }).ToList();
                options.Add("bounding-origin", new OMV.Vector3(bounds[0], bounds[1], bounds[2]));
                options.Add("bounding-size", new OMV.Vector3(bounds[3] - bounds[0], bounds[4] - bounds[1], bounds[5] - bounds[2]));
            }

            // Create an OpenSimulator region and scene to load the OAR into
            string regionName = "convoar";

            if (String.IsNullOrEmpty(ConvOAR.Globals.parms.P <String>("RegionName")))
            {
                // Try to build the region name from the OAR filesname
                regionName = Path.GetFileNameWithoutExtension(ConvOAR.Globals.parms.P <string>("InputOAR"));
            }
            else
            {
                regionName = ConvOAR.Globals.parms.P <string>("RegionName");
            }
            Scene scene = CreateScene(assetService, regionName);

            // Load the archive into our scene
            ArchiveReadRequest archive = new ArchiveReadRequest(scene, ConvOAR.Globals.parms.P <string>("InputOAR"), Guid.Empty, options);

            archive.DearchiveRegion(false);

            // Convert SOGs from OAR into EntityGroups
            // ConvOAR.Globals.log.Log("Num assets = {0}", assetService.NumAssets);
            LogBProgress("Num SOGs = {0}", scene.GetSceneObjectGroups().Count);

            PrimToMesh mesher = new PrimToMesh();

            // Convert SOGs => BInstances
            Promise <BInstance> .All(
                scene.GetSceneObjectGroups().Select(sog => {
                return(ConvertSogToInstance(sog, assetFetcher, mesher));
            })
                )
            .Done(instances => {
                ConvOAR.Globals.log.DebugFormat("{0} Num instances = {1}", _logHeader, instances.ToList().Count);
                List <BInstance> instanceList = new List <BInstance>();
                instanceList.AddRange(instances);

                // Add the terrain mesh to the scene
                BInstance terrainInstance = null;
                if (ConvOAR.Globals.parms.P <bool>("AddTerrainMesh"))
                {
                    ConvOAR.Globals.log.DebugFormat("{0} Creating terrain for scene", _logHeader);
                    // instanceList.Add(ConvoarTerrain.CreateTerrainMesh(scene, mesher, assetFetcher));
                    terrainInstance = ConvoarTerrain.CreateTerrainMesh(scene, mesher, assetFetcher);
                    CoordAxis.FixCoordinates(terrainInstance, new CoordAxis(CoordAxis.RightHand_Yup | CoordAxis.UVOriginLowerLeft));
                }

                // Twist the OpenSimulator Z-up coordinate system to the OpenGL Y-up
                foreach (var inst in instanceList)
                {
                    CoordAxis.FixCoordinates(inst, new CoordAxis(CoordAxis.RightHand_Yup | CoordAxis.UVOriginLowerLeft));
                }

                // package instances into a BScene
                BScene bScene          = new BScene();
                bScene.instances       = instanceList;
                RegionInfo ri          = scene.RegionInfo;
                bScene.name            = ri.RegionName;
                bScene.terrainInstance = terrainInstance;
                bScene.attributes.Add("RegionName", ri.RegionName);
                bScene.attributes.Add("RegionSizeX", ri.RegionSizeX);
                bScene.attributes.Add("RegionSizeY", ri.RegionSizeY);
                bScene.attributes.Add("RegionSizeZ", ri.RegionSizeZ);
                bScene.attributes.Add("RegionLocX", ri.RegionLocX);
                bScene.attributes.Add("RegionLocY", ri.RegionLocY);
                bScene.attributes.Add("WorldLocX", ri.WorldLocX);
                bScene.attributes.Add("WorldLocY", ri.WorldLocY);
                bScene.attributes.Add("WaterHeight", ri.RegionSettings.WaterHeight);
                bScene.attributes.Add("DefaultLandingPorint", ri.DefaultLandingPoint);

                prom.Resolve(bScene);
            }, e => {
                ConvOAR.Globals.log.ErrorFormat("{0} failed SOG conversion: {1}", _logHeader, e);
                // prom.Reject(new Exception(String.Format("Failed conversion: {0}", e)));
            });

            return(prom);
        }
Beispiel #10
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);
        }