/// <summary> /// Renders a chunk from its data. If the chunk is rendered /// for the first time. It adds it to the scene. If not, it /// just replaces its mesh with the new one. /// </summary> /// <param name="firstRender"></param> public void Render(bool firstRender) { if (firstRender) { for (int i = 0; i < SUBCHUNK_COUNT; i++) { // Create each sub chunks and place them var subChunk = m_SubChunks[i]; subChunk.Name = i.ToString(); subChunk.Translate(new Vector3(0, i * CHUNK_SIZE, 0)); // Creates the mesh. subChunk.Mesh = Renderer.Render(subChunk); // If the subchunk is not empty, create the collision. if (subChunk.Mesh != null) { subChunk.CreateTrimeshCollision(); } // Place each voxel sprite in the chunk. foreach (VoxelSprite voxelSprite in subChunk.GetDecorations()) { if (voxelSprite is null) { continue; } var newMesh = new MeshInstance(); newMesh.Scale = new Vector3(1f / 8f, 1f / 8f, 1f / 8f); newMesh.AddToGroup("decoration"); newMesh.MaterialOverride = Renderer.GetWavingShader; newMesh.SetDeferred("translation", voxelSprite.Position); newMesh.Mesh = voxelSprite.Mesh; subChunk.CallDeferred("add_child", newMesh); } this.CallDeferred("add_child", subChunk); // Creating a visibility notifier per chunk. // This is useful for the frustrum culling. // Connect the signals to the methods on the subchunk. //visibilityNotifier.Connect("camera_entered", subChunk, "CameraEntered", null, 1); //visibilityNotifier.Connect("camera_exited", subChunk, "CameraExited", null, 1); } } else { for (int i = 0; i < SUBCHUNK_COUNT; i++) { var subChunk = m_SubChunks[i]; subChunk.Mesh = Renderer.Render(subChunk); // removes old collisions foreach (Node node in subChunk.GetChildren()) { node.CallDeferred("queue_free"); } // Update collisions too if (subChunk.Mesh != null) { subChunk.CreateTrimeshCollision(); } } needUpdate = false; } }
private void Render(Chunk pChunk) { // If chunk is already loaded. if (LoadedChunks.ContainsKey(pChunk.Offset)) { return; } SurfaceTool = new SurfaceTool(); SurfaceTool.Begin(Mesh.PrimitiveType.Triangles); // Adding material Material mat = VoxMaterial.Duplicate() as Material; SurfaceTool.SetMaterial(mat); // Creating the mesh. Voxel by voxel for (int y = 0; y < Chunk.ChunkSize.y; y++) { for (int x = 0; x < Chunk.ChunkSize.x; x++) { for (int z = 0; z < Chunk.ChunkSize.z; z++) { if (!pChunk.Voxels[x, y, z].Active) { continue; } CreateVoxel(SurfaceTool, x, y, z, pChunk); } } } // Reduces vertex size SurfaceTool.Index(); // Creating instance MeshInstance chunk = new MeshInstance { Mesh = SurfaceTool.Commit(), Name = pChunk.Offset.ToString(), Translation = new Vector3(pChunk.Offset.x * Chunk.ChunkSize.x, 0, pChunk.Offset.y * Chunk.ChunkSize.z) }; // Creating collisions //chunk.CreateTrimeshCollision(); // Tagging the chunk chunk.AddToGroup("Chunk"); // Chunk is now loaded. Adding to the scene. LoadedChunks.TryAdd(pChunk.Offset, pChunk); this.CallDeferred("add_child", chunk); if (pChunk.VoxelSprite.Count < 64) { // Adding voxelsprite foreach (VoxelSprite voxSprite in pChunk.VoxelSprite) { var meshInstance = new MeshInstance(); meshInstance.SetDeferred("mesh", voxSprite.Mesh); // Adding next frame to avoid locking problems. chunk.CallDeferred("add_child", meshInstance); // Moving next frame because not in tree yet meshInstance.SetDeferred("translation", voxSprite.Position); // Applying wind shader. meshInstance.SetDeferred("material_override", GrassMaterial); // Scaling down because its a decoration meshInstance.Scale = meshInstance.Scale /= 8; } } // Fade in animation. //var t2 = new Tween(); //chunk.AddChild(t2); //t2.InterpolateProperty(mat, "albedo_color", new Color(1, 1, 1, 0f), new Color(1, 1, 1, 1f), 1f, Tween.TransitionType.Linear, Tween.EaseType.InOut); //t2.Start(); SurfaceTool.Clear(); }