/// <summary> /// Wraps the given raw mesh as a BXDA Submesh with a single surface. /// </summary> /// <param name="verts">The verticies. (3 elements per vertex)</param> /// <param name="vertCount">The vertex count.</param> /// <param name="inds">The index buffer. (3 element per triangle, zero based)</param> /// <param name="trisCount">The triangle count</param> /// <returns>The resulting mesh</returns> private static BXDAMesh.BXDASubMesh ExportSubMesh(float[] verts, uint vertCount, uint[] inds, uint trisCount) { Simplify(ref verts, ref vertCount, ref inds, ref trisCount); BXDAMesh.BXDASubMesh sub = new BXDAMesh.BXDASubMesh(); sub.norms = null; sub.verts = new double[verts.Length]; for (uint i2 = 0; i2 < vertCount * 3; i2++) { sub.verts[i2] = verts[i2]; } BXDAMesh.BXDASurface collisionSurface = new BXDAMesh.BXDASurface(); collisionSurface.indicies = new int[inds.Length]; for (uint i2 = 0; i2 < trisCount * 3; i2++) { collisionSurface.indicies[i2] = (int)inds[i2]; } sub.surfaces = new List <BXDAMesh.BXDASurface>(); sub.surfaces.Add(collisionSurface); return(sub); }
public static Material AsMaterial(this BXDAMesh.BXDASurface surf, bool emissive = false) { uint val = surf.hasColor ? surf.color : 0xFFFFFFFF; Color color = new Color32((byte)(val & 0xFF), (byte)((val >> 8) & 0xFF), (byte)((val >> 16) & 0xFF), (byte)((val >> 24) & 0xFF)); if (surf.transparency != 0) { color.a = surf.transparency; } else if (surf.translucency != 0) { color.a = surf.translucency; } if (color.a == 0) // No perfectly transparent things plz. { color.a = 1; } Material result = new Material(Shader.Find(emissive ? "Standard" : (color.a != 1 ? "Transparent/" : "") + (surf.specular > 0 ? "Specular" : "Diffuse"))); result.SetColor("_Color", color); if (surf.specular > 0) { result.SetFloat("_Shininess", surf.specular); result.SetColor("_SpecColor", color); } if (emissive) { result.EnableKeyword("_EMISSION"); result.SetColor("_EmissionColor", Color.black); } return(result); }
public static Material AsMaterial(this BXDAMesh.BXDASurface surf) { uint val = surf.hasColor ? surf.color : 0xFFFFFFFF; Color color = new Color32((byte)(val & 0xFF), (byte)((val >> 8) & 0xFF), (byte)((val >> 16) & 0xFF), (byte)((val >> 24) & 0xFF)); if (surf.transparency != 0) { color.a = surf.transparency; } else if (surf.translucency != 0) { color.a = surf.translucency; } if (color.a == 0) // No perfectly transparent things plz. { color.a = 1; } Material result = new Material((Shader)Shader.Find((color.a != 1 ? "Transparent/" : "") + (surf.specular > 0 ? "Specular" : "Diffuse"))); result.SetColor("_Color", color); if (surf.specular > 0) { result.SetFloat("_Shininess", surf.specular); result.SetColor("_SpecColor", color); } return(result); }
/// <summary> /// Adds a surface to the output mesh. Not saved as a sub-surface until <see cref="DumpOutput"/> is called. /// </summary> /// <param name="bufferSurface">Surface to add to mesh.</param> /// <param name="asset">Asset for surface.</param> public void AddSurface(ref PartialSurface bufferSurface, AssetProperties asset) { // Create new surface BXDAMesh.BXDASurface newMeshSurface = new BXDAMesh.BXDASurface(); // Apply Asset Properties if (asset == null) { return; } newMeshSurface.hasColor = true; newMeshSurface.color = asset.color; newMeshSurface.transparency = (float)asset.transparency; newMeshSurface.translucency = (float)asset.translucency; newMeshSurface.specular = (float)asset.specular; // Prevent too many vertices if (bufferSurface.verts.count > MAX_VERTS_OR_FACETS) { throw new TooManyVerticesException(); } int indexOffset; lock (outputVerts) { // Prevent too many vertices if (outputVerts.count + bufferSurface.verts.count > MAX_VERTS_OR_FACETS) { DumpOutputInternal(); } // Copy buffer vertices into output Array.Copy(bufferSurface.verts.coordinates, 0, outputVerts.coordinates, outputVerts.count * 3, bufferSurface.verts.count * 3); Array.Copy(bufferSurface.verts.norms, 0, outputVerts.norms, outputVerts.count * 3, bufferSurface.verts.count * 3); // Store length of output verts for later indexOffset = outputVerts.count - 1; outputVerts.count += bufferSurface.verts.count; } // Copy buffer surface into output, incrementing indices relative to where verts where stitched into the vert array newMeshSurface.indicies = new int[bufferSurface.facets.count * 3]; for (int i = 0; i < bufferSurface.facets.count * 3; i++) { newMeshSurface.indicies[i] = bufferSurface.facets.indices[i] + indexOffset; // Why does Inventor start from 1?! } // Add the new surface to the output lock (outputMeshSurfaces) outputMeshSurfaces.Add(newMeshSurface); // Empty buffer bufferSurface.verts.count = 0; bufferSurface.facets.count = 0; }
private void reloadSubMesh(BXDAEditorNode subMeshNode) { foreach (BXDAEditorNode surfaceNode in subMeshNode.LastNode.Nodes) { BXDAMesh.BXDASurface surface = (BXDAMesh.BXDASurface)surfaceNode.data[0]; BXDAEditorNode materialNode = (BXDAEditorNode)surfaceNode.Nodes[0]; surface.hasColor = (bool)((BXDAEditorNode)materialNode.Nodes[0]).data[1]; surface.color = (uint)((BXDAEditorNode)materialNode.Nodes[0]).data[0]; surface.transparency = (float)((BXDAEditorNode)materialNode.Nodes[1]).data[0]; surface.translucency = (float)((BXDAEditorNode)materialNode.Nodes[2]).data[0]; surface.specular = (float)((BXDAEditorNode)materialNode.Nodes[3]).data[0]; } }
/// <summary> /// Copies mesh information for the given surface body into the mesh storage structure. /// </summary> /// <param name="surf">The surface body to export</param> /// <param name="bestResolution">Use the best possible resolution</param> /// <param name="separateFaces">Separate the surface body into one mesh per face</param> private void AddFacets(SurfaceBody surf, bool bestResolution = false, bool separateFaces = false) { BXDAMesh.BXDASurface nextSurface = new BXDAMesh.BXDASurface(); surf.GetExistingFacetTolerances(out tmpToleranceCount, out tolerances); int bestIndex = -1; for (int i = 0; i < tmpToleranceCount; i++) { if (bestIndex < 0 || ((tolerances[i] < tolerances[bestIndex]) == bestResolution)) { bestIndex = i; } } #region SHOULD_SEPARATE_FACES AssetProperties sharedValue = null; string sharedDisp = null; if (separateFaces) // Only separate if they are actually different colors { separateFaces = false; foreach (Face f in surf.Faces) { try { Asset ast = f.Appearance; if (sharedValue == null) { sharedValue = new AssetProperties(ast); sharedDisp = ast.DisplayName; } else if (!ast.DisplayName.Equals(sharedDisp)) { separateFaces = true; break; } } catch { } } } #endregion #if USE_TEXTURES surf.GetExistingFacetsAndTextureMap(tolerances[bestIndex], out tmpSurface.vertCount, out tmpSurface.facetCount, out tmpSurface.verts, out tmpSurface.norms, out tmpSurface.indicies, out tmpSurface.textureCoords); if (tmpSurface.vertCount == 0) { surf.CalculateFacetsAndTextureMap(tolerances[bestIndex], out tmpSurface.vertCount, out tmpSurface.facetCount, out tmpSurface.verts, out tmpSurface.norms, out tmpSurface.indicies, out tmpSurface.textureCoords); } #else surf.GetExistingFacets(tolerances[bestIndex], out tmpSurface.vertCount, out tmpSurface.facetCount, out tmpSurface.verts, out tmpSurface.norms, out tmpSurface.indicies); if (tmpSurface.vertCount == 0) { surf.CalculateFacets(tolerances[bestIndex], out tmpSurface.vertCount, out tmpSurface.facetCount, out tmpSurface.verts, out tmpSurface.norms, out tmpSurface.indicies); } #endif if (separateFaces || tmpSurface.vertCount > TMP_VERTICIES) { int i = 0; foreach (Face f in surf.Faces) { i++; AddFacets(f, tolerances[bestIndex]); } } else { //Console.WriteLine("Exporting single block for " + surf.Parent.Name + "\t(" + surf.Name + ")"); AssetProperties assetProps = sharedValue; if (sharedValue == null) { assetProps = AssetProperties.Create(surf); } if (assetProps != null) { AddFacetsInternal(assetProps); } } }
/// <summary> /// Moves the mesh currently in the temporary mesh buffer into the mesh structure itself, /// with material information from the asset properties. /// </summary> /// <param name="assetProps">Material information to use</param> private void AddFacetsInternal(AssetProperties assetProps) { if (tmpSurface.vertCount > TMP_VERTICIES) { // This is just bad. It could be fixed by exporting it per-face instead of with a single block. System.Windows.Forms.MessageBox.Show("Warning: Mesh segment exceededed " + TMP_VERTICIES + " verticies. Strange things may begin to happen."); } // If adding this would cause the sub mesh to overflow dump what currently exists. if (tmpSurface.vertCount + postSurface.vertCount >= TMP_VERTICIES) { DumpMeshBuffer(); } Array.Copy(tmpSurface.verts, 0, postSurface.verts, postSurface.vertCount * 3, tmpSurface.vertCount * 3); Array.Copy(tmpSurface.norms, 0, postSurface.norms, postSurface.vertCount * 3, tmpSurface.vertCount * 3); #if USE_TEXTURES Array.Copy(tmpSurface.textureCoords, 0, postSurface.textureCoords, postSurface.vertCount * 2, tmpSurface.vertCount * 2); #endif BXDAMesh.BXDASurface nextSurface = new BXDAMesh.BXDASurface(); nextSurface.color = 0xFFFFFFFF; if (assetProps.color != null) { nextSurface.hasColor = true; nextSurface.color = ((uint)assetProps.color.Red << 0) | ((uint)assetProps.color.Green << 8) | ((uint)assetProps.color.Blue << 16) | ((((uint)(assetProps.color.Opacity * 255)) & 0xFF) << 24); } nextSurface.transparency = (float)assetProps.transparency; nextSurface.translucency = (float)assetProps.translucency; nextSurface.specular = (float)assetProps.specular; nextSurface.indicies = new int[tmpSurface.facetCount * 3]; // Raw copy the indicies for now, then fix the offset in a background thread. Array.Copy(tmpSurface.indicies, nextSurface.indicies, nextSurface.indicies.Length); #region Fix Index Buffer Offset // Make sure we haven't exceeded the maximum number of background tasks. if (waitingThreads.Count > MAX_BACKGROUND_THREADS) { // Console.WriteLine("Got ahead of ourselves...."); System.Threading.WaitHandle.WaitAll(waitingThreads.ToArray()); waitingThreads.Clear(); } { System.Threading.ManualResetEvent lockThing = new System.Threading.ManualResetEvent(false); waitingThreads.Add(lockThing); int offset = postSurface.vertCount; int backingFacetCount = tmpSurface.facetCount; System.Threading.ThreadPool.QueueUserWorkItem(delegate(object obj) { for (int i = 0; i < backingFacetCount * 3; i++) { nextSurface.indicies[i] = nextSurface.indicies[i] + offset - 1; // Inventor has one-based indicies. Zero-based is the way to go for everything except Inventor. } lockThing.Set(); }, waitingThreads.Count); } #endregion postSurfaces.Add(nextSurface); postSurface.facetCount += tmpSurface.facetCount; postSurface.vertCount += tmpSurface.vertCount; }