// I had a lot of trouble with problems with equality and GetHashCode of OMVR.Vertex // so this implementation creates a proper hash for a Vertex so it can be used // in a dictionary. public static BHash VertexBHash(OMVR.Vertex vert) { BHasher hasher = new BHasherMdjb2(); MeshInfo.VertexBHash(vert, hasher); return(hasher.Finish()); }
public MeshInfo GetMeshInfo(BHash hash, MeshInfoBuilder builder) { MeshInfo meshInfo = null; lock (Meshes) { if (!Meshes.TryGetValue(hash, out meshInfo)) { if (builder != null) { meshInfo = builder(); Meshes.Add(hash, meshInfo.handle, meshInfo); // Assert the hash we're indexing it under is the one in meshInfo if (!hash.Equals(meshInfo.GetBHash())) { ConvOAR.Globals.log.ErrorFormat( "AssetFetcher.GetMeshInfo: adding mesh with different hash!"); ConvOAR.Globals.log.ErrorFormat( "AssetFetcher.GetMeshInfo: meshInfo.handle={0}, passed hash={1}, meshInfo.hash={2}", meshInfo.handle, hash.ToString(), meshInfo.GetBHash().ToString()); } } else { meshInfo = null; } } } return(meshInfo); }
public BHash GetBHash(bool force) { if (force) { _hash = null; } if (_hash == null) { BHasher hasher = new BHasherMdjb2(); vertexs.ForEach(vert => { MeshInfo.VertexBHash(vert, hasher); }); indices.ForEach(ind => { hasher.Add(ind); }); hasher.Add(faceCenter.X); hasher.Add(faceCenter.Y); hasher.Add(faceCenter.Z); hasher.Add(scale.X); hasher.Add(scale.Y); hasher.Add(scale.Z); _hash = hasher.Finish(); } return(_hash); }
public static void OnAllVertex(MeshInfo mi, OperateOnVertex vertOp) { for (int jj = 0; jj < mi.vertexs.Count; jj++) { OMVR.Vertex aVert = mi.vertexs[jj]; vertOp(ref aVert); mi.vertexs[jj] = aVert; } }
// 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 the passed MeshInfo the to list if it is not already in the list public void AddUniqueMeshInfo(MeshInfo meshInfo) { lock (Meshes) { MeshInfo existingMeshInfo = null; if (!Meshes.TryGetValue(meshInfo.GetBHash(), out existingMeshInfo)) { // If not already in the list, add this MeshInfo Meshes.Add(meshInfo.GetBHash(), meshInfo.handle, meshInfo); } } }
// Create a new MeshInfo with a copy of what is in another MeshInfo. // Note that we need to do a deep'ish copy since the values of the // vertices may be modified in the copy. // OMVR.Vertex and OMV.Vextor3 are structs so they are copied. public MeshInfo(MeshInfo other) { handle = new EntityHandleUUID(); vertexs = other.vertexs.ConvertAll(v => { OMVR.Vertex newV = new OMVR.Vertex(); newV.Position = v.Position; newV.Normal = v.Normal; newV.TexCoord = v.TexCoord; return(newV); }); // vertexs = new List<OMVR.Vertex>(other.vertexs); indices = new List <int>(other.indices); scale = new OMV.Vector3(other.scale); faceCenter = new OMV.Vector3(other.faceCenter); }
// Walk through all the vertices and scale the included meshes // Returns 'true' of the mesh was changed. public static bool ScaleMeshes(MeshInfo meshInfo, OMV.Vector3 scale) { bool ret = false; if (scale.X != 1.0 || scale.Y != 1.0 || scale.Z != 1.0) { ret = true; for (int ii = 0; ii < meshInfo.vertexs.Count; ii++) { OMVR.Vertex aVert = meshInfo.vertexs[ii]; aVert.Position *= scale; meshInfo.vertexs[ii] = aVert; } } return(ret); }
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); }