private static void AddFaceToVbo(Block block, Vector3i blockPos, BlockFace blockFace, VertexArrayObject <Vector3> vao) { int indicesOffset = vao.GetBuffer(0).Length; for (int i = 0; i < 4; i++) { vao.Add(0, facePositions[(int)blockFace * 4 + i] + blockPos.AsVector3()); } int textureIndex = block.GetTextureId(blockFace); for (int i = 0; i < 4; i++) { vao.Add(1, new Vector3(faceTexCoords[i]) { Z = textureIndex }); } uint[] newIndices = new uint[faceIndices.Length]; for (int i = 0; i < newIndices.Length; i++) { newIndices[i] = (uint)(faceIndices[i] + indicesOffset); } vao.AddIndices(newIndices); }
void addRandomTrees(VertexArrayObject <MeshData, InstancedData> vao, int count, string objPath, string diffTexPath, float _scale = 1f) { VAOItem <InstancedData> vaoi = (VAOItem <InstancedData>)vao.Add(OBJMeshLoader.Load(objPath)); vaoi.DiffuseTexture = Tetra.Texture.Load(diffTexPath); vaoi.InstancedDatas = new Tetra.InstancedData[count]; for (int i = 0; i < count; i++) { Vector2 pos = new Vector2((float)rnd.NextDouble() * terrain.GridSize, (float)rnd.NextDouble() * terrain.GridSize); float scale = (float)(rnd.NextDouble() * 0.002f + 0.004f) * _scale; vaoi.InstancedDatas[i].modelMats = Matrix4.CreateRotationX(MathHelper.PiOver2) * Matrix4.CreateScale(scale) * Matrix4.CreateTranslation(pos.X, pos.Y, 0f); } vaoi.UpdateInstancesData(); }
void addRandomTrees(VertexArrayObject<MeshData, InstancedData> vao, int count, string objPath, string diffTexPath, float _scale=1f) { VAOItem<InstancedData> vaoi = (VAOItem<InstancedData>)vao.Add (OBJMeshLoader.Load (objPath)); vaoi.DiffuseTexture = Tetra.Texture.Load(diffTexPath); vaoi.InstancedDatas = new Tetra.InstancedData[count]; for (int i = 0; i < count; i++) { Vector2 pos = new Vector2 ((float)rnd.NextDouble() * terrain.GridSize, (float)rnd.NextDouble() * terrain.GridSize); float scale = (float)(rnd.NextDouble () * 0.002f + 0.004f)*_scale; vaoi.InstancedDatas[i].modelMats =Matrix4.CreateRotationX (MathHelper.PiOver2) * Matrix4.CreateScale (scale)* Matrix4.CreateTranslation(pos.X, pos.Y, 0f); } vaoi.UpdateInstancesData (); }
void initScene(){ heolBones[5] = 10f; pawnBones [2] = 0.299f; pawnBones [5] = 0.90812f; int nbHeol = 5; terrain = new Terrain (ClientRectangle.Size); terrain.gridShader.ShadowMap = shadowMap; vaoDeformables = new VertexArrayObject<WeightedMeshData, WeightedInstancedData> (); vaoObjects = new VertexArrayObject<MeshData, InstancedData> (); car = (VAOItem<InstancedData>)vaoObjects.Add (OBJMeshLoader.Load ("Meshes/car.obj")); car.DiffuseTexture = Tetra.Texture.Load ("Meshes/0000.png"); car.InstancedDatas = new InstancedData[nbHeol]; for (int i = 0; i < nbHeol; i++) { Vector2 pos = new Vector2 ((float)rnd.Next(0,terrain.GridSize), (float)rnd.Next(0,terrain.GridSize)); car.InstancedDatas[i].modelMats = Matrix4.CreateScale(0.2f) * Matrix4.CreateTranslation (pos.X-(pos.X % 4f) + 0.5f, pos.Y-(pos.Y % 4f) + 0.5f, 0.1f); } car.UpdateInstancesData(); nbHeol = 50; // trees = (VAOItem<WeightedInstancedData>)vaoDeformables.Add (OBJMeshLoader.Load ("Meshes/trees/treesTrunk.obj")); // treesLeave = (VAOItem<WeightedInstancedData>)vaoDeformables.Add (OBJMeshLoader.Load ("Meshes/trees/treesLeaves.obj")); // trees.DiffuseTexture = Tetra.Texture.Load ("Meshes/trees/treeTrunk.jpg"); // treesLeave.DiffuseTexture = Tetra.Texture.Load ("Meshes/trees/treeLeaves.png"); // trees.InstancedDatas = new Tetra.WeightedInstancedData[nbHeol]; // treesLeave.InstancedDatas = new Tetra.WeightedInstancedData[nbHeol]; // for (int i = 0; i < nbHeol; i++) { // Vector2 pos = new Vector2 ((float)rnd.Next(0,terrain.GridSize), (float)rnd.Next(0,terrain.GridSize)); // float angle = (float)(rnd.NextDouble() * Math.PI); // trees.InstancedDatas[i].modelMats = Matrix4.CreateRotationZ(angle) * Matrix4.CreateScale(4f) * Matrix4.CreateTranslation (pos.X-(pos.X % 4f) + 0.5f, pos.Y-(pos.Y % 4f) + 0.5f, 0f); // treesLeave.InstancedDatas [i].modelMats = trees.InstancedDatas [i].modelMats; // } // trees.UpdateInstancesData(); // // treesLeave.UpdateInstancesData(); //HEOLIENNES nbHeol = 5; // heoliennes = (VAOItem<WeightedInstancedData>)vaoDeformables.Add (OBJMeshLoader.Load ("Meshes/heolienne.obj")); // heoliennes.DiffuseTexture = Tetra.Texture.Load ("Meshes/heolienne.png"); // heoliennes.InstancedDatas = new Tetra.WeightedInstancedData[nbHeol]; // for (int i = 0; i < nbHeol; i++) { // Vector2 pos = new Vector2 ((float)rnd.Next(0,terrain.GridSize), (float)rnd.Next(0,terrain.GridSize)); // heoliennes.InstancedDatas[i].modelMats = Matrix4.CreateScale(0.1f) * Matrix4.CreateTranslation (pos.X-(pos.X % 4f) + 0.5f, pos.Y-(pos.Y % 4f) + 0.5f, 0f); // heoliennes.InstancedDatas [i].quat0 = Quaternion.Identity; // heoliennes.InstancedDatas [i].quat1 = Quaternion.Identity; // heoliennes.InstancedDatas [i].quat2 = Quaternion.Identity; // heoliennes.InstancedDatas [i].quat3 = Quaternion.Identity; //// heoliennes.InstancedDatas [i].bpos0 = new Vector4 (0f, 0f, 0f, 0f); //// heoliennes.InstancedDatas [i].bpos1 = new Vector4 (0f, 0f, 0f, 0f); //// heoliennes.InstancedDatas [i].bpos2 = new Vector4 (0f, 0f, 0f, 0f); //// heoliennes.InstancedDatas [i].bpos3 = new Vector4 (0f, 0f, 0f, 0f); // } // heoliennes.UpdateInstancesData(); nbHeol = 5; heollow = (VAOItem<WeightedInstancedData>)vaoDeformables.Add (OBJMeshLoader.Load ("Meshes/heolienne_lod0.obj")); heollow.DiffuseTexture = Tetra.Texture.Load ("Meshes/heollow.png"); heollow.InstancedDatas = new Tetra.WeightedInstancedData[nbHeol]; for (int i = 0; i < nbHeol; i++) { Vector2 pos = new Vector2 ((float)rnd.Next(0,terrain.GridSize), (float)rnd.Next(0,terrain.GridSize)); heollow.InstancedDatas[i].modelMats = Matrix4.CreateTranslation (pos.X-(pos.X % 4f) + 0.5f, pos.Y-(pos.Y % 4f) + 0.5f, 0f); heollow.InstancedDatas [i].quat0 = Quaternion.Identity; heollow.InstancedDatas [i].quat1 = Quaternion.Identity; heollow.InstancedDatas [i].quat2 = Quaternion.Identity; heollow.InstancedDatas [i].quat3 = Quaternion.Identity; // heollow.InstancedDatas [i].bpos0 = new Vector4 (0f, 0f, 0f, 0f); // heollow.InstancedDatas [i].bpos1 = new Vector4 (0f, 0f, 0f, 0f); // heollow.InstancedDatas [i].bpos2 = new Vector4 (0f, 0f, 0f, 0f); // heollow.InstancedDatas [i].bpos3 = new Vector4 (0f, 0f, 0f, 0f); } heollow.UpdateInstancesData(); // pawn = (VAOItem<WeightedInstancedData>)vaoDeformables.Add (OBJMeshLoader.Load ("Meshes/pawn.obj")); // pawn.DiffuseTexture = Tetra.Texture.Load ("Meshes/pawn.png"); // pawn.InstancedDatas = new Tetra.WeightedInstancedData[nbHeol]; // for (int i = 0; i < nbHeol; i++) { // Vector2 pos = new Vector2 ((float)rnd.Next(0,terrain.GridSize), (float)rnd.Next(0,terrain.GridSize)); // pawn.InstancedDatas[i].modelMats = Matrix4.CreateTranslation (pos.X-(pos.X % 4f) + 0.5f, pos.Y-(pos.Y % 4f) + 0.5f, 0f); // pawn.InstancedDatas [i].quat0 = Quaternion.Identity; // pawn.InstancedDatas [i].quat1 = Quaternion.Identity; // pawn.InstancedDatas [i].quat2 = Quaternion.Identity; // pawn.InstancedDatas [i].quat3 = Quaternion.Identity; // } // pawn.UpdateInstancesData(); //landItemsVao.ComputeTangents(); vaoDeformables.BuildBuffers (); vaoObjects.BuildBuffers (); // const float treezone = 32; // const int treeCount = 50; // transparentItemsVao = new VertexArrayObject<MeshData, VAOInstancedData> (); // // //====TREE1==== // // vaoi = transparentItemsVao.Add (Tetra.OBJMeshLoader.Load ("#Ottd3D.images.trees.obj__pinet1.obj")); // // vaoi.DiffuseTexture = Tetra.Texture.Load("#Ottd3D.images.trees.pinet1.png"); // // vaoi.modelMats = new Matrix4[treeCount]; // // for (int i = 0; i < treeCount; i++) { // // Vector2 pos = new Vector2 ((float)rnd.NextDouble() * treezone, (float)rnd.NextDouble() * treezone); // // float scale = (float)rnd.NextDouble () * 0.002f + 0.004f; // // vaoi.modelMats[i] =treeRot * Matrix4.CreateScale (scale)* Matrix4.CreateTranslation(pos.X, pos.Y, 0f); // // } // // vaoi.UpdateInstancesData (); // // //====TREE2==== // // addRandomTrees (transparentItemsVao, treeCount, // // "#Ottd3D.images.trees.simple.obj", // // "#Ottd3D.images.trees.birch_tree_small_20131230_2041956203.png",400f); // // // addRandomTrees (transparentItemsVao, treeCount, // // "#Ottd3D.images.trees.obj__pinet1.obj", // // "#Ottd3D.images.trees.pinet1.png",5f); // addRandomTrees (transparentItemsVao, treeCount, // "images/trees/obj__pinet2.obj", // "images/trees/pinet2.png",3f); // // addRandomTrees (transparentItemsVao, treeCount, // // "#Ottd3D.images.trees.obj__tree1.obj", // // "#Ottd3D.images.trees.tree1.png",5f); // // addRandomTrees (transparentItemsVao, treeCount, // // "#Ottd3D.images.trees.obj__tree2.obj", // // "#Ottd3D.images.trees.tree2.png", 5f); // // addRandomTrees (transparentItemsVao, treeCount, // // "#Ottd3D.images.trees.obj__tree3.obj", // // "#Ottd3D.images.trees.tree3.png", 5f); // // //transparentItemsVao.ComputeTangents (); // transparentItemsVao.BuildBuffers (); }
public static void AddFaceToVao(WorldServer world, Vector3i blockPos, int x, int y, int z, Block block, BlockFace face, BlockModel.FaceData data, VertexArrayObject vao, Matrix4 transform) { var faceId = (int)face - 1; var indicesOffset = vao.VertexCount; //var transform = Matrix4.CreateScale()//Matrix4.Identity;//block.GetTransform(world, blockPos, face); var texture = data.LoadedTexture; //block.GetTexture(world, blockPos, face); //var overlayTexture = block.GetOverlayTexture(world, blockPos, face); var texCoords = data.GetTexCoords(); //block.GetTexCoords(world, blockPos, face) ?? FaceTexCoords; //var overlayTexCoords = block.GetOverlayTexCoords(world, blockPos, face) ?? FaceTexCoords; var color = data.TintIndex == -1 ? new Vector4(1) : block.GetTintColor(world, blockPos, data.TintIndex).ToVector4(); var normal = face.GetNormal(); if (texCoords.Length != 4) { throw new Exception($"\"{block}\" invalid texture coords array length!"); } var vPositions = new Vector3[4]; var vTexCoords = new Vector4[4]; var vOverlayTexCoords = new Vector4[4]; //TODO: Remove var vBrightness = new Vector3[4]; for (var j = 0; j < 4; j++) { var vertexPosition = FacePositions[faceId * 4 + j]; var position = (new Vector4(vertexPosition, 1) * transform).Xyz + new Vector3(x, y, z); //tex coords are -1 if texture is null var texCoord = texture == null ? new Vector4(-1) : new Vector4(texCoords[j]) { //texCoord z = texId, w = textureArrayId Z = texture.TextureId, W = texture.ArrayId }; //per vertex light value interpolation (smooth lighting + free ambient occlusion) var brightness = CalculateBrightness(world, block, blockPos, face, vertexPosition); //TODO: transform normals vPositions[j] = position; vTexCoords[j] = texCoord; vOverlayTexCoords[j] = new Vector4(-1); vBrightness[j] = brightness; } //Flip faces to fix ambient occlusion anisotrophy //https://0fps.net/2013/07/03/ambient-occlusion-for-minecraft-like-worlds/ for (var j = 0; j < 4; j++) { vao.Add(vPositions[j], vTexCoords[j], new Vector4(normal), color.Xyz, vBrightness[j]); } var newIndices = new uint[FaceIndices.Length]; if ((vBrightness[0] + vBrightness[3]).LengthSquared > (vBrightness[1] + vBrightness[2]).LengthSquared) { for (var j = 0; j < newIndices.Length; j++) { newIndices[j] = (uint)(FlippedFaceIndices[j] + indicesOffset); } } else { for (var j = 0; j < newIndices.Length; j++) { newIndices[j] = (uint)(FaceIndices[j] + indicesOffset); } } //Calculate face middle for transparency sorting var faceMiddle = Vector3.Zero; if (vao is SortedVertexArrayObject) { faceMiddle = vPositions.Aggregate(faceMiddle, (current, pos) => current + pos); faceMiddle = faceMiddle / vPositions.Length + blockPos.ToVector3() - new Vector3(x, y, z); } vao.AddFace(newIndices, faceMiddle); }
void initScene() { heolBones[5] = 10f; pawnBones [2] = 0.299f; pawnBones [5] = 0.90812f; int nbHeol = 5; terrain = new Terrain(ClientRectangle.Size); terrain.gridShader.ShadowMap = shadowMap; vaoDeformables = new VertexArrayObject <WeightedMeshData, WeightedInstancedData> (); vaoObjects = new VertexArrayObject <MeshData, InstancedData> (); car = (VAOItem <InstancedData>)vaoObjects.Add(OBJMeshLoader.Load("Meshes/car.obj")); car.DiffuseTexture = Tetra.Texture.Load("Meshes/0000.png"); car.InstancedDatas = new InstancedData[nbHeol]; for (int i = 0; i < nbHeol; i++) { Vector2 pos = new Vector2((float)rnd.Next(0, terrain.GridSize), (float)rnd.Next(0, terrain.GridSize)); car.InstancedDatas[i].modelMats = Matrix4.CreateScale(0.2f) * Matrix4.CreateTranslation(pos.X - (pos.X % 4f) + 0.5f, pos.Y - (pos.Y % 4f) + 0.5f, 0.1f); } car.UpdateInstancesData(); nbHeol = 50; // trees = (VAOItem<WeightedInstancedData>)vaoDeformables.Add (OBJMeshLoader.Load ("Meshes/trees/treesTrunk.obj")); // treesLeave = (VAOItem<WeightedInstancedData>)vaoDeformables.Add (OBJMeshLoader.Load ("Meshes/trees/treesLeaves.obj")); // trees.DiffuseTexture = Tetra.Texture.Load ("Meshes/trees/treeTrunk.jpg"); // treesLeave.DiffuseTexture = Tetra.Texture.Load ("Meshes/trees/treeLeaves.png"); // trees.InstancedDatas = new Tetra.WeightedInstancedData[nbHeol]; // treesLeave.InstancedDatas = new Tetra.WeightedInstancedData[nbHeol]; // for (int i = 0; i < nbHeol; i++) { // Vector2 pos = new Vector2 ((float)rnd.Next(0,terrain.GridSize), (float)rnd.Next(0,terrain.GridSize)); // float angle = (float)(rnd.NextDouble() * Math.PI); // trees.InstancedDatas[i].modelMats = Matrix4.CreateRotationZ(angle) * Matrix4.CreateScale(4f) * Matrix4.CreateTranslation (pos.X-(pos.X % 4f) + 0.5f, pos.Y-(pos.Y % 4f) + 0.5f, 0f); // treesLeave.InstancedDatas [i].modelMats = trees.InstancedDatas [i].modelMats; // } // trees.UpdateInstancesData(); // // treesLeave.UpdateInstancesData(); //HEOLIENNES nbHeol = 5; // heoliennes = (VAOItem<WeightedInstancedData>)vaoDeformables.Add (OBJMeshLoader.Load ("Meshes/heolienne.obj")); // heoliennes.DiffuseTexture = Tetra.Texture.Load ("Meshes/heolienne.png"); // heoliennes.InstancedDatas = new Tetra.WeightedInstancedData[nbHeol]; // for (int i = 0; i < nbHeol; i++) { // Vector2 pos = new Vector2 ((float)rnd.Next(0,terrain.GridSize), (float)rnd.Next(0,terrain.GridSize)); // heoliennes.InstancedDatas[i].modelMats = Matrix4.CreateScale(0.1f) * Matrix4.CreateTranslation (pos.X-(pos.X % 4f) + 0.5f, pos.Y-(pos.Y % 4f) + 0.5f, 0f); // heoliennes.InstancedDatas [i].quat0 = Quaternion.Identity; // heoliennes.InstancedDatas [i].quat1 = Quaternion.Identity; // heoliennes.InstancedDatas [i].quat2 = Quaternion.Identity; // heoliennes.InstancedDatas [i].quat3 = Quaternion.Identity; //// heoliennes.InstancedDatas [i].bpos0 = new Vector4 (0f, 0f, 0f, 0f); //// heoliennes.InstancedDatas [i].bpos1 = new Vector4 (0f, 0f, 0f, 0f); //// heoliennes.InstancedDatas [i].bpos2 = new Vector4 (0f, 0f, 0f, 0f); //// heoliennes.InstancedDatas [i].bpos3 = new Vector4 (0f, 0f, 0f, 0f); // } // heoliennes.UpdateInstancesData(); nbHeol = 5; heollow = (VAOItem <WeightedInstancedData>)vaoDeformables.Add(OBJMeshLoader.Load("Meshes/heolienne_lod0.obj")); heollow.DiffuseTexture = Tetra.Texture.Load("Meshes/heollow.png"); heollow.InstancedDatas = new Tetra.WeightedInstancedData[nbHeol]; for (int i = 0; i < nbHeol; i++) { Vector2 pos = new Vector2((float)rnd.Next(0, terrain.GridSize), (float)rnd.Next(0, terrain.GridSize)); heollow.InstancedDatas[i].modelMats = Matrix4.CreateTranslation(pos.X - (pos.X % 4f) + 0.5f, pos.Y - (pos.Y % 4f) + 0.5f, 0f); heollow.InstancedDatas [i].quat0 = Quaternion.Identity; heollow.InstancedDatas [i].quat1 = Quaternion.Identity; heollow.InstancedDatas [i].quat2 = Quaternion.Identity; heollow.InstancedDatas [i].quat3 = Quaternion.Identity; // heollow.InstancedDatas [i].bpos0 = new Vector4 (0f, 0f, 0f, 0f); // heollow.InstancedDatas [i].bpos1 = new Vector4 (0f, 0f, 0f, 0f); // heollow.InstancedDatas [i].bpos2 = new Vector4 (0f, 0f, 0f, 0f); // heollow.InstancedDatas [i].bpos3 = new Vector4 (0f, 0f, 0f, 0f); } heollow.UpdateInstancesData(); // pawn = (VAOItem<WeightedInstancedData>)vaoDeformables.Add (OBJMeshLoader.Load ("Meshes/pawn.obj")); // pawn.DiffuseTexture = Tetra.Texture.Load ("Meshes/pawn.png"); // pawn.InstancedDatas = new Tetra.WeightedInstancedData[nbHeol]; // for (int i = 0; i < nbHeol; i++) { // Vector2 pos = new Vector2 ((float)rnd.Next(0,terrain.GridSize), (float)rnd.Next(0,terrain.GridSize)); // pawn.InstancedDatas[i].modelMats = Matrix4.CreateTranslation (pos.X-(pos.X % 4f) + 0.5f, pos.Y-(pos.Y % 4f) + 0.5f, 0f); // pawn.InstancedDatas [i].quat0 = Quaternion.Identity; // pawn.InstancedDatas [i].quat1 = Quaternion.Identity; // pawn.InstancedDatas [i].quat2 = Quaternion.Identity; // pawn.InstancedDatas [i].quat3 = Quaternion.Identity; // } // pawn.UpdateInstancesData(); //landItemsVao.ComputeTangents(); vaoDeformables.BuildBuffers(); vaoObjects.BuildBuffers(); // const float treezone = 32; // const int treeCount = 50; // transparentItemsVao = new VertexArrayObject<MeshData, VAOInstancedData> (); // // //====TREE1==== // // vaoi = transparentItemsVao.Add (Tetra.OBJMeshLoader.Load ("#Ottd3D.images.trees.obj__pinet1.obj")); // // vaoi.DiffuseTexture = Tetra.Texture.Load("#Ottd3D.images.trees.pinet1.png"); // // vaoi.modelMats = new Matrix4[treeCount]; // // for (int i = 0; i < treeCount; i++) { // // Vector2 pos = new Vector2 ((float)rnd.NextDouble() * treezone, (float)rnd.NextDouble() * treezone); // // float scale = (float)rnd.NextDouble () * 0.002f + 0.004f; // // vaoi.modelMats[i] =treeRot * Matrix4.CreateScale (scale)* Matrix4.CreateTranslation(pos.X, pos.Y, 0f); // // } // // vaoi.UpdateInstancesData (); // // //====TREE2==== // // addRandomTrees (transparentItemsVao, treeCount, // // "#Ottd3D.images.trees.simple.obj", // // "#Ottd3D.images.trees.birch_tree_small_20131230_2041956203.png",400f); // // // addRandomTrees (transparentItemsVao, treeCount, // // "#Ottd3D.images.trees.obj__pinet1.obj", // // "#Ottd3D.images.trees.pinet1.png",5f); // addRandomTrees (transparentItemsVao, treeCount, // "images/trees/obj__pinet2.obj", // "images/trees/pinet2.png",3f); // // addRandomTrees (transparentItemsVao, treeCount, // // "#Ottd3D.images.trees.obj__tree1.obj", // // "#Ottd3D.images.trees.tree1.png",5f); // // addRandomTrees (transparentItemsVao, treeCount, // // "#Ottd3D.images.trees.obj__tree2.obj", // // "#Ottd3D.images.trees.tree2.png", 5f); // // addRandomTrees (transparentItemsVao, treeCount, // // "#Ottd3D.images.trees.obj__tree3.obj", // // "#Ottd3D.images.trees.tree3.png", 5f); // // //transparentItemsVao.ComputeTangents (); // transparentItemsVao.BuildBuffers (); }