velage/engine/planet.hpp
miri 567a588d34 segfault fixed, subdivison of cubesphere done
TODO:automatic calculation of needed chunks, resizing chunks, multithreading
2024-02-13 19:55:11 +01:00

255 lines
No EOL
7.6 KiB
C++

#ifndef __PLANET_H__
#define __PLANET_H__
#include <algorithm>
#include <complex>
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <glm/ext/quaternion_geometric.hpp>
#include <glm/ext/vector_float2.hpp>
#include <glm/ext/vector_float3.hpp>
#include <iostream>
#define CHUNK_SIZE 16
glm::vec3 posMasks[18]={
glm::vec3(1.0,0.0,0.0), glm::vec3(0.0,-1.0,0.0), glm::vec3(0.0,0.0,-1.0),
glm::vec3(0.0,1.0,0.0), glm::vec3(1.0,0.0,0.0), glm::vec3(0.0,0.0,-1.0),
glm::vec3(0.0,0.0,1.0), glm::vec3(-1.0,0.0,0.0), glm::vec3(0.0,-1.0,0.0),
glm::vec3(-1.0,0.0,0.0), glm::vec3(0.0,-1.0,0.0), glm::vec3(0.0,0.0,-1.0),
glm::vec3(0.0,-1.0,0.0), glm::vec3(1.0,0.0,0.0), glm::vec3(0.0,0.0,-1.0),
glm::vec3(0.0,0.0,-1.0), glm::vec3(-1.0,0.0,0.0), glm::vec3(0.0,-1.0,0.0),
};
//TODO: generate the Heightmap on the GPU via compute shaders
float *generateHeightmap(glm::vec3 start, glm::vec3 end){
float *ret = (float*)malloc(CHUNK_SIZE*CHUNK_SIZE*sizeof(float));
for (int i=0; i<CHUNK_SIZE*CHUNK_SIZE; i++) {
ret[i]=1.0+(random()/0x1p31-0.5)/2.0;
}
return ret;
}
class planetMesh;
class chunk;
// vertecie data for a plane that is terrain
struct terraPlaneVtx{
glm::vec3 vertices[CHUNK_SIZE * CHUNK_SIZE];
unsigned int indices[(CHUNK_SIZE-1)*(CHUNK_SIZE-1)*2*3];
};
class planetMesh{
public:
unsigned int numverts;
unsigned int numindecies;
glm::vec3 *vertices;
unsigned int *indices;
~planetMesh(){
if(vertices){
free(vertices);
}
if(indices){
free(indices);
}
}
};
class chunk{
public:
terraPlaneVtx* vtx=nullptr;
chunk* children[4]={nullptr,nullptr,nullptr,nullptr};
glm::vec3 startPos;
glm::vec3 endPos;
int orientation=0;
~chunk(){
//std::cout<<"destructor of chunk"<<"\n";
if(vtx)
free(vtx);
for (int i=0; i<4; i++) {
free(children[i]);
}
}
unsigned int getSizeVtx(){
if(children[0]!=NULL&&children[1]!=NULL&&children[2]!=NULL&&children[3]!=NULL){
unsigned int res=0;
for (int i=0; i<4; i++) {
res+=children[i]->getSizeVtx();
}
return res;
}
if(!vtx) return 0;
return sizeof(vtx->vertices)/sizeof(vtx->vertices[0]);
}
unsigned int getSizeInd(){
if(children[0]!=NULL&&children[1]!=NULL&&children[2]!=NULL&&children[3]!=NULL){
unsigned int res=0;
for (int i=0; i<4; i++) {
res+=children[i]->getSizeInd();
}
return res;
}
if(!vtx) return 0;
return sizeof(vtx->indices)/sizeof(vtx->indices[0]);
}
void putVtxInList(glm::vec3 *list, unsigned int *current){
if(children[0]&&children[1]&&children[2]&&children[3]){
for (int i=0; i<4; i++) {
children[i]->putVtxInList(list,current);
}
return;
}
if(vtx){
memcpy(&list[*current], &vtx->vertices, sizeof(vtx->vertices));
*current+=sizeof(vtx->vertices)/sizeof(vtx->vertices[0]);
}
}
void putIndInList(unsigned int *list, unsigned int *icurrent, unsigned int *vcurrent){
if(children[0]!=NULL&&children[1]!=NULL&&children[2]!=NULL&&children[3]!=NULL){
for (int i=0; i<4; i++) {
children[i]->putIndInList(list,icurrent,vcurrent);
}
return;
}
if(vtx){
for(int i=0; i<sizeof(vtx->indices)/sizeof(vtx->indices[0]);i++){
list[*icurrent+i]=vtx->indices[i]+*vcurrent;
}
*icurrent+=sizeof(vtx->indices)/sizeof(vtx->indices[0]);
*vcurrent+=sizeof(vtx->vertices)/sizeof(vtx->vertices[0]);
}
}
void generatePlane(){
terraPlaneVtx *tpvtx = (terraPlaneVtx*)malloc(sizeof(terraPlaneVtx));
vtx=tpvtx;
//use alternative axis when y is not available to measure the size of the square (bzw. chunk)
float scaler=(orientation==1||orientation==4)?std::abs(endPos.x-startPos.x):std::abs(endPos.y-startPos.y);
float divider=(float)CHUNK_SIZE-1.0;
glm::vec3 midpoint=(startPos+endPos) /2.f;
for (unsigned int j=0; j<CHUNK_SIZE*CHUNK_SIZE; j++) {
glm::vec3 cv=
glm::vec3((j%CHUNK_SIZE)/divider-0.5) * posMasks[orientation*3+1] * scaler+
glm::vec3((j/CHUNK_SIZE)/divider-0.5) * posMasks[orientation*3+2] * scaler+
midpoint;
;
//cv*=scaler;
cv=glm::normalize(cv);
//cv*=1.0+(random()/0x1p31-0.5)/2.0;
vtx->vertices[j]=cv;
}
unsigned int s=0;
for (unsigned int j=0; j<(CHUNK_SIZE-1)*(CHUNK_SIZE-1)*2*3+s; j+=6) {
if((j/6+1)%CHUNK_SIZE==0&&j!=0){ s+=6; continue; }
unsigned int jdiv=j/6;
vtx->indices[j -s]=jdiv;
vtx->indices[j+1-s]=jdiv+1;
vtx->indices[j+2-s]=jdiv+CHUNK_SIZE;
vtx->indices[j+3-s]=jdiv+1;
vtx->indices[j+4-s]=jdiv+CHUNK_SIZE+1;
vtx->indices[j+5-s]=jdiv+CHUNK_SIZE;
}
}
// !WIP!
void subdivide(){
if(vtx){
free(vtx);
}
chunk *chunks = (chunk*)malloc(sizeof(chunk)*4);
glm::vec3 midpoint=(startPos+endPos)/2.f;
glm::vec3 midAdd=endPos-startPos;
glm::vec3 selX=glm::normalize(posMasks[orientation*3+1]);
glm::vec3 selY=glm::normalize(posMasks[orientation*3+2]);
chunks[0].startPos=startPos;
chunks[0].endPos=midpoint;
chunks[1].startPos=startPos - midAdd * selX /2.f;
chunks[1].endPos=midpoint - midAdd * selX /2.f;
chunks[2].startPos=startPos - midAdd * selY / 2.f;
chunks[2].endPos=midpoint - midAdd * selY / 2.f;
chunks[3].startPos=midpoint;
chunks[3].endPos=endPos;
for (int i=0; i<4; i++) {
chunks[i].orientation=orientation;
chunks[i].generatePlane();
chunks[i].children[0]=nullptr;
chunks[i].children[1]=nullptr;
chunks[i].children[2]=nullptr;
chunks[i].children[3]=nullptr;
children[i]=&chunks[i];
//std::cout<<"children[i]->getSizeInd() = " << children[i]->getSizeInd() << " i = " << i << "\n";
}
}
};
class planet{
public:
chunk chunks[6];
void generateSphere(){
for (int i=0; i<6; i++) {
chunks[i].orientation=i;
chunks[i].startPos= 0.5f*(posMasks[i*3]+ (posMasks[i*3+1] + posMasks[i*3+2]));
chunks[i].endPos= 0.5f*(posMasks[i*3]- (posMasks[i*3+1] + posMasks[i*3+2]));
chunks[i].generatePlane();
}
//chunks[0].subdivide();
//chunks[0].children[0]->subdivide();
}
planetMesh toPlanetMesh(){
unsigned int ind=0;
unsigned int vert=0;
for (unsigned int i=0; i<6; i++) {
ind+=chunks[i].getSizeInd();
vert+=chunks[i].getSizeVtx();
}
//std::cout<<"ind "<<ind<<"\n";
glm::vec3 *vertices=(glm::vec3*)malloc(vert*sizeof(glm::vec3));
unsigned int ctr=0;
for (int i=0; i<6; i++) {
chunks[i].putVtxInList(vertices,&ctr);
}
unsigned *indices=(unsigned *)malloc(ind*sizeof(unsigned));
ctr=0;
unsigned int vctr=0;
for (int i=0; i<6; i++) {
chunks[i].putIndInList(indices,&ctr,&vctr);
}
planetMesh mesh;
mesh.numindecies=ind;
mesh.numverts=vert;
mesh.vertices=vertices;
mesh.indices=indices;
return mesh;
}
private:
};
#endif