From 6b8af9cf83851c075c6c9514b1deaa931c2b19a4 Mon Sep 17 00:00:00 2001 From: Thomas Guillermo Albers Raviola Date: Fri, 16 Jan 2026 23:02:32 +0100 Subject: Initial commit --- 07-july/src/terrain.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 07-july/src/terrain.c (limited to '07-july/src/terrain.c') diff --git a/07-july/src/terrain.c b/07-july/src/terrain.c new file mode 100644 index 0000000..3bc66d2 --- /dev/null +++ b/07-july/src/terrain.c @@ -0,0 +1,163 @@ +#include "terrain.h" +#include "math/math_util.h" +#include "math/vector3f.h" +#include "util/util.h" + +#include +#include +#include + +#define PLANE_SIZE 128 +#define PLANE_MAX_HEIGHT 10 + +#define NUM_ARRAY_ELEMENTS(a) sizeof(a) / sizeof(*a) + +static float GetHeight(int x, int y, SDL_Surface* surface) +{ + if(x < 0 || x >= surface->w || y < 0 || y >= surface->h) + return 0.0f; + + Uint32 pixel = ( (Uint32*)surface->pixels )[y * surface->w + x]; + Uint8 r, g, b; + SDL_GetRGB(pixel, surface->format, &r, &g, &b); + + float height = (float)r / 255.0f; + + return height * 40.0f; +} + +static vec3_t GenerateNomal(int x, int y, SDL_Surface* surface) +{ + float hLeft = GetHeight(x-1, y, surface); + float hRight = GetHeight(x+1, y, surface); + float hUp = GetHeight(x, y+1, surface); + float hDown = GetHeight(x, y-1, surface); + + vec3_t normal = { hLeft - hRight, 2.0f, hDown - hUp}; + return vec3_normalize(&normal); +} + +GLfloat Terrain_GetHeightOfTerrain(terrain_t* terrain, GLfloat x, GLfloat z) +{ + GLfloat terrainX = x - terrain->position.x; + GLfloat terrainZ = z - terrain->position.z; + + GLfloat gridSquareSize = (float)terrain->l / ( (float)PLANE_SIZE - 1 ); + + GLint gridX = (GLint) floor(terrainX / gridSquareSize); + GLint gridZ = (GLint) floor(terrainZ / gridSquareSize); + + if(gridX >= PLANE_SIZE - 1 || gridX < 0 || gridZ >= PLANE_SIZE - 1 || gridZ < 0) + { + printf("called\n"); + return 0; + } + + GLfloat xCoord = fmod(terrainX, gridSquareSize) / gridSquareSize; + GLfloat zCoord = fmod(terrainZ, gridSquareSize) / gridSquareSize; + GLfloat answer; + + /* Determine in which triangle of the square are we. "Bary Centric Interpolation"*/ + if(xCoord <= (1 - zCoord)){ + /* 0, heights[gridX][gridZ], 0) */ + vec3_t p1 = { 0, terrain->height[ gridX * PLANE_SIZE + gridZ ], 0 }; + /* 1, heights[gridX + 1][gridZ], 0) */ + vec3_t p2 = { 1, terrain->height[ (gridX + 1) * PLANE_SIZE + gridZ ], 0}; + /* 0, heights[gridX][gridZ + 1], 1) */ + vec3_t p3 = { 0, terrain->height[ gridX * PLANE_SIZE + (gridZ + 1) ], 1}; + + vec2_t pos = {xCoord, zCoord}; + + answer = baryCentric(&p1, &p2, &p3, &pos); + } else { + /* (1, heights[gridX + 1][gridZ], 0) */ + vec3_t p1 = { 1, terrain->height[ (gridX + 1) * PLANE_SIZE + gridZ ], 0 }; + /* (1, heights[gridX + 1][gridZ + 1], 1) */ + vec3_t p2 = { 1, terrain->height[ (gridX + 1) * PLANE_SIZE + (gridZ + 1) ], 1}; + /* (0, heights[gridX][gridZ + 1], 1) */ + vec3_t p3 = { 0, terrain->height[ gridX * PLANE_SIZE + (gridZ + 1) ], 1}; + vec2_t pos = {xCoord, zCoord}; + + answer = baryCentric(&p1, &p2, &p3, &pos); + } + + return answer; +} + +terrain_t *Terrain_Create( int w, int l, const char* heightmap_path, texture_t *blendmap, TerrainTexturePack *textures ) +{ + terrain_t *terrain = (terrain_t*) malloc( sizeof(terrain_t) ); + terrain->height = (GLfloat*) malloc( sizeof(GLfloat) * PLANE_SIZE * PLANE_SIZE); + + terrain->blendmap = blendmap; + terrain->w = w; terrain->l = l; + terrain->textures = *textures; + + SDL_Surface* surface = IMG_Load(heightmap_path); + if(surface == NULL) + Util_FatalError("Heightmap file could not be loaded\n"); + + vertex_t data[PLANE_SIZE * PLANE_SIZE]; + int x, y; + for(x = 0; x < PLANE_SIZE; x++) + { + for(y = 0; y < PLANE_SIZE; y++) + { + vertex_t* v = &data[y + x * PLANE_SIZE]; + v->position = vec3_create( (float)x / (float)PLANE_SIZE, 0.0f, (float)y / (float)PLANE_SIZE); + /* Heightmap cordinates */ + int image_x = v->position.x * surface->w, image_y = v->position.z * surface->h; + + v->texCoord = vec2_create( v->position.x, v->position.z); + GLfloat height = GetHeight(image_x, image_y, surface); + terrain->height[y + x * PLANE_SIZE] = height; + v->position.y = height; + v->position.x *= w; + v->position.z *= l; + + v->normal = GenerateNomal(image_x, image_y, surface); + color_t temp = {+1.0f, +0.0f, +0.0f, +1.0f}; + v->color = temp; + } + } + + int runner = 0; + GLushort indices[ (PLANE_SIZE-1) * (PLANE_SIZE-1) * 6 ]; + for(x = 0; x < PLANE_SIZE-1; x++) + { + for(y = 0; y < PLANE_SIZE-1; y++) + { + indices[runner++] = PLANE_SIZE * x + y; + indices[runner++] = PLANE_SIZE * x + y + 1; + indices[runner++] = PLANE_SIZE * x + y + PLANE_SIZE; + + indices[runner++] = PLANE_SIZE * x + y + 1; + indices[runner++] = PLANE_SIZE * x + y + PLANE_SIZE + 1; + indices[runner++] = PLANE_SIZE * x + y + PLANE_SIZE; + } + } + + GLsizeiptr vertexBufferSize = NUM_ARRAY_ELEMENTS(data) * sizeof(vertex_t); + GLsizeiptr indexBufferSize = NUM_ARRAY_ELEMENTS(indices) * sizeof(GLushort); + + SDL_FreeSurface(surface); + + terrain->shape = Shape_CreateFromRawData(data, vertexBufferSize, indices, indexBufferSize); + return terrain; +} + +void Terrain_Destroy( terrain_t* terrain ) +{ + if(terrain->height) + free(terrain->height); + + Shape_Free(terrain->shape); + + int i; + for(i = 0; i < 4; i++) + Texture_Destroy(terrain->textures.texture[i]); + + Texture_Destroy(terrain->blendmap); + free(terrain); +} + -- cgit v1.2.3