private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim) { if ((PCode)prim.Shape.PCode != PCode.Prim) { return; } Vector3 ppos = prim.GetWorldPosition(); if (ppos.Z < m_renderMinHeight || ppos.Z > m_renderMaxHeight) { return; } warp_Vector primPos = ConvertVector(ppos); warp_Quaternion primRot = ConvertQuaternion(prim.GetWorldRotation()); warp_Matrix m = warp_Matrix.quaternionMatrix(primRot); float screenFactor = renderer.Scene.EstimateBoxProjectedArea(primPos, ConvertVector(prim.Scale), m); if (screenFactor < 0) { return; } const float log2inv = -1.442695f; int p2 = (int)((float)Math.Log(screenFactor) * log2inv * 0.25 - 1); if (p2 < 0) { p2 = 0; } else if (p2 > 3) { p2 = 3; } DetailLevel lod = (DetailLevel)(3 - p2); FacetedMesh renderMesh = null; Primitive omvPrim = prim.Shape.ToOmvPrimitive(prim.OffsetPosition, prim.RotationOffset); if (m_renderMeshes) { if (omvPrim.Sculpt != null && omvPrim.Sculpt.SculptTexture != UUID.Zero) { // Try fetchinng the asset AssetBase sculptAsset = m_scene.AssetService.Get(omvPrim.Sculpt.SculptTexture.ToString()); if (sculptAsset != null) { // Is it a mesh? if (omvPrim.Sculpt.Type == SculptType.Mesh) { AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset.Data); FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, lod, out renderMesh); meshAsset = null; } else // It's sculptie { if (m_imgDecoder != null) { Image sculpt = m_imgDecoder.DecodeToImage(sculptAsset.Data); if (sculpt != null) { renderMesh = m_primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, lod); sculpt.Dispose(); } } } } else { m_log.WarnFormat("[Warp3D] failed to get mesh or sculpt asset {0} of prim {1} at {2}", omvPrim.Sculpt.SculptTexture.ToString(), prim.Name, prim.GetWorldPosition().ToString()); } } } // If not a mesh or sculptie, try the regular mesher if (renderMesh == null) { renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, lod); } if (renderMesh == null) { return; } string primID = prim.UUID.ToString(); // Create the prim faces // TODO: Implement the useTextures flag behavior for (int i = 0; i < renderMesh.Faces.Count; i++) { Face face = renderMesh.Faces[i]; string meshName = primID + i.ToString(); // Avoid adding duplicate meshes to the scene if (renderer.Scene.objectData.ContainsKey(meshName)) { continue; } warp_Object faceObj = new warp_Object(); Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i); Color4 faceColor = teFace.RGBA; if (faceColor.A == 0) { continue; } string materialName = string.Empty; if (m_texturePrims) { // if(lod > DetailLevel.Low) { // materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID, lod == DetailLevel.Low); materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID, false, prim); if (String.IsNullOrEmpty(materialName)) { continue; } int c = renderer.Scene.material(materialName).getColor(); if ((c & warp_Color.MASKALPHA) == 0) { continue; } } } else { materialName = GetOrCreateMaterial(renderer, faceColor); } if (renderer.Scene.material(materialName).getTexture() == null) { // uv map details dont not matter for color; for (int j = 0; j < face.Vertices.Count; j++) { Vertex v = face.Vertices[j]; warp_Vector pos = ConvertVector(v.Position); warp_Vertex vert = new warp_Vertex(pos, v.TexCoord.X, v.TexCoord.Y); faceObj.addVertex(vert); } } else { float tu; float tv; float offsetu = teFace.OffsetU + 0.5f; float offsetv = teFace.OffsetV + 0.5f; float scaleu = teFace.RepeatU; float scalev = teFace.RepeatV; float rotation = teFace.Rotation; float rc = 0; float rs = 0; if (rotation != 0) { rc = (float)Math.Cos(rotation); rs = (float)Math.Sin(rotation); } for (int j = 0; j < face.Vertices.Count; j++) { warp_Vertex vert; Vertex v = face.Vertices[j]; warp_Vector pos = ConvertVector(v.Position); if (teFace.TexMapType == MappingType.Planar) { UVPlanarMap(v, prim.Scale, out tu, out tv); } else { tu = v.TexCoord.X - 0.5f; tv = 0.5f - v.TexCoord.Y; } if (rotation != 0) { float tur = tu * rc - tv * rs; float tvr = tu * rs + tv * rc; tur *= scaleu; tur += offsetu; tvr *= scalev; tvr += offsetv; vert = new warp_Vertex(pos, tur, tvr); } else { tu *= scaleu; tu += offsetu; tv *= scalev; tv += offsetv; vert = new warp_Vertex(pos, tu, tv); } faceObj.addVertex(vert); } } for (int j = 0; j < face.Indices.Count; j += 3) { faceObj.addTriangle( face.Indices[j + 0], face.Indices[j + 1], face.Indices[j + 2]); } faceObj.scaleSelf(prim.Scale.X, prim.Scale.Z, prim.Scale.Y); faceObj.transform(m); faceObj.setPos(primPos); renderer.Scene.addObject(meshName, faceObj); renderer.SetObjectMaterial(meshName, materialName); } }
private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim, bool useTextures) { const float MIN_SIZE_SQUARE = 4f; if ((PCode)prim.Shape.PCode != PCode.Prim) { return; } float primScaleLenSquared = prim.Scale.LengthSquared(); if (primScaleLenSquared < MIN_SIZE_SQUARE) { return; } FacetedMesh renderMesh = null; Primitive omvPrim = prim.Shape.ToOmvPrimitive(prim.OffsetPosition, prim.RotationOffset); if (m_renderMeshes) { if (omvPrim.Sculpt != null && omvPrim.Sculpt.SculptTexture != UUID.Zero) { // Try fetchinng the asset byte[] sculptAsset = m_scene.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); if (sculptAsset != null) { // Is it a mesh? if (omvPrim.Sculpt.Type == SculptType.Mesh) { AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out renderMesh); meshAsset = null; } else // It's sculptie { IJ2KDecoder imgDecoder = m_scene.RequestModuleInterface <IJ2KDecoder>(); if (imgDecoder != null) { Image sculpt = imgDecoder.DecodeToImage(sculptAsset); if (sculpt != null) { renderMesh = m_primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium); sculpt.Dispose(); } } } } } } // If not a mesh or sculptie, try the regular mesher if (renderMesh == null) { renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, DetailLevel.Medium); } if (renderMesh == null) { return; } string primID = prim.UUID.ToString(); // Create the prim faces // TODO: Implement the useTextures flag behavior for (int i = 0; i < renderMesh.Faces.Count; i++) { Face face = renderMesh.Faces[i]; string meshName = primID + i.ToString(); // Avoid adding duplicate meshes to the scene if (renderer.Scene.objectData.ContainsKey(meshName)) { continue; } warp_Object faceObj = new warp_Object(); for (int j = 0; j < face.Vertices.Count; j++) { Vertex v = face.Vertices[j]; warp_Vector pos = ConvertVector(v.Position); warp_Vertex vert = new warp_Vertex(pos, v.TexCoord.X, v.TexCoord.Y); faceObj.addVertex(vert); } for (int j = 0; j < face.Indices.Count; j += 3) { faceObj.addTriangle( face.Indices[j + 0], face.Indices[j + 1], face.Indices[j + 2]); } Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i); Color4 faceColor = GetFaceColor(teFace); string materialName = String.Empty; if (m_texturePrims && primScaleLenSquared > m_texturePrimSize * m_texturePrimSize) { materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID); } else { materialName = GetOrCreateMaterial(renderer, faceColor); } warp_Vector primPos = ConvertVector(prim.GetWorldPosition()); warp_Quaternion primRot = ConvertQuaternion(prim.GetWorldRotation()); warp_Matrix m = warp_Matrix.quaternionMatrix(primRot); faceObj.transform(m); faceObj.setPos(primPos); faceObj.scaleSelf(prim.Scale.X, prim.Scale.Z, prim.Scale.Y); renderer.Scene.addObject(meshName, faceObj); renderer.SetObjectMaterial(meshName, materialName); } }
/// <summary> /// Decodes mesh asset into FacetedMesh /// </summary> /// <param name="prim">Mesh primitive</param> /// <param name="meshAsset">Asset retrieved from the asset server</param> /// <param name="LOD">Level of detail</param> /// <param name="mesh">Resulting decoded FacetedMesh</param> /// <returns>True if mesh asset decoding was successful</returns> public static bool TryDecodeFromAsset(Primitive prim, AssetMesh meshAsset, DetailLevel LOD, out FacetedMesh mesh) { mesh = null; try { if (!meshAsset.Decode()) { return(false); } OSDMap MeshData = meshAsset.MeshData; mesh = new FacetedMesh(); mesh.Faces = new List <Face>(); mesh.Prim = prim; mesh.Profile.Faces = new List <ProfileFace>(); mesh.Profile.Positions = new List <Vector3>(); mesh.Path.Points = new List <PathPoint>(); OSD facesOSD = null; switch (LOD) { default: case DetailLevel.Highest: facesOSD = MeshData["high_lod"]; break; case DetailLevel.High: facesOSD = MeshData["medium_lod"]; break; case DetailLevel.Medium: facesOSD = MeshData["low_lod"]; break; case DetailLevel.Low: facesOSD = MeshData["lowest_lod"]; break; } if (facesOSD == null || !(facesOSD is OSDArray)) { return(false); } OSDArray decodedMeshOsdArray = (OSDArray)facesOSD; for (int faceNr = 0; faceNr < decodedMeshOsdArray.Count; faceNr++) { OSD subMeshOsd = decodedMeshOsdArray[faceNr]; // Decode each individual face if (subMeshOsd is OSDMap) { Face oface = new Face(); oface.ID = faceNr; oface.Vertices = new List <Vertex>(); oface.Indices = new List <ushort>(); oface.TextureFace = prim.Textures.GetFace((uint)faceNr); OSDMap subMeshMap = (OSDMap)subMeshOsd; Vector3 posMax; Vector3 posMin; // If PositionDomain is not specified, the default is from -0.5 to 0.5 if (subMeshMap.ContainsKey("PositionDomain")) { posMax = ((OSDMap)subMeshMap["PositionDomain"])["Max"]; posMin = ((OSDMap)subMeshMap["PositionDomain"])["Min"]; } else { posMax = new Vector3(0.5f, 0.5f, 0.5f); posMin = new Vector3(-0.5f, -0.5f, -0.5f); } // Vertex positions byte[] posBytes = subMeshMap["Position"]; // Normals byte[] norBytes = null; if (subMeshMap.ContainsKey("Normal")) { norBytes = subMeshMap["Normal"]; } // UV texture map Vector2 texPosMax = Vector2.Zero; Vector2 texPosMin = Vector2.Zero; byte[] texBytes = null; if (subMeshMap.ContainsKey("TexCoord0")) { texBytes = subMeshMap["TexCoord0"]; texPosMax = ((OSDMap)subMeshMap["TexCoord0Domain"])["Max"]; texPosMin = ((OSDMap)subMeshMap["TexCoord0Domain"])["Min"]; } // Extract the vertex position data // If present normals and texture coordinates too for (int i = 0; i < posBytes.Length; i += 6) { ushort uX = Utils.BytesToUInt16(posBytes, i); ushort uY = Utils.BytesToUInt16(posBytes, i + 2); ushort uZ = Utils.BytesToUInt16(posBytes, i + 4); Vertex vx = new Vertex(); vx.Position = new Vector3( Utils.UInt16ToFloat(uX, posMin.X, posMax.X), Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y), Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z)); if (norBytes != null && norBytes.Length >= i + 4) { ushort nX = Utils.BytesToUInt16(norBytes, i); ushort nY = Utils.BytesToUInt16(norBytes, i + 2); ushort nZ = Utils.BytesToUInt16(norBytes, i + 4); vx.Normal = new Vector3( Utils.UInt16ToFloat(nX, posMin.X, posMax.X), Utils.UInt16ToFloat(nY, posMin.Y, posMax.Y), Utils.UInt16ToFloat(nZ, posMin.Z, posMax.Z)); } var vertexIndexOffset = oface.Vertices.Count * 4; if (texBytes != null && texBytes.Length >= vertexIndexOffset + 4) { ushort tX = Utils.BytesToUInt16(texBytes, vertexIndexOffset); ushort tY = Utils.BytesToUInt16(texBytes, vertexIndexOffset + 2); vx.TexCoord = new Vector2( Utils.UInt16ToFloat(tX, texPosMin.X, texPosMax.X), Utils.UInt16ToFloat(tY, texPosMin.Y, texPosMax.Y)); } oface.Vertices.Add(vx); } byte[] triangleBytes = subMeshMap["TriangleList"]; for (int i = 0; i < triangleBytes.Length; i += 6) { ushort v1 = (ushort)(Utils.BytesToUInt16(triangleBytes, i)); oface.Indices.Add(v1); ushort v2 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 2)); oface.Indices.Add(v2); ushort v3 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 4)); oface.Indices.Add(v3); } mesh.Faces.Add(oface); } } } catch (Exception ex) { Logger.Log("Failed to decode mesh asset: " + ex.Message, Helpers.LogLevel.Warning); return(false); } return(true); }
private void Asset_MeshCallback(bool success, AssetMesh assetMesh) { lock (Manager.AssetsReceived) Manager.AssetsReceived[assetMesh.AssetID] = success; }
void CreatePrim(WarpRenderer renderer, ISceneChildEntity prim, bool texturePrims) { try { if ((PCode)prim.Shape.PCode != PCode.Prim) { return; } if (prim.Scale.LengthSquared() < MIN_PRIM_SIZE * MIN_PRIM_SIZE) { return; } Primitive omvPrim = prim.Shape.ToOmvPrimitive(prim.OffsetPosition, prim.GetRotationOffset()); FacetedMesh renderMesh = null; // Are we dealing with a sculptie or mesh? if (omvPrim.Sculpt != null && omvPrim.Sculpt.SculptTexture != UUID.Zero) { // Try fetching the asset byte [] sculptAsset = m_scene.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); if (sculptAsset != null) { // Is it a mesh? if (omvPrim.Sculpt.Type == SculptType.Mesh) { AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out renderMesh); meshAsset = null; } else // It's sculptie { Image sculpt = m_imgDecoder.DecodeToImage(sculptAsset); if (sculpt != null) { renderMesh = m_primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium); sculpt.Dispose(); } } sculptAsset = null; } else { // missing sculpt data... replace with something renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, DetailLevel.Medium); } } else // Prim { renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, DetailLevel.Medium); } if (renderMesh == null) { return; } warp_Vector primPos = ConvertVector(prim.GetWorldPosition()); warp_Quaternion primRot = ConvertQuaternion(prim.GetRotationOffset()); warp_Matrix m = warp_Matrix.quaternionMatrix(primRot); if (prim.ParentID != 0) { ISceneEntity group = m_scene.GetGroupByPrim(prim.LocalId); if (group != null) { m.transform(warp_Matrix.quaternionMatrix(ConvertQuaternion(group.RootChild.GetRotationOffset()))); } } warp_Vector primScale = ConvertVector(prim.Scale); string primID = prim.UUID.ToString(); // Create the prim faces for (int i = 0; i < renderMesh.Faces.Count; i++) { Face renderFace = renderMesh.Faces [i]; string meshName = primID + "-Face-" + i; warp_Object faceObj = new warp_Object(renderFace.Vertices.Count, renderFace.Indices.Count / 3); foreach (Vertex v in renderFace.Vertices) { warp_Vector pos = ConvertVector(v.Position); warp_Vector norm = ConvertVector(v.Normal); if (prim.Shape.SculptTexture == UUID.Zero) { norm = norm.reverse(); } warp_Vertex vert = new warp_Vertex(pos, norm, v.TexCoord.X, v.TexCoord.Y); faceObj.addVertex(vert); } for (int j = 0; j < renderFace.Indices.Count;) { faceObj.addTriangle( renderFace.Indices [j++], renderFace.Indices [j++], renderFace.Indices [j++]); } Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i); string materialName; Color4 faceColor = GetFaceColor(teFace); if (texturePrims && (prim.Scale.LengthSquared() > m_texturePrimSize)) { materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID); } else { materialName = GetOrCreateMaterial(renderer, faceColor); } faceObj.transform(m); faceObj.setPos(primPos); faceObj.scaleSelf(primScale.x, primScale.y, primScale.z); renderer.Scene.addObject(meshName, faceObj); renderer.SetObjectMaterial(meshName, materialName); faceObj = null; } renderMesh.Faces.Clear(); renderMesh = null; } catch (Exception ex) { MainConsole.Instance.Warn("[WarpTile generator]: Exception creating prim, " + ex); } }