private void AddMesh() { Vector3[] vertices = new Vector3[] { new Vector3(-5f, 0f, -5f), new Vector3(5f, 0f, -5f), new Vector3(5f, 0f, 5f), new Vector3(-5f, 0f, 5f) }; Vector3[] normals = new Vector3[] { Vector3.Up, Vector3.Up, Vector3.Up, Vector3.Up }; int[] indices = new int[] { 0, 1, 2, 0, 2, 3 }; Godot.Collections.Array meshData = new Godot.Collections.Array(); meshData.Resize((int)Mesh.ArrayType.Max); meshData[(int)Mesh.ArrayType.Vertex] = vertices; meshData[(int)Mesh.ArrayType.Normal] = normals; meshData[(int)Mesh.ArrayType.Index] = indices; _mesh = VisualServer.MeshCreate(); VisualServer.MeshAddSurfaceFromArrays(_mesh, VisualServer.PrimitiveType.Triangles, meshData); _instance = VisualServer.InstanceCreate(); VisualServer.InstanceSetBase(_instance, _mesh); RID scenario = GetWorld().Scenario; VisualServer.InstanceSetScenario(_instance, scenario); }
private ArrayMesh draw_hex_tri(Vector3[] base_verts, ref ArrayMesh local_array_mesh) { Mesh a = new ArrayMesh(); Godot.Collections.Array mesh_arrays = new Godot.Collections.Array(); int[] indices = new int[] { 0, 1, 2, 0, 2, 3 }; mesh_arrays.Resize((int)Mesh.ArrayType.Max); for (int i = 0; i < 3; i++) { List <Vector3> verts = new List <Vector3>(); for (int i2 = 0; i2 < base_verts.Length; i2++) { verts.Add(point_rotation(base_verts[i2], base_verts[2], 120f * i)); } //mesh_arrays[Godot.Mesh] = verts; mesh_arrays[(int)ArrayMesh.ArrayType.Vertex] = verts.ToArray(); mesh_arrays[(int)ArrayMesh.ArrayType.Index] = indices; } local_array_mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, mesh_arrays); return(local_array_mesh); }
// Called when the node enters the scene tree for the first time. public override void _Ready() { StreamReader textReader = new StreamReader(@"./UMA/Content/UMA_Core/HumanMale/Slots/Body/UMA_Human_Male_Legs_Slot.asset"); textReader.ReadLine(); textReader.ReadLine(); textReader.ReadLine(); var deserializer = new DeserializerBuilder() .WithNamingConvention(new CamelCaseNamingConvention()) .Build(); var slotData = deserializer.Deserialize <SlotYaml>(textReader); GD.Print(slotData.MonoBehaviour.MName); var verticeOrder = decodeUnitysCompressionSubMesh(slotData.MonoBehaviour.MeshData.Submeshes[0].Triangles); var surfaceArray = new Godot.Collections.Array(); surfaceArray.Resize(ARRAY_MAX); surfaceArray[ARRAY_VERTEX] = slotData.MonoBehaviour.MeshData.Vertices; surfaceArray[ARRAY_NORMAL] = slotData.MonoBehaviour.MeshData.Normals; surfaceArray[ARRAY_TANGENTS] = CreateTangents(slotData.MonoBehaviour.MeshData.Tangents); surfaceArray[ARRAY_TEX_UV] = slotData.MonoBehaviour.MeshData.Uv; surfaceArray[ARRAY_INDEX] = verticeOrder; ArrayMesh legMesh = new ArrayMesh(); legMesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, surfaceArray, null, ARRAY_FORMAT_VERTEX + ARRAY_FORMAT_NORMAL + ARRAY_FORMAT_TANGENT + ARRAY_FORMAT_TANGENT); var legMaterial = (SpatialMaterial)GD.Load("res://skin.material"); GD.Print("Surface Count" + legMesh.GetSurfaceCount()); var node = (MeshInstance)FindNode("UmaMeshNode"); GD.Print(node.GetType()); GD.Print(node.Mesh.ToString()); legMesh.SurfaceSetMaterial(0, legMaterial); node.SetMesh(legMesh); GD.Print(node.Mesh.ToString()); /* * DynamicCharacterAvatar characterAvatar= new DynamicCharacterAvatar(); * * DynamicAssetLoader.Instance = new DynamicAssetLoader(); * * UMA.UMAContext.Instance = new UMA.UMAContext(); * characterAvatar.context = UMA.UMAContext.Instance; * UMA.UMAContext.Instance.raceLibrary = new DynamicRaceLibrary(); * * UMATextRecipe textRecipe = new UMATextRecipe(); * textRecipe.recipeString = @"{""version"":3,""packedSlotDataList"":[],""slotsV2"":[],""slotsV3"":[{""id"":""MaleEyes"",""scale"":100,""copyIdx"":-1,""overlays"":[{""id"":""EyeOverlay"",""colorIdx"":3,""rect"":[0,0,0,0]},{""id"":""Default Eye Adjust"",""colorIdx"":2,""rect"":[0,0,0,0]}]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":""MaleInnerMouth"",""scale"":100,""copyIdx"":-1,""overlays"":[{""id"":""InnerMouth"",""colorIdx"":4,""rect"":[0,0,0,0]}]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":""MaleTorso"",""scale"":100,""copyIdx"":-1,""overlays"":[{""id"":""M_BodOverlay 1"",""colorIdx"":0,""rect"":[0,0,0,0]}]},{""id"":""MaleFeet"",""scale"":100,""copyIdx"":16,""overlays"":[]},{""id"":""MaleHands"",""scale"":100,""copyIdx"":16,""overlays"":[]},{""id"":""MaleLegs"",""scale"":100,""copyIdx"":16,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":"""",""scale"":1,""copyIdx"":-1,""overlays"":[]},{""id"":""M_Highpoly Head"",""scale"":100,""copyIdx"":-1,""overlays"":[{""id"":""M_Face"",""colorIdx"":0,""rect"":[0,0,0,0]}]}],""colors"":[],""fColors"":[{""name"":""Skin"",""colors"":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]},{""name"":""Hair"",""colors"":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]},{""name"":""Eyes"",""colors"":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]},{""name"":""-"",""colors"":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]},{""name"":""-"",""colors"":[234,234,234,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]}],""sharedColorCount"":3,""race"":""HumanMale"",""packedDna"":[{""dnaType"":""DynamicUMADna"",""dnaTypeHash"":815443803,""packedDna"":""{\""bDnaAsset\"":{\""instanceID\"":12024},\""bDnaAssetName\"":\""HumanMaleDynamicDnaAsset\"",\""bDnaSettings\"":[{\""name\"":\""skinGreenness\"",\""value\"":128},{\""name\"":\""skinBlueness\"",\""value\"":128},{\""name\"":\""skinRedness\"",\""value\"":128},{\""name\"":\""height\"",\""value\"":128},{\""name\"":\""headSize\"",\""value\"":128},{\""name\"":\""headWidth\"",\""value\"":128},{\""name\"":\""neckThickness\"",\""value\"":128},{\""name\"":\""armLength\"",\""value\"":128},{\""name\"":\""forearmLength\"",\""value\"":128},{\""name\"":\""armWidth\"",\""value\"":128},{\""name\"":\""forearmWidth\"",\""value\"":128},{\""name\"":\""handsSize\"",\""value\"":128},{\""name\"":\""feetSize\"",\""value\"":128},{\""name\"":\""legSeparation\"",\""value\"":128},{\""name\"":\""upperMuscle\"",\""value\"":128},{\""name\"":\""lowerMuscle\"",\""value\"":128},{\""name\"":\""upperWeight\"",\""value\"":128},{\""name\"":\""lowerWeight\"",\""value\"":128},{\""name\"":\""legsSize\"",\""value\"":128},{\""name\"":\""belly\"",\""value\"":128},{\""name\"":\""waist\"",\""value\"":128},{\""name\"":\""gluteusSize\"",\""value\"":128},{\""name\"":\""earsSize\"",\""value\"":128},{\""name\"":\""earsPosition\"",\""value\"":128},{\""name\"":\""earsRotation\"",\""value\"":128},{\""name\"":\""noseSize\"",\""value\"":128},{\""name\"":\""noseCurve\"",\""value\"":128},{\""name\"":\""noseWidth\"",\""value\"":128},{\""name\"":\""noseInclination\"",\""value\"":128},{\""name\"":\""nosePosition\"",\""value\"":128},{\""name\"":\""nosePronounced\"",\""value\"":128},{\""name\"":\""noseFlatten\"",\""value\"":128},{\""name\"":\""chinSize\"",\""value\"":128},{\""name\"":\""chinPronounced\"",\""value\"":128},{\""name\"":\""chinPosition\"",\""value\"":128},{\""name\"":\""mandibleSize\"",\""value\"":128},{\""name\"":\""jawsSize\"",\""value\"":128},{\""name\"":\""jawsPosition\"",\""value\"":128},{\""name\"":\""cheekSize\"",\""value\"":128},{\""name\"":\""cheekPosition\"",\""value\"":128},{\""name\"":\""lowCheekPronounced\"",\""value\"":128},{\""name\"":\""lowCheekPosition\"",\""value\"":128},{\""name\"":\""foreheadSize\"",\""value\"":128},{\""name\"":\""foreheadPosition\"",\""value\"":128},{\""name\"":\""lipsSize\"",\""value\"":128},{\""name\"":\""mouthSize\"",\""value\"":128},{\""name\"":\""eyeRotation\"",\""value\"":128},{\""name\"":\""eyeSize\"",\""value\"":128},{\""name\"":\""breastSize\"",\""value\"":128},{\""name\"":\""eyeSpacing\"",\""value\"":128}]}""}],""wardrobeSet"":[],""packedRecipeType"":""Standard""}"; * GD.Print(textRecipe.recipeString); * characterAvatar.umaRecipe = textRecipe; * * UMAGenerator generator = new UMAGenerator(); * characterAvatar.umaGenerator = generator; * * characterAvatar.Start(); * GD.Print("It actually made it to the end of the Start routine!");*/ }
public static ArrayMesh GenerateMesh(float[,] noiseMap, float heightMultiplier, Curve heightCurve, int lod) { int width = noiseMap.GetLength(0); int height = noiseMap.GetLength(1); Vector3[] vertices = new Vector3[width * height]; Vector3[] normals = new Vector3[width * height]; Vector2[] uvs = new Vector2[width * height]; int[] indices = new int[(width - 1) * (height - 1) * 6]; float topLeftX = (width - 1) / -2f; float topLeftZ = (height - 1) / -2f; int simplificationFactor = lod == 0 ? 1 : lod * 2; int verticesPerLine = (width - 1) / simplificationFactor + 1; int vertices_idx = 0; for (int y = 0; y < height; y += simplificationFactor) { for (int x = 0; x < width; x += simplificationFactor) { vertices[vertices_idx] = new Vector3(topLeftX + x, heightCurve.Interpolate(noiseMap[x, y]) * heightMultiplier, topLeftZ + y); uvs[vertices_idx] = new Vector2(x / (float)width, y / (float)height); ++vertices_idx; } } int indices_idx = 0; vertices_idx = 0; for (int y = 0; y < height; y += simplificationFactor) { for (int x = 0; x < width; x += simplificationFactor) { if (x < width - 1 && y < height - 1) { AddTriangle(vertices, indices, normals, vertices_idx, vertices_idx + verticesPerLine + 1, vertices_idx + verticesPerLine, indices_idx); AddTriangle(vertices, indices, normals, vertices_idx, vertices_idx + 1, vertices_idx + verticesPerLine + 1, indices_idx + 3); indices_idx += 6; } ++vertices_idx; } } var meshArrays = new Godot.Collections.Array(); meshArrays.Resize((int)ArrayMesh.ArrayType.Max); meshArrays[(int)ArrayMesh.ArrayType.Vertex] = vertices; meshArrays[(int)ArrayMesh.ArrayType.TexUv] = uvs; meshArrays[(int)ArrayMesh.ArrayType.Index] = indices; meshArrays[(int)ArrayMesh.ArrayType.Normal] = normals; ArrayMesh mesh = new ArrayMesh(); mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, meshArrays); return(mesh); }
void CombinaQuads() { MeshInstance cube = new MeshInstance { Name = "Chunk" }; ArrayMesh cubeArray = new ArrayMesh(); Godot.Collections.Array kids = chunk.GetChildren(); Material[] materiais = new Material[kids.Count]; int contador = 0; foreach (MeshInstance meshI in kids) { Vector3[] vertLocal = (Vector3[])meshI.Mesh.SurfaceGetArrays(0)[(int)ArrayMesh.ArrayType.Vertex]; Vector3[] vertGlobal = new Vector3[vertLocal.Length]; //convertendo as coordenads de locais para globais dos quads for (int i = 0; i < vertLocal.Length; i++) { vertGlobal[i].x = vertLocal[i].x + meshI.Translation.x; vertGlobal[i].y = vertLocal[i].y + meshI.Translation.y; vertGlobal[i].z = vertLocal[i].z + meshI.Translation.z; } ArrayMesh combineArray = new ArrayMesh(); var arrays = new Godot.Collections.Array(); arrays.Resize((int)ArrayMesh.ArrayType.Max); arrays[(int)ArrayMesh.ArrayType.Vertex] = vertGlobal; arrays[(int)ArrayMesh.ArrayType.Normal] = meshI.Mesh.SurfaceGetArrays(0)[(int)ArrayMesh.ArrayType.Normal]; arrays[(int)ArrayMesh.ArrayType.TexUv] = meshI.Mesh.SurfaceGetArrays(0)[(int)ArrayMesh.ArrayType.TexUv]; arrays[(int)ArrayMesh.ArrayType.Index] = meshI.Mesh.SurfaceGetArrays(0)[(int)ArrayMesh.ArrayType.Index]; cubeArray.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays); materiais[contador] = meshI.GetSurfaceMaterial(0); meshI.QueueFree(); contador++; } cube.Mesh = cubeArray; for (int i = 0; i < materiais.Length; i++) { cube.SetSurfaceMaterial(i, materiais[i]); } chunk.AddChild(cube); }
public void CreateQuad(Vector3 vertex0, Vector3 vertex1, Vector3 vertex2, Vector3 vertex3) { // Generate quad mesh (2 triangles) Vector3[] vertices = { vertex0, //top-left vertex1, //top-right vertex2, //bottom-left vertex3 }; //bottom-right int[] index = new int[6] { 0, 1, 2, 3, 2, 1 }; // UVs Vector2[] uvs = { new Vector2(0f, 1f), //top-left new Vector2(1f, 1f), //top-right new Vector2(0f, 0f), //bottom-left new Vector2(1f, 0f) }; //bottom-right // Normals Vector3[] normals = new Vector3[4] { Vector3.Up, Vector3.Up, Vector3.Up, Vector3.Up }; Godot.Collections.Array arrays = new Godot.Collections.Array(); arrays.Resize(9); // see arrays[0] = vertices; arrays[1] = normals; arrays[4] = uvs; arrays[8] = index; // Create the Mesh. // Initialize the ArrayMesh. ArrayMesh arr_mesh = new ArrayMesh(); arr_mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays); MeshInstance quad = new MeshInstance(); quad.Mesh = arr_mesh; quad.MaterialOverride = cubeMaterial; // apply texture - rock, dirt, grass, etc. quad.MaterialOverride = cubeMaterial; // apply texture - rock, dirt, grass, etc. cube.AddChild(quad); // add quad to the cube node }
/// <summary> /// Creates the actual mesh object. Call InitializeMesh instead of this directly /// </summary> private void BuildMesh() { // This is actually a triangle list, but the index buffer is used to build // the indices (to emulate a triangle fan) var bufferSize = vertices2D.Count + 2; var indexSize = vertices2D.Count * 3; var arrays = new Godot.Collections.Array(); arrays.Resize((int)Mesh.ArrayType.Max); // Build vertex, index, and uv lists // Index mapping to build all triangles var indices = new int[indexSize]; int currentVertexIndex = 1; for (int i = 0; i < indexSize; i += 3) { indices[i] = 0; indices[i + 1] = currentVertexIndex + 1; indices[i + 2] = currentVertexIndex; ++currentVertexIndex; } // Write mesh data // var vertices = new Vector3[bufferSize]; var uvs = new Vector2[bufferSize]; int writeIndex = 0; writeIndex = InitializeCorrectMembrane(writeIndex, vertices, uvs); if (writeIndex != bufferSize) { throw new Exception("Membrane buffer write ended up at wrong index"); } // Godot might do this automatically // // Set the bounds to get frustum culling and LOD to work correctly. // // TODO: make this more accurate by calculating the actual extents // m_mesh->_setBounds(Ogre::Aabb(Float3::ZERO, Float3::UNIT_SCALE * 50) // /*, false*/); // m_mesh->_setBoundingSphereRadius(50); arrays[(int)Mesh.ArrayType.Vertex] = vertices; arrays[(int)Mesh.ArrayType.Index] = indices; arrays[(int)Mesh.ArrayType.TexUv] = uvs; // Create the mesh var generatedMesh = new ArrayMesh(); var surfaceIndex = generatedMesh.GetSurfaceCount(); generatedMesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays); // Apply the mesh to us Mesh = generatedMesh; SetSurfaceMaterial(surfaceIndex, MaterialToEdit); }
void CriaQuad(LadoDoCubo lado) { ArrayMesh quadArray; MeshInstance quad = new MeshInstance { Name = "Quad" }; //Criando os Arrays Vector3[] normalArray = new Vector3[4]; Vector2[] uvArray = new Vector2[4]; Vector3[] vertexArray = new Vector3[4]; int[] indexArray = new int[6]; //calculando UVs no atlas Vector2 uv00; Vector2 uv10; Vector2 uv01; Vector2 uv11; if (tBloco == TipoDeBloco.GRASS && lado == LadoDoCubo.TOP) { uv00 = blocosUVs[0, 0]; uv10 = blocosUVs[0, 1]; uv01 = blocosUVs[0, 2]; uv11 = blocosUVs[0, 3]; } else if (tBloco == TipoDeBloco.GRASS && lado == LadoDoCubo.BOTTOM) { uv00 = blocosUVs[(int)(TipoDeBloco.DIRT + 1), 0]; uv10 = blocosUVs[(int)(TipoDeBloco.DIRT + 1), 1]; uv01 = blocosUVs[(int)(TipoDeBloco.DIRT + 1), 2]; uv11 = blocosUVs[(int)(TipoDeBloco.DIRT + 1), 3]; } else { uv00 = blocosUVs[(int)(tBloco + 1), 0]; uv10 = blocosUVs[(int)(tBloco + 1), 1]; uv01 = blocosUVs[(int)(tBloco + 1), 2]; uv11 = blocosUVs[(int)(tBloco + 1), 3]; } //Todos os Vertices Possiveis Vector3 p0 = new Vector3(-0.5f, -0.5f, 0.5f); Vector3 p1 = new Vector3(0.5f, -0.5f, 0.5f); Vector3 p2 = new Vector3(0.5f, -0.5f, -0.5f); Vector3 p3 = new Vector3(-0.5f, -0.5f, -0.5f); Vector3 p4 = new Vector3(-0.5f, 0.5f, 0.5f); Vector3 p5 = new Vector3(0.5f, 0.5f, 0.5f); Vector3 p6 = new Vector3(0.5f, 0.5f, -0.5f); Vector3 p7 = new Vector3(-0.5f, 0.5f, -0.5f); switch (lado) { case LadoDoCubo.BOTTOM: vertexArray = new Vector3[] { p0, p1, p2, p3 }; normalArray = new Vector3[] { Vector3.Down, Vector3.Down, Vector3.Down, Vector3.Down }; break; case LadoDoCubo.TOP: vertexArray = new Vector3[] { p7, p6, p5, p4 }; normalArray = new Vector3[] { Vector3.Up, Vector3.Up, Vector3.Up, Vector3.Up }; break; case LadoDoCubo.LEFT: vertexArray = new Vector3[] { p7, p4, p0, p3 }; normalArray = new Vector3[] { Vector3.Left, Vector3.Left, Vector3.Left, Vector3.Left }; break; case LadoDoCubo.RIGHT: vertexArray = new Vector3[] { p5, p6, p2, p1 }; normalArray = new Vector3[] { Vector3.Right, Vector3.Right, Vector3.Right, Vector3.Right }; break; case LadoDoCubo.FRONT: vertexArray = new Vector3[] { p4, p5, p1, p0 }; normalArray = new Vector3[] { Vector3.Forward, Vector3.Forward, Vector3.Forward, Vector3.Forward }; break; case LadoDoCubo.BACK: vertexArray = new Vector3[] { p6, p7, p3, p2 }; normalArray = new Vector3[] { Vector3.Back, Vector3.Back, Vector3.Back, Vector3.Back }; break; } uvArray = new Vector2[] { uv11, uv01, uv00, uv10 }; indexArray = new int[] { 0, 1, 2, 0, 2, 3 }; quadArray = new ArrayMesh(); var arrays = new Godot.Collections.Array(); arrays.Resize((int)ArrayMesh.ArrayType.Max); arrays[(int)ArrayMesh.ArrayType.Vertex] = vertexArray; arrays[(int)ArrayMesh.ArrayType.Normal] = normalArray; arrays[(int)ArrayMesh.ArrayType.TexUv] = uvArray; arrays[(int)ArrayMesh.ArrayType.Index] = indexArray; quadArray.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays); quad.Mesh = quadArray; quad.SetSurfaceMaterial(0, material); quad.Translation = position; parent.AddChild(quad); }
private static void RenderDrawData(ImDrawDataPtr drawData, RID parent) { // allocate and clear out our CanvasItem pool as needed int neededNodes = 0; for (int i = 0; i < drawData.CmdListsCount; i++) { neededNodes += drawData.CmdListsRange[i].CmdBuffer.Size; } while (_children.Count < neededNodes) { RID newChild = VisualServer.CanvasItemCreate(); VisualServer.CanvasItemSetParent(newChild, parent); VisualServer.CanvasItemSetDrawIndex(newChild, _children.Count); _children.Add(newChild); _meshes.Add(new ArrayMesh()); } // trim unused nodes to reduce draw calls while (_children.Count > neededNodes) { int idx = _children.Count - 1; VisualServer.FreeRid(_children[idx]); _children.RemoveAt(idx); _meshes.RemoveAt(idx); } // render drawData.ScaleClipRects(ImGui.GetIO().DisplayFramebufferScale); int nodeN = 0; for (int n = 0; n < drawData.CmdListsCount; n++) { ImDrawListPtr cmdList = drawData.CmdListsRange[n]; int idxOffset = 0; int nVert = cmdList.VtxBuffer.Size; Godot.Vector2[] vertices = new Godot.Vector2[nVert]; Godot.Color[] colors = new Godot.Color[nVert]; Godot.Vector2[] uvs = new Godot.Vector2[nVert]; for (int i = 0; i < cmdList.VtxBuffer.Size; i++) { var v = cmdList.VtxBuffer[i]; vertices[i] = new Godot.Vector2(v.pos.X, v.pos.Y); // need to reverse the color bytes byte[] col = BitConverter.GetBytes(v.col); colors[i] = Godot.Color.Color8(col[0], col[1], col[2], col[3]); uvs[i] = new Godot.Vector2(v.uv.X, v.uv.Y); } for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++, nodeN++) { ImDrawCmdPtr drawCmd = cmdList.CmdBuffer[cmdi]; int[] indices = new int[drawCmd.ElemCount]; for (int i = idxOffset, j = 0; i < idxOffset + drawCmd.ElemCount; i++, j++) { indices[j] = cmdList.IdxBuffer[i]; } var arrays = new Godot.Collections.Array(); arrays.Resize((int)ArrayMesh.ArrayType.Max); arrays[(int)ArrayMesh.ArrayType.Vertex] = vertices; arrays[(int)ArrayMesh.ArrayType.Color] = colors; arrays[(int)ArrayMesh.ArrayType.TexUv] = uvs; arrays[(int)ArrayMesh.ArrayType.Index] = indices; var mesh = _meshes[nodeN]; while (mesh.GetSurfaceCount() > 0) { mesh.SurfaceRemove(0); } mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays); RID child = _children[nodeN]; Texture tex = GetTexture(drawCmd.TextureId); VisualServer.CanvasItemClear(child); VisualServer.CanvasItemSetClip(child, true); VisualServer.CanvasItemSetCustomRect(child, true, new Godot.Rect2( drawCmd.ClipRect.X, drawCmd.ClipRect.Y, drawCmd.ClipRect.Z - drawCmd.ClipRect.X, drawCmd.ClipRect.W - drawCmd.ClipRect.Y) ); VisualServer.CanvasItemAddMesh(child, mesh.GetRid(), null, null, tex.GetRid(), new RID(null)); // why doesn't this quite work? // VisualServer.CanvasItemAddTriangleArray(child, indices, vertices, colors, uvs, null, null, tex.GetRid(), -1, new RID(null)); idxOffset += (int)drawCmd.ElemCount; } } }
// Creates a cube using an array. public static ArrayMesh Render(SubChunk chunk) { var arrayMesh = new ArrayMesh(); // Array containing other arrays. // OpenGL array buffer. var arrays = new Godot.Collections.Array(); arrays.Resize((int)ArrayMesh.ArrayType.Max); // Reset data. Vertices = new Vector3[9999]; Normals = new Vector3[9999]; Colors = new Color[9999]; vertexIdx = 0; if (chunk.isEmpty()) { return(null); } // If sub-chunk is completely surrounded. dont render. if (!chunk.RenderBottom && !chunk.RenderTop && !chunk.RenderLeft && !chunk.RenderRight && !chunk.RenderFront && !chunk.RenderBack) { return(null); } // 16 x 16 x 16 = 4096 blocks. for (int x = 0; x < Chunk.CHUNK_SIZE; x++) { for (int z = 0; z < Chunk.CHUNK_SIZE; z++) { for (int y = 0; y < Chunk.CHUNK_SIZE; y++) { // No cube if not active. if (chunk.GetBlock(x, y, z) == -1) { continue; } // Create cube. CreateBlock(new Vector3(x, y, z), chunk); } } } System.Array.Resize(ref Vertices, vertexIdx); System.Array.Resize(ref Normals, vertexIdx); System.Array.Resize(ref Colors, vertexIdx); // Fill the array with the others arrays. arrays[0] = Vertices; arrays[1] = Normals; arrays[3] = Colors; if (Vertices.Length == 0) { return(null); } // Create surface from arrays. arrayMesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays); ApplyMaterial(arrayMesh); // Done. return(arrayMesh); }
private bool CreateMesh() { var verts = new List <Vector3>(); var normals = new List <Vector3>(); var indices = new List <int>(); Dictionary <Vector3, int> index_lookup = new Dictionary <Vector3, int>(); ArrayMesh marching_cube_mesh = new ArrayMesh(); float cell_dimensions = mesh_dimensions.x / (float)mesh_subdivisions;// 10.0F; int splitting = mesh_subdivisions / 2; int index_counter = 0; for (int i = -splitting; i < splitting; i++) { for (int j = -splitting; j < splitting; j++) { for (int k = -splitting; k < splitting; k++) { Vector3 cell_origin = mesh_offset + new Vector3(i * cell_dimensions, j * cell_dimensions, k * cell_dimensions); GridCell grid_cell = new GridCell(); grid_cell.p = new Vector3[8]; grid_cell.val = new float[8]; grid_cell.p[0] = cell_origin + 0.5F * new Vector3(-cell_dimensions, -cell_dimensions, -cell_dimensions); grid_cell.p[1] = cell_origin + 0.5F * new Vector3(+cell_dimensions, -cell_dimensions, -cell_dimensions); grid_cell.p[2] = cell_origin + 0.5F * new Vector3(+cell_dimensions, +cell_dimensions, -cell_dimensions); grid_cell.p[3] = cell_origin + 0.5F * new Vector3(-cell_dimensions, +cell_dimensions, -cell_dimensions); grid_cell.p[4] = cell_origin + 0.5F * new Vector3(-cell_dimensions, -cell_dimensions, +cell_dimensions); grid_cell.p[5] = cell_origin + 0.5F * new Vector3(+cell_dimensions, -cell_dimensions, +cell_dimensions); grid_cell.p[6] = cell_origin + 0.5F * new Vector3(+cell_dimensions, +cell_dimensions, +cell_dimensions); grid_cell.p[7] = cell_origin + 0.5F * new Vector3(-cell_dimensions, +cell_dimensions, +cell_dimensions); for (int l = 0; l < 8; l++) { grid_cell.val[l] = GetDensity(grid_cell.p[l]); } Triangle[] triangles = new Triangle[5]; int num_triangles = Polygonise(ref grid_cell, 0.5F, ref triangles); for (int l = 0; l < num_triangles; l++) { // for (int m = 0; m < 3; m++) // { // if (index_lookup.ContainsKey(triangles[l].p[m])) // { // indices.Add(index_lookup[triangles[l].p[m]]); // // GD.Print("collision: " + triangles[l].p[m] + "\t" + index_lookup[triangles[l].p[0]] + "\t" + index_counter); // } // else // { // index_lookup[triangles[l].p[m]] = index_counter; // indices.Add(index_counter); // verts.Add(triangles[l].p[m]); // ++index_counter; // } // } index_lookup[triangles[l].p[1]] = index_counter; indices.Add(index_counter); verts.Add(triangles[l].p[1]); ++index_counter; index_lookup[triangles[l].p[0]] = index_counter; indices.Add(index_counter); verts.Add(triangles[l].p[0]); ++index_counter; index_lookup[triangles[l].p[2]] = index_counter; indices.Add(index_counter); verts.Add(triangles[l].p[2]); ++index_counter; } } } } Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); foreach (var vertex in verts) { normals.Add(GetDensityNormal(vertex)); } stopwatch.Stop(); // GD.Print("normals took ", stopwatch.Elapsed); if (index_counter == 0) { return(false); } // GD.Print("index: " + index_counter); // GD.Print("verts: " + verts.Count); // Calculate vertex normals, face-by-face. // for (int i = 0; i < mdt.GetFaceCount(); i++) // { // // Get the index in the vertex array. // int a = mdt.GetFaceVertex(i, 0); // int b = mdt.GetFaceVertex(i, 1); // int c = mdt.GetFaceVertex(i, 2); // // Get vertex position using vertex index. // Vector3 ap = mdt.GetVertex(a); // Vector3 bp = mdt.GetVertex(b); // Vector3 cp = mdt.GetVertex(c); // // Calculate face normal. // Vector3 n = (bp - cp).Cross(ap - bp).Normalized(); // // Add face normal to current vertex normal. // // This will not result in perfect normals, but it will be close. // mdt.SetVertexNormal(a, n + mdt.GetVertexNormal(a)); // mdt.SetVertexNormal(b, n + mdt.GetVertexNormal(b)); // mdt.SetVertexNormal(c, n + mdt.GetVertexNormal(c)); // } // Run through vertices one last time to normalize normals and // set color to normal. // foreach (int i in Enumerable.Range(0,mdt.GetVertexCount())) // { // var v = mdt.GetVertexNormal(i).Normalized(); // mdt.SetVertexNormal(i, v); // mdt.SetVertexColor(i, new Color(v.x, v.y, v.z)); // } var arr = new Godot.Collections.Array(); arr.Resize((int)Mesh.ArrayType.Max); arr[(int)Mesh.ArrayType.Vertex] = verts.ToArray(); arr[(int)Mesh.ArrayType.Normal] = normals.ToArray(); arr[(int)Mesh.ArrayType.Index] = indices.ToArray(); marching_cube_mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arr); this.Mesh = marching_cube_mesh; return(true); }
private RawChunk Meshing(Chunk chunk, RawChunk rawChunk, ArrayPool <Position> pool) { Position[] values = MeshingUtils.NaiveGreedyMeshing(chunk, pool); Queue <Position>[][] stacks = new Queue <Position> [6][]; int[] size = new int[chunk.Materials - 1]; for (int side = 0; side < 6; side++) { stacks[side] = new Queue <Position> [chunk.Materials - 1]; for (int t = 0; t < chunk.Materials - 1; t++) { stacks[side][t] = new Queue <Position> (Constants.CHUNK_SIZE3D); } MeshingUtils.GreedyMeshing(values, side, stacks[side]); for (int t = 0; t < chunk.Materials - 1; t++) { size[t] += stacks[side][t].Count; } } pool.Return(values); for (int t = 0; t < chunk.Materials - 1; t++) { SpatialMaterial material = reg.SelectByID(t + 1).material; Vector3[] vertice = new Vector3[size[t]]; int[] indices = new int[size[t] + (size[t] / 2)]; Vector3[] normals = new Vector3[size[t]]; Vector2[] uvs = new Vector2[size[t]]; float textureWidth = 2048f / material.AlbedoTexture.GetWidth(); float textureHeight = 2048f / material.AlbedoTexture.GetHeight(); if (size[t] > 0) { int index = 0; int i = 0; for (int side = 0; side < 6; side++) { for (; i < size[t]; i += 4) { if (stacks[side][t].Count > 0) { indices[index] = i; indices[index + 1] = i + 1; indices[index + 2] = i + 2; indices[index + 3] = i + 2; indices[index + 4] = i + 3; indices[index + 5] = i; index += 6; for (int s = 0; s < 4; s++) { Position position = stacks[side][t].Dequeue(); Vector3 vector = new Vector3(); vector.x = position.x * Constants.VOXEL_SIZE; vector.y = position.y * Constants.VOXEL_SIZE; vector.z = position.z * Constants.VOXEL_SIZE; vertice[i + s] = vector; Vector2 uv = new Vector2(); Vector3 normal = new Vector3(); switch (side) { case 0: //Front normal.x = 0f; normal.y = 0f; normal.z = -1f; normals[i + s] = normal; uv.x = vector.x * textureWidth; uv.y = vector.y * textureHeight; uvs[i + s] = uv; break; case 1: //Back normal.x = 0f; normal.y = 0f; normal.z = 1f; normals[i + s] = normal; uv.x = vector.x * textureWidth; uv.y = vector.y * textureHeight; uvs[i + s] = uv; break; case 2: //Right normal.x = -1f; normal.y = 0f; normal.z = 0f; normals[i + s] = normal; uv.x = vector.z * textureWidth; uv.y = vector.y * textureHeight; uvs[i + s] = uv; break; case 3: //Left normal.x = 1f; normal.y = 0f; normal.z = 0f; normals[i + s] = normal; uv.x = vector.z * textureWidth; uv.y = vector.y * textureHeight; uvs[i + s] = uv; break; case 4: //Top normal.x = 0f; normal.y = 1f; normal.z = 0f; normals[i + s] = normal; uv.x = vector.x * textureWidth; uv.y = vector.z * textureHeight; uvs[i + s] = uv; break; case 5: //Bottom normal.x = 0f; normal.y = 0f; normal.z = 0f; normals[i + s] = normal; uv.x = vector.x * textureWidth; uv.y = vector.z * textureHeight; uvs[i + s] = uv; break; } } } else { break; } } } } Godot.Collections.Array godotArray = new Godot.Collections.Array(); if (vertice.Length > 0) { godotArray.Resize(9); godotArray[0] = vertice; godotArray[1] = normals; godotArray[4] = uvs; godotArray[8] = indices; } rawChunk.arrays[t] = godotArray; rawChunk.materials[t] = material; } return(rawChunk); }
public RawChunk FastGodotCube(Chunk chunk, RawChunk rawChunk) { Godot.Collections.Array godotArray = new Godot.Collections.Array(); godotArray.Resize(9); rawChunk.arrays = new Godot.Collections.Array[1]; rawChunk.materials = new SpatialMaterial[1]; rawChunk.colliderFaces = new Vector3[1][]; int objectID = chunk.Voxels[0].value; SpatialMaterial material = reg.SelectByID(objectID).material; float textureWidth = 2048f / material.AlbedoTexture.GetWidth(); float textureHeight = 2048f / material.AlbedoTexture.GetHeight(); Vector3[] vertice = new Vector3[24]; Vector3[] normals = new Vector3[24]; Vector2[] uvs = new Vector2[24]; //FRONT vertice[0] = new Vector3(0, 0, 0); vertice[1] = new Vector3(Constants.CHUNK_LENGHT, 0, 0); vertice[2] = new Vector3(Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT, 0); vertice[3] = new Vector3(0, Constants.CHUNK_LENGHT, 0); for (int i = 0; i < 4; i++) { normals[i] = new Vector3(0, 0, -1); uvs[i].x = vertice[i].x * textureWidth; uvs[i].y = vertice[i].y * textureHeight; } //BACK vertice[4] = new Vector3(Constants.CHUNK_LENGHT, 0, Constants.CHUNK_LENGHT); vertice[5] = new Vector3(0, 0, Constants.CHUNK_LENGHT); vertice[6] = new Vector3(0, Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT); vertice[7] = new Vector3(Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT); for (int i = 4; i < 8; i++) { normals[i] = new Vector3(0, 0, 1); uvs[i].x = vertice[i].x * textureWidth; uvs[i].y = vertice[i].y * textureHeight; } //LEFT vertice[8] = new Vector3(0, 0, Constants.CHUNK_LENGHT); vertice[9] = new Vector3(0, 0, 0); vertice[10] = new Vector3(0, Constants.CHUNK_LENGHT, 0); vertice[11] = new Vector3(0, Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT); for (int i = 8; i < 12; i++) { normals[i] = new Vector3(1, 0, 0); uvs[i].x = vertice[i].z * textureWidth; uvs[i].y = vertice[i].y * textureHeight; } //RIGHT vertice[12] = new Vector3(Constants.CHUNK_LENGHT, 0, 0); vertice[13] = new Vector3(Constants.CHUNK_LENGHT, 0, Constants.CHUNK_LENGHT); vertice[14] = new Vector3(Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT); vertice[15] = new Vector3(Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT, 0); for (int i = 12; i < 16; i++) { normals[i] = new Vector3(-1, 0, 0); uvs[i].x = vertice[i].z * textureWidth; uvs[i].y = vertice[i].y * textureHeight; } // TOP vertice[16] = new Vector3(0, Constants.CHUNK_LENGHT, 0); vertice[17] = new Vector3(Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT, 0); vertice[18] = new Vector3(Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT); vertice[19] = new Vector3(0, Constants.CHUNK_LENGHT, Constants.CHUNK_LENGHT); for (int i = 16; i < 20; i++) { normals[i] = new Vector3(0, 1, 0); uvs[i].x = vertice[i].x * textureWidth; uvs[i].y = vertice[i].z * textureHeight; } //BOTTOM vertice[20] = new Vector3(0, 0, Constants.CHUNK_LENGHT); vertice[21] = new Vector3(Constants.CHUNK_LENGHT, 0, Constants.CHUNK_LENGHT); vertice[22] = new Vector3(Constants.CHUNK_LENGHT, 0, 0); vertice[23] = new Vector3(0, 0, 0); for (int i = 20; i < 24; i++) { normals[i] = new Vector3(0, -1, 0); uvs[i].x = vertice[i].x * textureWidth; uvs[i].y = vertice[i].z * textureHeight; } godotArray[0] = vertice; godotArray[1] = normals; godotArray[4] = uvs; int index = 0; int[] indice = new int[36]; for (int i = 0; i < 36; i += 6) { indice[i] = index; indice[i + 1] = index + 1; indice[i + 2] = index + 2; indice[i + 3] = index + 2; indice[i + 4] = index + 3; indice[i + 5] = index; index += 4; } godotArray[8] = indice; rawChunk.arrays[0] = godotArray; rawChunk.materials[0] = material; rawChunk.colliderFaces[0] = vertice; return(rawChunk); }
static void BuildSection(File file, int xPos, int yPos, float heightScale, Vector2 textureScale, ref ArrayMesh mesh) { var vertices = new Vector3[VERTEX_CHUNK * VERTEX_CHUNK]; var normals = new Vector3[VERTEX_CHUNK * VERTEX_CHUNK]; var uv = new Vector2[VERTEX_CHUNK * VERTEX_CHUNK]; var cutout = new bool[VERTEX_CHUNK * VERTEX_CHUNK]; var colour = new Color[VERTEX_CHUNK * VERTEX_CHUNK]; //I'm using the colour info for texture mix info. for (int sz = 0; sz < VERTEX_CHUNK; sz++) { for (int sx = 0; sx < VERTEX_CHUNK; sx++) { var index = sz * VERTEX_CHUNK + sx; vertices[index] = new Vector3( xPos + sx - CHUNK_WIDTH * NUM_CHUNKS / 2, file.Get16() * heightScale, yPos + sz - CHUNK_WIDTH * NUM_CHUNKS / 2); normals[index] = new Vector3((sbyte)file.Get8(), (sbyte)file.Get8(), (sbyte)file.Get8()).Normalized(); uv[index] = new Vector2( (float)(xPos + sx) / CHUNK_WIDTH, (float)(yPos + sz) / CHUNK_WIDTH) * textureScale; cutout[index] = (file.Get8() & 0b10000000) == 0b10000000; var mixRatios = file.Get16(); colour[index] = new Color( MixRatioHelper(mixRatios, 0x000f), MixRatioHelper(mixRatios, 0x00f0), MixRatioHelper(mixRatios, 0x0f00), MixRatioHelper(mixRatios, 0xf000) ); } } var indices = new int[CHUNK_WIDTH * CHUNK_WIDTH * 6]; for (var z = 0; z < CHUNK_WIDTH; z++) { for (var x = 0; x < CHUNK_WIDTH; x++) { var index = (z * CHUNK_WIDTH + x) * 6; var base_vertex = (z * VERTEX_CHUNK + x); if (!cutout[base_vertex + 1 + VERTEX_CHUNK]) { if (z % 2 == 0) { indices[index] = base_vertex; indices[index + 1] = base_vertex + 1; indices[index + 2] = base_vertex + VERTEX_CHUNK; indices[index + 3] = base_vertex + VERTEX_CHUNK; indices[index + 4] = base_vertex + 1; indices[index + 5] = base_vertex + 1 + VERTEX_CHUNK; } else { indices[index] = base_vertex; indices[index + 1] = base_vertex + 1; indices[index + 2] = base_vertex + 1 + VERTEX_CHUNK; indices[index + 3] = base_vertex; indices[index + 4] = base_vertex + 1 + VERTEX_CHUNK; indices[index + 5] = base_vertex + VERTEX_CHUNK; } } } } var array = new Godot.Collections.Array(); array.Resize((int)ArrayMesh.ArrayType.Max); array[(int)ArrayMesh.ArrayType.Vertex] = vertices; array[(int)ArrayMesh.ArrayType.Normal] = normals; array[(int)ArrayMesh.ArrayType.Color] = colour; array[(int)ArrayMesh.ArrayType.TexUv] = uv; array[(int)ArrayMesh.ArrayType.Index] = indices; mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, array); }