314 lines
15 KiB
C#
314 lines
15 KiB
C#
using AC2RE.Definitions;
|
|
using LandblockExtraction.AtlasMaker;
|
|
using LandblockExtraction.DatEngine;
|
|
using LandblockExtraction.Tools;
|
|
using System;
|
|
using System.Numerics;
|
|
|
|
namespace LandblockExtraction.LandBlockExtractor {
|
|
public class LandBlockExtrator {
|
|
private PortalEngine portalEngine;
|
|
private CellEngine cellEngine;
|
|
private TerrainAtlasManager terrainAtlasManager;
|
|
|
|
private readonly int NumberLandBlocks = 255;
|
|
private readonly int BlockSize = 17;
|
|
private readonly int cellSize = 8;
|
|
|
|
public LandBlockExtrator(PortalEngine portalEngine, CellEngine cellEngine) {
|
|
this.portalEngine = portalEngine;
|
|
this.cellEngine = cellEngine;
|
|
|
|
terrainAtlasManager = new TerrainAtlasManager(portalEngine);
|
|
terrainAtlasManager.ExtractTexture();
|
|
terrainAtlasManager.GenerateUV();
|
|
terrainAtlasManager.SaveAllTerrain();
|
|
}
|
|
|
|
public BlockStruct? GetBlock(int landX, int landY) {
|
|
CellId landBlockId = new CellId((byte)landX, (byte)landY, 0xFF, 0xFF);
|
|
var landBlock = cellEngine.GetLandBlockData(landBlockId.id);
|
|
if (landBlock == null) return null;
|
|
|
|
return GenerateBlockStructByData(landBlock, landX, landY);
|
|
}
|
|
|
|
public BlockStruct GenerateBlockStructByData(CLandBlockData blockData, int landX, int landY) {
|
|
BlockStruct blockStruct = new BlockStruct();
|
|
for (int y = 0; y < BlockSize; y++) {
|
|
for (int x = 0; x < BlockSize; x++) {
|
|
var indice = y * BlockSize + x;
|
|
blockStruct.verticesStruct.position[indice] = GenerateVertexPosition(landX, landY, x, y, blockData.heights[indice]);
|
|
blockStruct.verticesStruct.color[indice] = GenerateVertexColor(blockData.cellInfos[indice]);
|
|
blockStruct.verticesStruct.farcolor[indice] = GenerateVertexFarColor(blockData.cellInfos[indice]);
|
|
blockStruct.verticesStruct.terraintype[indice] = GenerateVertexTerrainType(blockData.cellInfos[indice]);
|
|
blockStruct.verticesStruct.texturecoord[indice] = GenerateUVForSubTile(x, y);
|
|
blockStruct.indices = GenerateBasicIndices();
|
|
|
|
}
|
|
}
|
|
//blockStruct.verticesStruct.texturecoord = GenerateBasicUVTest(blockStruct);
|
|
blockStruct.verticesStruct.normal = GenerateBasicNormal(blockStruct);
|
|
//DoubleEdgeVertices(blockStruct);
|
|
|
|
Dictionary<int, int> testTerr = new Dictionary<int, int>();
|
|
foreach (var test in blockStruct.verticesStruct.terraintype) {
|
|
var type = (int)test.X;
|
|
if (testTerr.ContainsKey(type)) {
|
|
testTerr[type]++;
|
|
} else {
|
|
testTerr.Add(type, 1);
|
|
}
|
|
}
|
|
|
|
return blockStruct;
|
|
}
|
|
|
|
private Vector2 GenerateBasicUV(int x, int y) {
|
|
float u = (float)x / (BlockSize - 1) * 8;
|
|
float v = (float)y / (BlockSize - 1) * 8;
|
|
|
|
return new Vector2(u, v);
|
|
}
|
|
private Vector2 GenerateUVForSubTile(int x, int y) {
|
|
// Taille d'une "mini-tuile" en termes de coordonnées UV
|
|
float miniTileSize = 1f / BlockSize - 1; // Comme la sous-grille est 5x5
|
|
|
|
// Calcul des coordonnées UV basées sur la position (x, y) dans la sous-grille
|
|
float u = x * miniTileSize;
|
|
float v = y * miniTileSize;
|
|
|
|
return new Vector2(u, v);
|
|
}
|
|
private Vector2[] GenerateBasicUVTest(BlockStruct blockStruct) {
|
|
Vector2[] uvs = new Vector2[blockStruct.verticesStruct.position.Length];
|
|
|
|
for (int i = 0; i < uvs.Length; i++) {
|
|
uvs[i] = new Vector2(0, 0);
|
|
}
|
|
|
|
for (int i = 0; i < blockStruct.indices.Length; i += 6) {
|
|
int index1 = blockStruct.indices[i];
|
|
int index2 = blockStruct.indices[i + 1];
|
|
int index3 = blockStruct.indices[i + 2];
|
|
int index4 = blockStruct.indices[i + 5];
|
|
|
|
uvs[index1] = new(0, 0);
|
|
uvs[index2] = new(0, 1);
|
|
uvs[index3] = new(1, 0);
|
|
uvs[index4] = new(1, 1);
|
|
}
|
|
|
|
return uvs;
|
|
}
|
|
private Vector3[] GenerateBasicNormal(BlockStruct blockStruct) {
|
|
Vector3[] normals = new Vector3[blockStruct.verticesStruct.position.Length];
|
|
|
|
// Initialise tous les vecteurs normaux à zéro
|
|
for (int i = 0; i < normals.Length; i++) {
|
|
normals[i] = new Vector3(0, 0, 0);
|
|
}
|
|
|
|
// Parcourt tous les indices et calcule les normales pour chaque triangle
|
|
for (int i = 0; i < blockStruct.indices.Length; i += 6) {
|
|
int index1 = blockStruct.indices[i];
|
|
int index2 = blockStruct.indices[i + 1];
|
|
int index3 = blockStruct.indices[i + 2];
|
|
int index4 = blockStruct.indices[i + 5];
|
|
|
|
Vector3 vertex1 = blockStruct.verticesStruct.position[index1];
|
|
Vector3 vertex2 = blockStruct.verticesStruct.position[index2];
|
|
Vector3 vertex3 = blockStruct.verticesStruct.position[index3];
|
|
Vector3 vertex4 = blockStruct.verticesStruct.position[index4];
|
|
|
|
// Calcule la normale du triangle
|
|
/*Vector3 edge1 = vertex2 - vertex1;
|
|
Vector3 edge2 = vertex3 - vertex1;
|
|
Vector3 normal = Vector3.Cross(edge1, edge2);
|
|
normal = Vector3.Normalize(normal);*/
|
|
var normal = MathOperations.CalculateQuadNormal(vertex1, vertex2, vertex3, vertex4);
|
|
// Ajoute la normale du triangle aux normales des sommets du triangle
|
|
normals[index1] += normal;
|
|
normals[index2] += normal;
|
|
normals[index3] += normal;
|
|
normals[index4] += normal;
|
|
}
|
|
|
|
// Normalise toutes les normales de sommets pour qu'elles soient de longueur unitaire
|
|
for (int i = 0; i < normals.Length; i++) {
|
|
normals[i] = Vector3.Normalize(normals[i]);
|
|
}
|
|
|
|
return normals;
|
|
}
|
|
|
|
private int[] GenerateBasicIndices() {
|
|
List<int> indices = new List<int>();
|
|
|
|
for (int y = 0; y < BlockSize - 1; y++) {
|
|
for (int x = 0; x < BlockSize - 1; x++) {
|
|
// Indices des sommets du premier triangle
|
|
indices.Add(y * BlockSize + x);
|
|
indices.Add((y + 1) * BlockSize + x);
|
|
indices.Add(y * BlockSize + x + 1);
|
|
|
|
// Indices des sommets du deuxième triangle
|
|
indices.Add(y * BlockSize + x + 1);
|
|
indices.Add((y + 1) * BlockSize + x);
|
|
indices.Add((y + 1) * BlockSize + x + 1);
|
|
}
|
|
}
|
|
|
|
return indices.ToArray();
|
|
}
|
|
|
|
private Vector4 GenerateVertexTerrainType(uint cellInfo) {
|
|
var terrain = MathOperations.GetTerrainInCellInfo(cellInfo);
|
|
|
|
return new(terrain, 0f, 0f, 0f);
|
|
}
|
|
|
|
private Vector3 GenerateVertexPosition(int landx, int landy, int x, int y, byte height) {
|
|
int tmpx = (landx * BlockSize + y) * cellSize;
|
|
int tmpy = (BlockSize * NumberLandBlocks * cellSize) - ((landy * BlockSize + x) * cellSize) - 1;
|
|
var newX = (tmpx - (NumberLandBlocks * BlockSize * cellSize / 2));
|
|
var newY = (tmpy - ((NumberLandBlocks * BlockSize * cellSize) - (NumberLandBlocks * BlockSize * cellSize / 2) - 1));
|
|
|
|
return new Vector3(newX, portalEngine.landScapeDefs.landHeightTable[height], newY);
|
|
}
|
|
private Vector4 GenerateVertexColor(uint cellInfo) {
|
|
var terrain = MathOperations.GetTerrainInCellInfo(cellInfo);
|
|
|
|
foreach (var terrainType in portalEngine.cTerrainDesc.terrains) {
|
|
if (terrainType.terrainIndex == terrain) {
|
|
foreach (var surfaceIndex in portalEngine.cSurfaceDesc.surfaces) {
|
|
if (surfaceIndex.surfIndex == terrainType.surfaceInfo) {
|
|
var color = surfaceIndex.terrainMaterials.First().vertexColor.First().vertexColor;
|
|
return MathOperations.RGBAColorToVector4(color);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return Vector4.One;
|
|
}
|
|
private Vector4 GenerateVertexFarColor(uint cellInfo) {
|
|
var terrain = MathOperations.GetTerrainInCellInfo(cellInfo);
|
|
|
|
foreach (var terrainType in portalEngine.cTerrainDesc.terrains) {
|
|
if (terrainType.terrainIndex == terrain) {
|
|
foreach (var surfaceIndex in portalEngine.cSurfaceDesc.surfaces) {
|
|
if (surfaceIndex.surfIndex == terrainType.surfaceInfo) {
|
|
var color = surfaceIndex.terrainMaterials.First().vertexColor.First().farVertexColor;
|
|
return MathOperations.RGBAColorToVector4(color);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return Vector4.One;
|
|
}
|
|
|
|
//TEST
|
|
public void DoubleEdgeVertices(BlockStruct blockStruct) {
|
|
List<Vector3> newPositions = new List<Vector3>();
|
|
List<Vector3> newNormals = new List<Vector3>();
|
|
List<Vector4> newColors = new List<Vector4>();
|
|
List<Vector4> newFarColors = new List<Vector4>();
|
|
List<Vector2> newTexCoord = new List<Vector2>();
|
|
List<Vector4> newTerrainTypes = new List<Vector4>();
|
|
List<float> newRealTerrainType = new List<float>();
|
|
|
|
int originalVertexCount = blockStruct.verticesStruct.position.Length;
|
|
int originalIndicesCount = blockStruct.indices.Length;
|
|
|
|
// Doubler les sommets sur le bord supérieur et inférieur
|
|
|
|
for (int i = 0; i < originalIndicesCount; i = i + 6) {
|
|
|
|
var one = blockStruct.indices[i + 0];
|
|
var two = blockStruct.indices[i + 1];
|
|
var three = blockStruct.indices[i + 2];
|
|
var foor = blockStruct.indices[i + 5];
|
|
|
|
newPositions.Add(blockStruct.verticesStruct.position[one]);
|
|
newColors.Add(blockStruct.verticesStruct.color[one]);
|
|
newFarColors.Add(blockStruct.verticesStruct.farcolor[one]);
|
|
newTerrainTypes.Add(new Vector4(blockStruct.verticesStruct.terraintype[one].X,
|
|
blockStruct.verticesStruct.terraintype[two].X,
|
|
blockStruct.verticesStruct.terraintype[three].X,
|
|
blockStruct.verticesStruct.terraintype[foor].X));
|
|
newRealTerrainType.Add(blockStruct.verticesStruct.terraintype[one].X);
|
|
|
|
/*newPositions.Add(blockStruct.verticesStruct.position[two]);
|
|
newColors.Add(blockStruct.verticesStruct.color[two]);
|
|
newFarColors.Add(blockStruct.verticesStruct.farcolor[two]);
|
|
newTerrainTypes.Add(new Vector4(blockStruct.verticesStruct.terraintype[one].X,
|
|
blockStruct.verticesStruct.terraintype[two].X,
|
|
blockStruct.verticesStruct.terraintype[three].X,
|
|
blockStruct.verticesStruct.terraintype[foor].X));
|
|
newRealTerrainType.Add(blockStruct.verticesStruct.terraintype[two].X);
|
|
|
|
newPositions.Add(blockStruct.verticesStruct.position[three]);
|
|
newColors.Add(blockStruct.verticesStruct.color[three]);
|
|
newFarColors.Add(blockStruct.verticesStruct.farcolor[three]);
|
|
newTerrainTypes.Add(new Vector4(blockStruct.verticesStruct.terraintype[one].X,
|
|
blockStruct.verticesStruct.terraintype[two].X,
|
|
blockStruct.verticesStruct.terraintype[three].X,
|
|
blockStruct.verticesStruct.terraintype[foor].X));
|
|
newRealTerrainType.Add(blockStruct.verticesStruct.terraintype[three].X);
|
|
|
|
|
|
newPositions.Add(blockStruct.verticesStruct.position[foor]);
|
|
newColors.Add(blockStruct.verticesStruct.color[foor]);
|
|
newFarColors.Add(blockStruct.verticesStruct.farcolor[foor]);
|
|
newTerrainTypes.Add(new Vector4(blockStruct.verticesStruct.terraintype[one].X,
|
|
blockStruct.verticesStruct.terraintype[two].X,
|
|
blockStruct.verticesStruct.terraintype[three].X,
|
|
blockStruct.verticesStruct.terraintype[foor].X));
|
|
newRealTerrainType.Add(blockStruct.verticesStruct.terraintype[foor].X);
|
|
|
|
newTexCoord.Add(new(0, 0));
|
|
newTexCoord.Add(new(0, 1));
|
|
newTexCoord.Add(new(1, 0));
|
|
newTexCoord.Add(new(1, 1));*/
|
|
|
|
var normal = MathOperations.CalculateQuadNormal(blockStruct.verticesStruct.position[one],
|
|
blockStruct.verticesStruct.position[two],
|
|
blockStruct.verticesStruct.position[three],
|
|
blockStruct.verticesStruct.position[foor]);
|
|
|
|
newNormals.Add(normal);
|
|
//newNormals.Add(normal);
|
|
//newNormals.Add(normal);
|
|
//newNormals.Add(normal);
|
|
}
|
|
|
|
// Ajouter les nouveaux sommets à la structure BlockStruct (étape 2)
|
|
// Vous devez également mettre à jour les indices dans blockStruct.indices
|
|
blockStruct.verticesStruct.position = newPositions.ToArray();
|
|
blockStruct.verticesStruct.normal = newNormals.ToArray();
|
|
blockStruct.verticesStruct.color = newColors.ToArray();
|
|
blockStruct.verticesStruct.farcolor = newFarColors.ToArray();
|
|
blockStruct.verticesStruct.texturecoord = newTexCoord.ToArray();
|
|
blockStruct.verticesStruct.terraintype = newTerrainTypes.ToArray();
|
|
blockStruct.verticesStruct.realtype = newRealTerrainType.ToArray();
|
|
|
|
blockStruct.indices = GenerateNewsIndices(newPositions.Count);
|
|
}
|
|
|
|
private int[] GenerateNewsIndices(int count) {
|
|
List<int> indices = new List<int>();
|
|
for (int i = 0; i < count; i = i + 4) {
|
|
indices.Add(i);
|
|
indices.Add(i + 1);
|
|
indices.Add(i + 2);
|
|
indices.Add(i + 2);
|
|
indices.Add(i + 1);
|
|
indices.Add(i + 3);
|
|
}
|
|
|
|
return indices.ToArray();
|
|
}
|
|
}
|
|
}
|