176 lines
8.9 KiB
C#
176 lines
8.9 KiB
C#
using LandblockExtraction.AtlasMaker;
|
|
using LandblockExtraction.DatEngine;
|
|
using LandblockExtraction.LandBlockExtractor;
|
|
using Map3DRendering.Common;
|
|
using OpenTK.Graphics.OpenGL4;
|
|
using OpenTK.Mathematics;
|
|
|
|
namespace Map3DRendering {
|
|
public class MapRender {
|
|
private PortalEngine portalEngine;
|
|
private CellEngine cellEngine;
|
|
private LandBlockExtrator landblockExtraction;
|
|
private TerrainAtlasManager terrainAtlasManager;
|
|
|
|
private readonly int NumberLandBlocks = 255;
|
|
private readonly int BlockSize = 17;
|
|
private readonly int allBlocks = 255 * 17 * 255 * 17;
|
|
private readonly int cellSize = 8;
|
|
private readonly int radius = 0x10; // Rayon du voisinage
|
|
|
|
public int[,] _vertexArrayObject;
|
|
public int[,] _vertexBufferObject;
|
|
public int[,] _elementBufferObject;
|
|
public bool[,] _mapExiste;
|
|
|
|
public int currentLandBlockX { get; private set; } // Position X du landblock actuel
|
|
public int currentLandBlockY { get; private set; } // Position Y du landblock actuel
|
|
public int startX { get; private set; }
|
|
public int startY { get; private set; }
|
|
public int endX { get; private set; }
|
|
public int endY { get; private set; }
|
|
public MapRender() {
|
|
portalEngine = new PortalEngine();
|
|
cellEngine = new CellEngine();
|
|
terrainAtlasManager = new(portalEngine);
|
|
|
|
landblockExtraction = new(portalEngine, cellEngine);
|
|
|
|
_vertexArrayObject = new int[0xFE, 0xFE];
|
|
_vertexBufferObject = new int[0xFE, 0xFE];
|
|
_elementBufferObject = new int[0xFE, 0xFE];
|
|
_mapExiste = new bool[0xFE, 0xFE];
|
|
|
|
currentLandBlockX = 0x7F;
|
|
currentLandBlockY = 0x7F;
|
|
|
|
CalculeRadius(currentLandBlockX, currentLandBlockY);
|
|
}
|
|
public int GetIndiceLenght() {
|
|
return (17 - 1) * (17 - 1) * 6; //Always that.
|
|
}
|
|
public void CalculeRadius(int x, int y) {
|
|
currentLandBlockX = x;
|
|
currentLandBlockY = y;
|
|
startX = Math.Max(0, currentLandBlockX - radius);
|
|
startY = Math.Max(0, currentLandBlockY - radius);
|
|
endX = Math.Min(NumberLandBlocks - 1, currentLandBlockX + radius);
|
|
endY = Math.Min(NumberLandBlocks - 1, currentLandBlockY + radius);
|
|
}
|
|
public void OnLoad(Shader _shader) {
|
|
for (int landY = startY; landY <= endY; landY++) {
|
|
for (int landX = startX; landX <= endX; landX++) {
|
|
if (!_mapExiste[landX, landY]) {
|
|
var block = landblockExtraction.GetBlock(landX, landY);
|
|
if (block != null) {
|
|
InitializeBlock(landX, landY, block, _shader);
|
|
_mapExiste[landX, landY] = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private void InitializeBlock(int x, int y, BlockStruct block, Shader _shader) {
|
|
int lenghPacket = 20;
|
|
// Initialisez le VAO, VBO et EBO pour le bloc à (x, y)...
|
|
// Utilisez le code de votre méthode OnLoad originale pour configurer le VAO, VBO et EBO.
|
|
int tempVertexArray = GL.GenVertexArray();
|
|
GL.BindVertexArray(tempVertexArray);
|
|
_vertexArrayObject[x, y] = tempVertexArray;
|
|
|
|
int tmpVertexBuffer = GL.GenBuffer();
|
|
GL.BindBuffer(BufferTarget.ArrayBuffer, tmpVertexBuffer);
|
|
GL.BufferData(BufferTarget.ArrayBuffer, block.verticesStruct.Vertices().Length * sizeof(float), block.verticesStruct.Vertices(), BufferUsageHint.StaticDraw);
|
|
_vertexBufferObject[x, y] = tmpVertexBuffer;
|
|
|
|
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, lenghPacket * sizeof(float), 0);
|
|
|
|
int tmpElementBuffer = GL.GenBuffer();
|
|
GL.BindBuffer(BufferTarget.ElementArrayBuffer, tmpElementBuffer);
|
|
GL.BufferData(BufferTarget.ElementArrayBuffer, block.indices.Length * sizeof(int), block.indices, BufferUsageHint.StaticDraw);
|
|
_elementBufferObject[x, y] = tmpElementBuffer;
|
|
|
|
var vertexLocation = _shader.GetAttribLocation("aPos");
|
|
GL.EnableVertexAttribArray(vertexLocation);
|
|
GL.VertexAttribPointer(vertexLocation, 3, VertexAttribPointerType.Float, false, lenghPacket * sizeof(float), 0);
|
|
|
|
var vertexNormal = _shader.GetAttribLocation("aNormal");
|
|
GL.EnableVertexAttribArray(vertexNormal);
|
|
GL.VertexAttribPointer(vertexNormal, 3, VertexAttribPointerType.Float, false, lenghPacket * sizeof(float), 3 * sizeof(float));
|
|
|
|
var colorLocation = _shader.GetAttribLocation("aColor");
|
|
GL.EnableVertexAttribArray(colorLocation);
|
|
GL.VertexAttribPointer(colorLocation, 4, VertexAttribPointerType.Float, false, lenghPacket * sizeof(float), 6 * sizeof(float));
|
|
|
|
var farcolorLocation = _shader.GetAttribLocation("aColorFar");
|
|
GL.EnableVertexAttribArray(farcolorLocation);
|
|
GL.VertexAttribPointer(farcolorLocation, 4, VertexAttribPointerType.Float, false, lenghPacket * sizeof(float), 10 * sizeof(float));
|
|
|
|
var texturecoordLocation = _shader.GetAttribLocation("aTexCoord");
|
|
GL.EnableVertexAttribArray(texturecoordLocation);
|
|
GL.VertexAttribPointer(texturecoordLocation, 2, VertexAttribPointerType.Float, false, lenghPacket * sizeof(float), 14 * sizeof(float));
|
|
|
|
var terraintypeLocation = _shader.GetAttribLocation("aTexType");
|
|
GL.EnableVertexAttribArray(terraintypeLocation);
|
|
GL.VertexAttribPointer(terraintypeLocation, 4, VertexAttribPointerType.Float, false, lenghPacket * sizeof(float), 16 * sizeof(float));
|
|
}
|
|
public void Render(Shader shader) {
|
|
for (int y = startY; y <= endY; y++) {
|
|
for (int x = startX; x <= endX; x++) {
|
|
if (_mapExiste[x, y]) {
|
|
var model = Matrix4.Identity;//CreateTranslation(x * BlockSize, 0, y * BlockSize); // Ajustez selon votre système de coordonnées
|
|
shader.SetMatrix4("model", model);
|
|
GL.BindVertexArray(_vertexArrayObject[x, y]);
|
|
GL.DrawElements(PrimitiveType.Triangles, GetIndiceLenght(), DrawElementsType.UnsignedInt, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public void CleanupBlock(int x, int y) {
|
|
if (_mapExiste[x, y]) {
|
|
GL.DeleteBuffer(_vertexBufferObject[x, y]);
|
|
GL.DeleteBuffer(_elementBufferObject[x, y]);
|
|
GL.DeleteVertexArray(_vertexArrayObject[x, y]);
|
|
_mapExiste[x, y] = false;
|
|
}
|
|
}
|
|
public void UpdateBlocks(Vector3 cameraPosition, Shader shader) {
|
|
// Convertir la position de la caméra en coordonnées de landblock
|
|
int newLandBlockX = ConvertPositionToLandBlockCoord(cameraPosition.X);
|
|
int newLandBlockY = (0xFF) - ConvertPositionToLandBlockCoord(cameraPosition.Z);
|
|
|
|
// Vérifier si la caméra a déplacé suffisamment pour nécessiter une mise à jour des blocs
|
|
if (newLandBlockX != currentLandBlockX || newLandBlockY != currentLandBlockY) {
|
|
// Nettoyer les blocs qui ne sont plus dans la nouvelle zone visible
|
|
for (int y = startY; y <= endY; y++) {
|
|
for (int x = startX; x <= endX; x++) {
|
|
if (!IsInNewRadius(x, y, newLandBlockX, newLandBlockY)) {
|
|
CleanupBlock(x, y);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Mettre à jour les coordonnées du rayon pour la nouvelle position
|
|
CalculeRadius(newLandBlockX, newLandBlockY);
|
|
|
|
// Initialiser les nouveaux blocs dans la nouvelle zone visible
|
|
OnLoad(shader);
|
|
}
|
|
}
|
|
|
|
private int ConvertPositionToLandBlockCoord(float position) {
|
|
// Convertir la position en coordonnée de landblock, ajuster selon la mise en échelle de votre carte
|
|
return (int)(position / 128) + 0x7f; // Ajustez cette conversion en fonction de votre mise en échelle
|
|
}
|
|
private bool IsInNewRadius(int x, int y, int newLandBlockX, int newLandBlockY) {
|
|
// Calculer le nouveau startX, startY, endX, et endY basé sur newLandBlockX, newLandBlockY
|
|
int newStartX = Math.Max(0, newLandBlockX - radius);
|
|
int newStartY = Math.Max(0, newLandBlockY - radius);
|
|
int newEndX = Math.Min(NumberLandBlocks - 1, newLandBlockX + radius);
|
|
int newEndY = Math.Min(NumberLandBlocks - 1, newLandBlockY + radius);
|
|
|
|
// Vérifier si (x, y) est dans la nouvelle zone définie par newStartX, newStartY, newEndX, et newEndY
|
|
return x >= newStartX && x <= newEndX && y >= newStartY && y <= newEndY;
|
|
}
|
|
}
|
|
}
|