255 lines
No EOL
7.6 KiB
C++
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 |