/***** * glrender.h * Render 3D Bezier paths and surfaces. *****/ #ifndef GLRENDER_H #define GLRENDER_H #include "common.h" #include "triple.h" #include "pen.h" #ifdef HAVE_LIBGLM #define GLM_ENABLE_EXPERIMENTAL #include #include #include #include #endif #ifdef HAVE_GL #include #include #ifdef __APPLE__ #define GL_SILENCE_DEPRECATION #include #ifdef HAVE_LIBGLUT #include #ifndef GLUT_3_2_CORE_PROFILE #undef HAVE_GL #endif #endif #ifdef HAVE_LIBOSMESA #ifndef APIENTRY #define APIENTRY #endif #ifndef GLAPI #define GLAPI #endif #define GLEW_OSMESA #include #endif #else #ifdef HAVE_LIBGLUT #include #endif #ifdef HAVE_LIBOSMESA #ifndef APIENTRY #define APIENTRY #endif #ifndef GLAPI #define GLAPI #endif #include #endif #endif #else typedef unsigned int GLuint; typedef int GLint; typedef float GLfloat; typedef double GLdouble; typedef unsigned char GLubyte; typedef unsigned int GLenum; #define GL_POINTS 0x0000 #define GL_LINES 0x0001 #define GL_TRIANGLES 0x0004 #endif #ifdef HAVE_LIBGLM #include "material.h" #endif namespace camp { class picture; inline void store(GLfloat *f, double *C) { f[0]=C[0]; f[1]=C[1]; f[2]=C[2]; } inline void store(GLfloat *control, const camp::triple& v) { control[0]=v.getx(); control[1]=v.gety(); control[2]=v.getz(); } inline void store(GLfloat *control, const triple& v, double weight) { control[0]=v.getx()*weight; control[1]=v.gety()*weight; control[2]=v.getz()*weight; control[3]=weight; } } namespace gl { extern bool outlinemode; extern bool wireframeMode; extern bool orthographic; // 2D bounds extern double xmin,xmax; extern double ymin,ymax; // 3D bounds extern double Xmin,Xmax; extern double Ymin,Ymax; extern double Zmin,Zmax; extern int fullWidth,fullHeight; extern double Zoom0; extern double Angle; extern camp::pair Shift; extern camp::pair Margin; extern camp::triple *Lights; extern size_t nlights; extern double *Diffuse; extern double Background[4]; struct projection { public: bool orthographic; camp::triple camera; camp::triple up; camp::triple target; double zoom; double angle; camp::pair viewportshift; projection(bool orthographic=false, camp::triple camera=0.0, camp::triple up=0.0, camp::triple target=0.0, double zoom=0.0, double angle=0.0, camp::pair viewportshift=0.0) : orthographic(orthographic), camera(camera), up(up), target(target), zoom(zoom), angle(angle), viewportshift(viewportshift) {} }; #ifdef HAVE_GL extern GLuint ubo; GLuint initHDR(); #endif projection camera(bool user=true); struct GLRenderArgs { string prefix; camp::picture* pic; string format; double width; double height; double angle; double zoom; camp::triple m; camp::triple M; camp::pair shift; camp::pair margin; double *t; double *tup; double *background; size_t nlights; camp::triple *lights; double *diffuse; double *specular; bool view; }; void glrender(GLRenderArgs const& args, int oldpid=0); extern const double *dprojView; extern const double *dView; extern double BBT[9]; extern double T[16]; extern bool format3dWait; } namespace camp { struct Billboard { double cx,cy,cz; void init(const triple& center) { cx=center.getx(); cy=center.gety(); cz=center.getz(); } triple transform(const triple& v) const { double x=v.getx()-cx; double y=v.gety()-cy; double z=v.getz()-cz; return triple(x*gl::BBT[0]+y*gl::BBT[3]+z*gl::BBT[6]+cx, x*gl::BBT[1]+y*gl::BBT[4]+z*gl::BBT[7]+cy, x*gl::BBT[2]+y*gl::BBT[5]+z*gl::BBT[8]+cz); } }; extern Billboard BB; #ifdef HAVE_LIBGLM typedef mem::map MaterialMap; extern std::vector materials; extern MaterialMap materialMap; extern size_t materialIndex; extern int MaterialIndex; extern const size_t Nbuffer; // Initial size of 2D dynamic buffers extern const size_t nbuffer; // Initial size of 0D & 1D dynamic buffers class vertexData { public: GLfloat position[3]; GLfloat normal[3]; GLint material; vertexData() {}; vertexData(const triple& v, const triple& n) { position[0]=v.getx(); position[1]=v.gety(); position[2]=v.getz(); normal[0]=n.getx(); normal[1]=n.gety(); normal[2]=n.getz(); material=MaterialIndex; } }; class VertexData { public: GLfloat position[3]; GLfloat normal[3]; GLint material; GLfloat color[4]; VertexData() {}; VertexData(const triple& v, const triple& n) { position[0]=v.getx(); position[1]=v.gety(); position[2]=v.getz(); normal[0]=n.getx(); normal[1]=n.gety(); normal[2]=n.getz(); material=MaterialIndex; } VertexData(const triple& v, const triple& n, GLfloat *c) { position[0]=v.getx(); position[1]=v.gety(); position[2]=v.getz(); normal[0]=n.getx(); normal[1]=n.gety(); normal[2]=n.getz(); material=MaterialIndex; color[0]=c[0]; color[1]=c[1]; color[2]=c[2]; color[3]=c[3]; } }; class vertexData0 { public: GLfloat position[3]; GLfloat width; GLint material; vertexData0() {}; vertexData0(const triple& v, double width) : width(width) { position[0]=v.getx(); position[1]=v.gety(); position[2]=v.getz(); material=MaterialIndex; } }; class vertexBuffer { public: GLenum type; GLuint verticesBuffer; GLuint VerticesBuffer; GLuint vertices0Buffer; GLuint indicesBuffer; GLuint materialsBuffer; std::vector vertices; std::vector Vertices; std::vector vertices0; std::vector indices; std::vector materials; std::vector materialTable; bool rendered; // Are all patches in this buffer fully rendered? bool partial; // Does buffer contain incomplete data? vertexBuffer(GLint type=GL_TRIANGLES) : type(type), verticesBuffer(0), VerticesBuffer(0), vertices0Buffer(0), indicesBuffer(0), materialsBuffer(0), rendered(false), partial(false) {} void clear() { vertices.clear(); Vertices.clear(); vertices0.clear(); indices.clear(); materials.clear(); materialTable.clear(); } void reserve0() { vertices0.reserve(nbuffer); } void reserve() { vertices.reserve(Nbuffer); indices.reserve(Nbuffer); } void Reserve() { Vertices.reserve(Nbuffer); indices.reserve(Nbuffer); } // Store the vertex v and its normal vector n. GLuint vertex(const triple &v, const triple& n) { size_t nvertices=vertices.size(); vertices.push_back(vertexData(v,n)); return nvertices; } // Store the vertex v and its normal vector n, without an explicit color. GLuint tvertex(const triple &v, const triple& n) { size_t nvertices=Vertices.size(); Vertices.push_back(VertexData(v,n)); return nvertices; } // Store the vertex v, its normal vector n, and colors c. GLuint Vertex(const triple &v, const triple& n, GLfloat *c) { size_t nvertices=Vertices.size(); Vertices.push_back(VertexData(v,n,c)); return nvertices; } // Store the pixel v and its width. GLuint vertex0(const triple &v, double width) { size_t nvertices=vertices0.size(); vertices0.push_back(vertexData0(v,width)); return nvertices; } // append array b onto array a with offset void appendOffset(std::vector& a, const std::vector& b, size_t offset) { size_t n=a.size(); size_t m=b.size(); a.resize(n+m); for(size_t i=0; i < m; ++i) a[n+i]=b[i]+offset; } void append(const vertexBuffer& b) { appendOffset(indices,b.indices,vertices.size()); vertices.insert(vertices.end(),b.vertices.begin(),b.vertices.end()); } void Append(const vertexBuffer& b) { appendOffset(indices,b.indices,Vertices.size()); Vertices.insert(Vertices.end(),b.Vertices.begin(),b.Vertices.end()); } void append0(const vertexBuffer& b) { appendOffset(indices,b.indices,vertices0.size()); vertices0.insert(vertices0.end(),b.vertices0.begin(),b.vertices0.end()); } }; extern vertexBuffer material0Data; // pixels extern vertexBuffer material1Data; // material Bezier curves extern vertexBuffer materialData; // material Bezier patches & triangles extern vertexBuffer colorData; // colored Bezier patches & triangles extern vertexBuffer triangleData; // opaque indexed triangles extern vertexBuffer transparentData; // transparent patches & triangles void drawBuffer(vertexBuffer& data, GLint shader, bool color=false); void drawBuffers(); void clearMaterials(); void clearCenters(); typedef void draw_t(); void setMaterial(vertexBuffer& data, draw_t *draw); void drawMaterial0(); void drawMaterial1(); void drawMaterial(); void drawColor(); void drawTriangle(); void drawTransparent(); #endif } #endif