// 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); } }
// 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); }
// 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); }
// 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); }