ULRE/src/SceneGraph/InlineGeometry.cpp

568 lines
22 KiB
C++
Raw Normal View History

2019-05-24 19:28:27 +08:00
#include<hgl/graph/InlineGeometry.h>
#include<hgl/graph/VertexBuffer.h>
#include<hgl/graph/vulkan/VKDevice.h>
#include<hgl/graph/vulkan/VKShaderModule.h>
#include<hgl/graph/SceneDB.h>
2019-05-24 19:28:27 +08:00
namespace hgl
{
namespace graph
{
vulkan::Renderable *CreateRectangle(SceneDB *db,vulkan::Material *mtl,const RectangleCreateInfo *rci)
2019-05-24 19:28:27 +08:00
{
const vulkan::VertexShaderModule *vsm=mtl->GetVertexShaderModule();
const int vertex_binding=vsm->GetStageInputBinding("Vertex");
2019-05-24 19:46:46 +08:00
if(vertex_binding==-1)
return(nullptr);
VB2f *vertex=new VB2f(4);
2019-05-24 19:28:27 +08:00
2019-05-24 19:46:46 +08:00
vertex->Begin();
vertex->WriteRectFan(rci->scope);
vertex->End();
2019-05-24 19:28:27 +08:00
2019-05-24 19:46:46 +08:00
vulkan::Renderable *render_obj=mtl->CreateRenderable(vertex->GetCount());
render_obj->Set(vertex_binding,db->CreateVBO(vertex));
render_obj->SetBoundingBox(vertex->GetAABB());
2019-05-24 19:28:27 +08:00
2019-05-24 19:46:46 +08:00
delete vertex;
db->Add(render_obj);
2019-05-24 19:28:27 +08:00
return render_obj;
}
vulkan::Renderable *CreateRoundRectangle(SceneDB *db,vulkan::Material *mtl,const RoundRectangleCreateInfo *rci)
2019-05-24 19:28:27 +08:00
{
const vulkan::VertexShaderModule *vsm=mtl->GetVertexShaderModule();
vulkan::Renderable *render_obj=nullptr;
const int vertex_binding=vsm->GetStageInputBinding("Vertex");
if(vertex_binding==-1)
return(nullptr);
VB2f *vertex=nullptr;
if(rci->radius==0||rci->round_per<=1) //这是要画矩形
{
vertex=new VB2f(4);
vertex->Begin();
vertex->WriteRectFan(rci->scope);
vertex->End();
}
else
{
float radius=rci->radius;
if(radius>rci->scope.GetWidth()/2.0f)radius=rci->scope.GetWidth()/2.0f;
if(radius>rci->scope.GetHeight()/2.0f)radius=rci->scope.GetHeight()/2.0f;
vertex=new VB2f(rci->round_per*4);
vertex->Begin();
vec2<float> *coord=new vec2<float>[rci->round_per];
2019-05-27 14:18:44 +08:00
float l=rci->scope.GetLeft(),
r=rci->scope.GetRight(),
t=rci->scope.GetTop(),
b=rci->scope.GetBottom();
2019-05-24 19:28:27 +08:00
for(uint i=0;i<rci->round_per;i++)
{
float ang=float(i)/float(rci->round_per-1)*90.0f;
float x=sin(hgl_ang2rad(ang))*radius;
float y=cos(hgl_ang2rad(ang))*radius;
coord[i].x=x;
coord[i].y=y;
//右上角
2019-05-27 14:18:44 +08:00
vertex->Write(r-radius+x,
t+radius-y);
2019-05-24 19:28:27 +08:00
}
//右下角
for(uint i=0;i<rci->round_per;i++)
{
2019-05-27 14:18:44 +08:00
vertex->Write(r-radius+coord[rci->round_per-1-i].x,
b-radius+coord[rci->round_per-1-i].y);
2019-05-24 19:28:27 +08:00
}
//左下角
for(uint i=0;i<rci->round_per;i++)
{
2019-05-27 14:18:44 +08:00
vertex->Write(l+radius-coord[i].x,
b-radius+coord[i].y);
2019-05-24 19:28:27 +08:00
}
//左上角
for(uint i=0;i<rci->round_per;i++)
{
2019-05-27 14:18:44 +08:00
vertex->Write(l+radius-coord[rci->round_per-1-i].x,
t+radius-coord[rci->round_per-1-i].y);
2019-05-24 19:28:27 +08:00
}
delete[] coord;
vertex->End();
}
render_obj=mtl->CreateRenderable(vertex->GetCount());
render_obj->Set(vertex_binding,db->CreateVBO(vertex));
render_obj->SetBoundingBox(vertex->GetAABB());
2019-05-24 19:28:27 +08:00
delete vertex;
db->Add(render_obj);
2019-05-24 19:46:46 +08:00
return render_obj;
}
vulkan::Renderable *CreateCircle(SceneDB *db,vulkan::Material *mtl,const CircleCreateInfo *cci)
2019-05-24 19:46:46 +08:00
{
const vulkan::VertexShaderModule *vsm=mtl->GetVertexShaderModule();
2019-05-24 19:28:27 +08:00
2019-05-24 19:46:46 +08:00
const int vertex_binding=vsm->GetStageInputBinding("Vertex");
if(vertex_binding==-1)
return(nullptr);
VB2f *vertex=new VB2f(cci->field_count+2);
vertex->Begin();
vertex->Write(cci->center.x,cci->center.y);
for(uint i=0;i<=cci->field_count;i++)
{
float ang=float(i)/float(cci->field_count)*360.0f;
float x=cci->center.x+sin(hgl_ang2rad(ang))*cci->radius.x;
float y=cci->center.y+cos(hgl_ang2rad(ang))*cci->radius.y;
vertex->Write(x,y);
}
vertex->End();
vulkan::Renderable *render_obj=mtl->CreateRenderable(vertex->GetCount());
render_obj->Set(vertex_binding,db->CreateVBO(vertex));
render_obj->SetBoundingBox(vertex->GetAABB());
2019-05-24 19:46:46 +08:00
delete vertex;
db->Add(render_obj);
2019-05-24 19:28:27 +08:00
return render_obj;
}
2019-05-27 22:48:01 +08:00
vulkan::Renderable *CreatePlaneGrid(SceneDB *db,vulkan::Material *mtl,const PlaneGridCreateInfo *pgci)
{
const vulkan::VertexShaderModule *vsm=mtl->GetVertexShaderModule();
const int vertex_binding=vsm->GetStageInputBinding("Vertex");
if(vertex_binding==-1)
return(nullptr);
VB3f *vertex=new VB3f(((pgci->step.u+1)+(pgci->step.v+1))*2);
vertex->Begin();
for(uint row=0;row<=pgci->step.u;row++)
2019-05-27 22:48:01 +08:00
{
float pos=float(row)/float(pgci->step.u);
vertex->WriteLine( to(pgci->coord[0],pgci->coord[1],pos),
to(pgci->coord[3],pgci->coord[2],pos));
}
for(uint col=0;col<=pgci->step.v;col++)
2019-05-27 22:48:01 +08:00
{
float pos=float(col)/float(pgci->step.v);
vertex->WriteLine(to(pgci->coord[1],pgci->coord[2],pos),
to(pgci->coord[0],pgci->coord[3],pos));
}
vertex->End();
vulkan::Renderable *render_obj=mtl->CreateRenderable(vertex->GetCount());
render_obj->Set(vertex_binding,db->CreateVBO(vertex));
render_obj->SetBoundingBox(vertex->GetAABB());
const int color_binding=vsm->GetStageInputBinding("Color");
if(color_binding!=-1)
{
VB4f *color=new VB4f(((pgci->step.u+1)+(pgci->step.v+1))*2);
color->Begin();
for(uint row=0;row<=pgci->step.u;row++)
{
if((row%pgci->side_step.u)==0)
color->Fill(pgci->side_color,2);
else
color->Fill(pgci->color,2);
}
for(uint col=0;col<=pgci->step.v;col++)
{
if((col%pgci->side_step.v)==0)
color->Fill(pgci->side_color,2);
else
color->Fill(pgci->color,2);
}
color->End();
render_obj->Set(color_binding,db->CreateVBO(color));
}
2019-05-27 22:48:01 +08:00
delete vertex;
db->Add(render_obj);
return render_obj;
}
vulkan::Renderable *CreatePlane(SceneDB *db,vulkan::Material *mtl,const PlaneCreateInfo *pci)
{
const float xy_vertices [] = { -0.5f,-0.5f,0.0f, +0.5f,-0.5f,0.0f, -0.5f,+0.5f,0.0f, +0.5f,+0.5f,0.0f};
float xy_tex_coord[] = { 0.0f, 0.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 1.0f};
const Vector3f xy_normal(0.0f,0.0f,1.0f);
const Vector3f xy_tangent(1.0f,0.0f,0.0f);
const vulkan::VertexShaderModule *vsm=mtl->GetVertexShaderModule();
vulkan::Renderable *render_obj=nullptr;
{
const int vertex_binding=vsm->GetStageInputBinding("Vertex");
if(vertex_binding==-1)
return(nullptr);
VB3f *vertex=new VB3f(4,xy_vertices);
render_obj=mtl->CreateRenderable(vertex->GetCount());
render_obj->Set(vertex_binding,db->CreateVBO(vertex));
render_obj->SetBoundingBox(vertex->GetAABB());
delete vertex;
}
if(render_obj)
{
const int normal_binding=vsm->GetStageInputBinding("Normal");
if(normal_binding!=-1)
{
VB3f *normal=new VB3f(4);
normal->Begin();
normal->Fill(xy_normal,4);
normal->End();
render_obj->Set(normal_binding,db->CreateVBO(normal));
delete normal;
}
const int tagent_binding=vsm->GetStageInputBinding("Tangent");
if(tagent_binding!=-1)
{
VB3f *tangent=new VB3f(4);
tangent->Begin();
tangent->Fill(xy_tangent,4);
tangent->End();
render_obj->Set(tagent_binding,db->CreateVBO(tangent));
delete tangent;
}
const int texcoord_binding=vsm->GetStageInputBinding("TexCoord");
if(texcoord_binding!=-1)
{
xy_tex_coord[2]=xy_tex_coord[6]=pci->tile.x;
xy_tex_coord[5]=xy_tex_coord[7]=pci->tile.y;
VB2f *tex_coord=new VB2f(4,xy_tex_coord);
render_obj->Set(texcoord_binding,db->CreateVBO(tex_coord));
delete tex_coord;
}
}
db->Add(render_obj);
return render_obj;
}
vulkan::Renderable *CreateCube(SceneDB *db,vulkan::Material *mtl,const CubeCreateInfo *cci)
{ // Points of a cube.
/* 4 5 */ const float points[]={ -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, +0.5f, +0.5f, -0.5f, +0.5f, +0.5f, -0.5f, -0.5f, -0.5f, +0.5f, -0.5f, -0.5f, +0.5f, +0.5f,
/* *------------* */ +0.5f, +0.5f, +0.5f, +0.5f, +0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, +0.5f, -0.5f, +0.5f, +0.5f, -0.5f, +0.5f, -0.5f, -0.5f,
/* /| /| */ -0.5f, -0.5f, +0.5f, -0.5f, +0.5f, +0.5f, +0.5f, +0.5f, +0.5f, +0.5f, -0.5f, +0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, +0.5f,
/* 0/ | 1/ | */ -0.5f, +0.5f, +0.5f, -0.5f, +0.5f, -0.5f, +0.5f, -0.5f, -0.5f, +0.5f, -0.5f, +0.5f, +0.5f, +0.5f, +0.5f, +0.5f, +0.5f, -0.5f };
/* *--+---------* | */ // Normals of a cube.
/* | | | | */ const float normals[]={ +0.0f, -1.0f, +0.0f, +0.0f, -1.0f, +0.0f, +0.0f, -1.0f, +0.0f, +0.0f, -1.0f, +0.0f, +0.0f, +1.0f, +0.0f, +0.0f, +1.0f, +0.0f,
/* | 7| | 6| */ +0.0f, +1.0f, +0.0f, +0.0f, +1.0f, +0.0f, +0.0f, +0.0f, -1.0f, +0.0f, +0.0f, -1.0f, +0.0f, +0.0f, -1.0f, +0.0f, +0.0f, -1.0f,
/* | *---------+--* */ +0.0f, +0.0f, +1.0f, +0.0f, +0.0f, +1.0f, +0.0f, +0.0f, +1.0f, +0.0f, +0.0f, +1.0f, -1.0f, +0.0f, +0.0f, -1.0f, +0.0f, +0.0f,
/* | / | / */ -1.0f, +0.0f, +0.0f, -1.0f, +0.0f, +0.0f, +1.0f, +0.0f, +0.0f, +1.0f, +0.0f, +0.0f, +1.0f, +0.0f, +0.0f, +1.0f, +0.0f, +0.0f };
/* |/ 2|/ */ // The associated indices.
/* 3*------------* */ const uint16 indices[]={ 0, 2, 1, 0, 3, 2, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 15, 14, 12, 14, 13, 16, 17, 18, 16, 18, 19, 20, 23, 22, 20, 22, 21 };
const float tangents[] = { +1.0f, 0.0f, 0.0f, +1.0f, 0.0f, 0.0f, +1.0f, 0.0f, 0.0f, +1.0f, 0.0f, 0.0f, +1.0f, 0.0f, 0.0f, +1.0f, 0.0f, 0.0f,
+1.0f, 0.0f, 0.0f, +1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
+1.0f, 0.0f, 0.0f, +1.0f, 0.0f, 0.0f, +1.0f, 0.0f, 0.0f, +1.0f, 0.0f, 0.0f, 0.0f, 0.0f,+1.0f, 0.0f, 0.0f,+1.0f,
0.0f, 0.0f,+1.0f, 0.0f, 0.0f,+1.0f, 0.0f, 0.0f,-1.0f, 0.0f, 0.0f,-1.0f, 0.0f, 0.0f,-1.0f, 0.0f, 0.0f,-1.0f };
float tex_coords[] ={ 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f };
const vulkan::VertexShaderModule *vsm=mtl->GetVertexShaderModule();
vulkan::Renderable *render_obj=nullptr;
{
const int vertex_binding=vsm->GetStageInputBinding("Vertex");
if(vertex_binding==-1)
return(nullptr);
VB3f *vertex=new VB3f(24,points);
render_obj=mtl->CreateRenderable(vertex->GetCount());
render_obj->Set(vertex_binding,db->CreateVBO(vertex));
render_obj->SetBoundingBox(vertex->GetAABB());
delete vertex;
}
const int normal_binding=vsm->GetStageInputBinding("Normal");
if(normal_binding!=-1)
{
VB3f *normal=new VB3f(24,normals);
render_obj->Set(normal_binding,db->CreateVBO(normal));
delete normal;
}
const int tagent_binding=vsm->GetStageInputBinding("Tangent");
if(tagent_binding!=-1)
{
VB3f *tangent=new VB3f(24,tangents);
render_obj->Set(tagent_binding,db->CreateVBO(tangent));
delete tangent;
}
const int texcoord_binding=vsm->GetStageInputBinding("TexCoord");
if(texcoord_binding!=-1)
{
float *tc=tex_coords;
for(uint i=0;i<24;i++)
{
(*tc)*=cci->tile.x;++tc;
(*tc)*=cci->tile.y;++tc;
}
VB2f *tex_coord=new VB2f(24,tex_coords);
render_obj->Set(texcoord_binding,db->CreateVBO(tex_coord));
delete tex_coord;
}
render_obj->Set(db->CreateIBO16(6*2*3,indices));
db->Add(render_obj);
2019-05-27 22:48:01 +08:00
return(render_obj);
}
2019-06-17 10:37:59 +08:00
template<typename T> vulkan::IndexBuffer *CreateSphereIndices(vulkan::IndexBuffer *ibo,uint numberParallels,const uint numberSlices)
2019-05-27 22:48:01 +08:00
{
2019-06-17 10:37:59 +08:00
T *tp=(T *)ibo->Map();
for (uint i = 0; i < numberParallels; i++)
{
for (uint j = 0; j < numberSlices; j++)
{
*tp= i * (numberSlices + 1) + j; ++tp;
*tp=(i + 1) * (numberSlices + 1) + j; ++tp;
*tp=(i + 1) * (numberSlices + 1) + (j + 1); ++tp;
*tp= i * (numberSlices + 1) + j; ++tp;
*tp=(i + 1) * (numberSlices + 1) + (j + 1); ++tp;
*tp= i * (numberSlices + 1) + (j + 1); ++tp;
}
}
ibo->Unmap();
return ibo;
}
namespace
{
void glusQuaternionRotateRyf(float quaternion[4], const float angle)
{
float halfAngleRadian = hgl_ang2rad(angle) * 0.5f;
quaternion[0] = 0.0f;
quaternion[1] = sinf(halfAngleRadian);
quaternion[2] = 0.0f;
quaternion[3] = cosf(halfAngleRadian);
}
void glusQuaternionGetMatrix4x4f(float matrix[16], const float quaternion[4])
{
float x = quaternion[0];
float y = quaternion[1];
float z = quaternion[2];
float w = quaternion[3];
matrix[0] = 1.0f - 2.0f * y * y - 2.0f * z * z;
matrix[1] = 2.0f * x * y + 2.0f * w * z;
matrix[2] = 2.0f * x * z - 2.0f * w * y;
matrix[3] = 0.0f;
matrix[4] = 2.0f * x * y - 2.0f * w * z;
matrix[5] = 1.0f - 2.0f * x * x - 2.0f * z * z;
matrix[6] = 2.0f * y * z + 2.0f * w * x;
matrix[7] = 0.0f;
matrix[8] = 2.0f * x * z + 2.0f * w * y;
matrix[9] = 2.0f * y * z - 2.0f * w * x;
matrix[10] = 1.0f - 2.0f * x * x - 2.0f * y * y;
matrix[11] = 0.0f;
matrix[12] = 0.0f;
matrix[13] = 0.0f;
matrix[14] = 0.0f;
matrix[15] = 1.0f;
}
void glusMatrix4x4MultiplyVector3f(float result[3], const float matrix[16], const float vector[3])
{
int i;
2019-05-27 22:48:01 +08:00
2019-06-17 10:37:59 +08:00
float temp[3];
2019-05-27 22:48:01 +08:00
2019-06-17 10:37:59 +08:00
for (i = 0; i < 3; i++)
{
temp[i] = matrix[i] * vector[0] + matrix[4 + i] * vector[1] + matrix[8 + i] * vector[2];
}
for (i = 0; i < 3; i++)
{
result[i] = temp[i];
}
}
}
/**
* ,0,0,01
* @param numberSlices
* @return
*/
vulkan::Renderable *CreateRenderableSphere(SceneDB *db,vulkan::Material *mtl,const uint numberSlices)
{
2019-05-27 22:48:01 +08:00
const vulkan::VertexShaderModule *vsm=mtl->GetVertexShaderModule();
vulkan::Renderable *render_obj=nullptr;
2019-06-17 10:37:59 +08:00
const int vertex_binding=vsm->GetStageInputBinding("Vertex");
if(vertex_binding==-1)
return(nullptr);
uint numberParallels = (numberSlices+1) / 2;
uint numberVertices = (numberParallels + 1) * (numberSlices + 1);
uint numberIndices = numberParallels * numberSlices * 6;
const double angleStep = double(2.0f * HGL_PI) / ((double) numberSlices);
// used later to help us calculating tangents vectors
float helpVector[3] = { 1.0f, 0.0f, 0.0f };
float helpQuaternion[4];
float helpMatrix[16];
float tex_x;
VB3f *vertex =new VB3f(numberVertices);
VB3f *normal =nullptr;
VB3f *tangent =nullptr;
VB2f *tex_coord =nullptr;
render_obj=mtl->CreateRenderable(vertex->GetCount());
const int normal_binding=vsm->GetStageInputBinding("Normal");
const int tangent_binding=vsm->GetStageInputBinding("Tangent");
const int texcoord_binding=vsm->GetStageInputBinding("TexCoord");
float *vp=(float *)vertex->Begin();
float *np=nullptr;
float *tp=nullptr;
float *tc=nullptr;
if(normal_binding !=-1){normal =new VB3f(numberVertices);np=(float *)normal->Begin();}
if(tangent_binding !=-1){tangent =new VB3f(numberVertices);tp=(float *)tangent->Begin();}
if(texcoord_binding !=-1){tex_coord =new VB2f(numberVertices);tc=(float *)tex_coord->Begin();}
for (uint i = 0; i < numberParallels + 1; i++)
2019-05-27 22:48:01 +08:00
{
2019-06-17 10:37:59 +08:00
for (uint j = 0; j < numberSlices + 1; j++)
{
float x=sin(angleStep * (double) i) * sin(angleStep * (double) j);
float y=cos(angleStep * (double) i);
float z=sin(angleStep * (double) i) * cos(angleStep * (double) j);
2019-05-27 22:48:01 +08:00
2019-06-17 10:37:59 +08:00
*vp=x;++vp;
*vp=y;++vp;
*vp=z;++vp;
2019-05-27 22:48:01 +08:00
2019-06-17 10:37:59 +08:00
if(normal)
{
*np=x;++np;
*np=y;++np;
*np=z;++np;
}
2019-05-27 22:48:01 +08:00
2019-06-17 10:37:59 +08:00
if(tex_coord)
{
tex_x=(float) j / (float) numberSlices;
2019-05-27 22:48:01 +08:00
2019-06-17 10:37:59 +08:00
*tc=tex_x;++tc;
*tc=1.0f - (float) i / (float) numberParallels;++tc;
if(tangent)
{
// use quaternion to get the tangent vector
glusQuaternionRotateRyf(helpQuaternion, 360.0f * tex_x);
glusQuaternionGetMatrix4x4f(helpMatrix, helpQuaternion);
glusMatrix4x4MultiplyVector3f(tp, helpMatrix, helpVector);
tp+=3;
}
}
}
}
if(tex_coord){tex_coord ->End();render_obj->Set(texcoord_binding, db->CreateVBO(tex_coord ));delete tex_coord;}
if(tangent ){tangent ->End();render_obj->Set(tangent_binding, db->CreateVBO(tangent ));delete tangent; }
if(normal ){normal ->End();render_obj->Set(normal_binding, db->CreateVBO(normal ));delete normal; }
vertex->End();
render_obj->Set(vertex_binding,db->CreateVBO(vertex));
render_obj->SetBoundingBox(vertex->GetAABB());
delete vertex;
{
uint indices_number=numberParallels * numberSlices * 6;
if(numberVertices<=0xffff)
render_obj->Set(CreateSphereIndices<uint16>(db->CreateIBO16(indices_number),numberParallels,numberSlices));
else
render_obj->Set(CreateSphereIndices<uint32>(db->CreateIBO32(indices_number),numberParallels,numberSlices));
2019-05-27 22:48:01 +08:00
}
return render_obj;
}
//vulkan::Renderable *CreateSphere(SceneDB *db,vulkan::Material *mtl,const SphereCreateInfo *sci)
//{
//}
2019-05-24 19:28:27 +08:00
}//namespace graph
}//namespace hgl