cubious/src/engine_world.c

341 lines
9.2 KiB
C

#include <stdlib.h>
#include <math.h>
#include "engine_math.h"
#include "engine_world.h"
#include "engine_generation.h"
#include "engine_camera.h"
#include "engine_renderer.h"
void
InitializeWorld(CubeWorld* World,
CubeType* CubeTypes,
int X, int Z, int Height,
int ChunkSize,
float PerlinXSeed, float PerlinZSeed, float Inc,
int Octaves, float Persistence)
{
float* RenderVertexBuffer;
int RVBSize;
RVBSize = sizeof(float) * RENDER_FLOATS_PER_CUBE_VERTEX
* ChunkSize * ChunkSize * ChunkSize
* 6 * 6;
RenderVertexBuffer = malloc(RVBSize);
World->WorldChunks = malloc(sizeof(Chunk)*X*Z*Height);
World->ChunkDirtyList = malloc(sizeof(int)*X*Z*Height);
World->WorldIsDirty = 0;
World->TotalRebuild = 0;
World->PhysicsModelDirty = 0;
World->CubeTypes = CubeTypes;
World->ChunkCount = X*Z*Height;
World->ChunkDimension = ChunkSize;
World->XLength = X;
World->ZLength = Z;
World->StackHeight = Height;
World->PerlinXSeed = PerlinXSeed;
World->PerlinZSeed = PerlinZSeed;
World->Increment = Inc;
World->Octaves = Octaves;
World->Persistence = Persistence;
World->DayNightCycle = 0;
World->Apocalypse = 0;
World->Spheres = 0;
for (int s = 0; s < SPHERE_DEMO_COUNT; s++)
{
InitializeChunk(&World->Sphere[s], ChunkSize,
Vec3f(s*ChunkSize,
0,
-ChunkSize));
GenerateSphereChunk(&World->Sphere[s]);
GreedyMesh(&World->Sphere[s], World->CubeTypes, RenderVertexBuffer, &RVBSize);
InitializeChunkRenderBuffers(&World->Sphere[s], RenderVertexBuffer);
}
int i = 0;
for (int y = 0; y < Height; y++)
{
for (int z = 0; z < Z; z++)
{
for (int x = 0; x < X; x++)
{
World->ChunkDirtyList[i] = 0;
InitializeChunk(&World->WorldChunks[i], ChunkSize,
Vec3f(x*ChunkSize,
y*ChunkSize,
z*ChunkSize));
GenerateOctavedPerlinChunk(PerlinXSeed+(x*Inc*ChunkSize),
PerlinZSeed+(z*Inc*ChunkSize),
Inc,
&World->WorldChunks[i], y, Height,
Octaves, Persistence);
ChunkEarthBiomeWash(&World->WorldChunks[i]);
GreedyMesh(&World->WorldChunks[i], World->CubeTypes, RenderVertexBuffer, &RVBSize);
InitializeChunkRenderBuffers(&World->WorldChunks[i], RenderVertexBuffer);
i++;
}
}
}
free(RenderVertexBuffer);
}
void
ReseedWorld(CubeWorld* World,
CubeType* CubeTypes,
float PerlinXSeed, float PerlinZSeed, float Inc,
int Octaves, float Persistence)
{
World->WorldIsDirty = 1;
World->PerlinXSeed = PerlinXSeed;
World->PerlinZSeed = PerlinZSeed;
World->Increment = Inc;
World->Octaves = Octaves;
World->Persistence = Persistence;
int RVBSize;
RVBSize = sizeof(float) * RENDER_FLOATS_PER_CUBE_VERTEX
* World->ChunkDimension * World->ChunkDimension * World->ChunkDimension
* 6 * 6;
World->RenderVertexBuffer = malloc(RVBSize);
int i = 0;
for (int y = 0; y < World->StackHeight; y++)
{
for (int z = 0; z < World->ZLength; z++)
{
for (int x = 0; x < World->XLength; x++)
{
World->ChunkDirtyList[i] = 1;
World->WorldChunks[i].PerlinXSeed = PerlinXSeed + (x*Inc*World->ChunkDimension);
World->WorldChunks[i].PerlinZSeed = PerlinZSeed + (z*Inc*World->ChunkDimension);
World->WorldChunks[i].YLevel = y;
i++;
}
}
}
}
void
UpdateWorld(CubeWorld* World)
{
if (World->WorldIsDirty)
{
int ChkIndex = 0;
while (ChkIndex < World->ChunkCount && !World->ChunkDirtyList[ChkIndex])
{
ChkIndex++;
}
if (ChkIndex < World->ChunkCount && World->ChunkDirtyList[ChkIndex])
{
int RVBSize;
RVBSize = sizeof(float) * RENDER_FLOATS_PER_CUBE_VERTEX
* World->ChunkDimension * World->ChunkDimension * World->ChunkDimension
* 6 * 6;
GenerateOctavedPerlinChunk(World->WorldChunks[ChkIndex].PerlinXSeed,
World->WorldChunks[ChkIndex].PerlinZSeed,
World->Increment,
&World->WorldChunks[ChkIndex],
World->WorldChunks[ChkIndex].YLevel,
World->StackHeight,
World->Octaves, World->Persistence);
ChunkEarthBiomeWash(&World->WorldChunks[ChkIndex]);
GreedyMesh(&World->WorldChunks[ChkIndex], World->CubeTypes,
World->RenderVertexBuffer, &RVBSize);
if (!World->TotalRebuild)
{
UpdateChunkRenderBuffers(&World->WorldChunks[ChkIndex], World->RenderVertexBuffer);
}
else
{
InitializeChunkRenderBuffers(&World->WorldChunks[ChkIndex],
World->RenderVertexBuffer);
}
World->ChunkDirtyList[ChkIndex] = 0;
}
else
{
World->WorldIsDirty = 0;
World->TotalRebuild = 0;
free(World->RenderVertexBuffer);
}
}
}
void
InitializePlayer(CubeWorld* World, vec3f_t Position,
float CameraPitch, float CameraYaw)
{
World->Player.Body.Position = Position;
World->Player.Camera.Position = World->Player.Body.Position;
World->Player.Camera.Pitch = CameraPitch;
World->Player.Camera.Yaw = CameraYaw;
}
Chunk*
GetChunkFromPosition(CubeWorld* World, vec3f_t Position)
{
if (Position.x < 0 || Position.x >= World->XLength*World->ChunkDimension) return (0);
if (Position.y < 0 || Position.y >= World->StackHeight*World->ChunkDimension) return (0);
if (Position.z < 0 || Position.z >= World->ZLength*World->ChunkDimension) return (0);
int LowerBoundX = floor(Position.x / World->ChunkDimension);
int LowerBoundZ = floor(Position.z / World->ChunkDimension);
return (&World->WorldChunks[LowerBoundZ*World->ZLength + LowerBoundX]);
}
PhysicsStaticGeometry*
GetStaticChunkGeometryInformation(CubeWorld* World)
{
PhysicsStaticGeometry* Geometry = malloc(sizeof(PhysicsStaticGeometry));
Geometry->ChunkList = &(World->WorldChunks);
Geometry->AABBList = malloc(sizeof(PhysicsAABB)*World->ChunkCount);
Geometry->AABBCount = World->ChunkCount;
for (int i = 0; i < World->ChunkCount; i++)
{
Geometry->AABBList[i].Min = World->WorldChunks[i].Transform;
Geometry->AABBList[i].Max = AddVec3f(World->WorldChunks[i].Transform,
Vec3f(World->ChunkDimension, World->ChunkDimension, World->ChunkDimension));
}
return (Geometry);
}
void
RebuildStaticChunkGeometryInformation(CubeWorld* World,
PhysicsStaticGeometry* Geo)
{
Geo->ChunkList = &(World->WorldChunks);
free(Geo->AABBList);
Geo->AABBList = malloc(sizeof(PhysicsAABB)*World->ChunkCount);
Geo->AABBCount = World->ChunkCount;
for (int i = 0; i < World->ChunkCount; i++)
{
Geo->AABBList[i].Min = World->WorldChunks[i].Transform;
Geo->AABBList[i].Max = AddVec3f(World->WorldChunks[i].Transform,
Vec3f(World->ChunkDimension, World->ChunkDimension, World->ChunkDimension));
}
}
int
GetActiveCubeCount(CubeWorld* World)
{
int Sum = 0;
for (int i = 0; i < World->ChunkCount; i++)
{
Sum += World->WorldChunks[i].ActiveCubes;
}
return (Sum);
}
void
RedoWorld(CubeWorld* World,
int X, int Z, int Height,
int ChunkSize,
float PerlinXSeed, float PerlinZSeed, float Inc,
int Octaves, float Persistence)
{
for (int i = 0; i < World->ChunkCount; i++)
{
FreeChunk(&World->WorldChunks[i]);
FreeChunkRenderBuffers(&World->WorldChunks[i]);
}
free(World->WorldChunks);
free(World->ChunkDirtyList);
int RVBSize;
RVBSize = sizeof(float) * RENDER_FLOATS_PER_CUBE_VERTEX
* ChunkSize * ChunkSize * ChunkSize
* 6 * 6;
World->RenderVertexBuffer = malloc(RVBSize);
World->WorldChunks = malloc(sizeof(Chunk)*X*Z*Height);
World->ChunkDirtyList = malloc(sizeof(int)*X*Z*Height);
World->WorldIsDirty = 1;
World->TotalRebuild = 1;
World->ChunkCount = X*Z*Height;
World->ChunkDimension = ChunkSize;
World->XLength = X;
World->ZLength = Z;
World->StackHeight = Height;
World->PerlinXSeed = PerlinXSeed;
World->PerlinZSeed = PerlinZSeed;
World->Increment = Inc;
World->Octaves = Octaves;
World->Persistence = Persistence;
World->DayNightCycle = 0;
World->Apocalypse = 0;
World->Spheres = 0;
World->PhysicsModelDirty = 1;
int i = 0;
for (int y = 0; y < World->StackHeight; y++)
{
for (int z = 0; z < World->ZLength; z++)
{
for (int x = 0; x < World->XLength; x++)
{
InitializeChunk(&World->WorldChunks[i], ChunkSize,
Vec3f(x*ChunkSize,
y*ChunkSize,
z*ChunkSize));
World->ChunkDirtyList[i] = 1;
World->WorldChunks[i].PerlinXSeed = PerlinXSeed + (x*Inc*World->ChunkDimension);
World->WorldChunks[i].PerlinZSeed = PerlinZSeed + (z*Inc*World->ChunkDimension);
World->WorldChunks[i].YLevel = y;
i++;
}
}
}
}