summaryrefslogtreecommitdiff
path: root/graphics/asymptote/beziercurve.cc
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/asymptote/beziercurve.cc')
-rw-r--r--graphics/asymptote/beziercurve.cc181
1 files changed, 181 insertions, 0 deletions
diff --git a/graphics/asymptote/beziercurve.cc b/graphics/asymptote/beziercurve.cc
new file mode 100644
index 0000000000..ccf3267e6e
--- /dev/null
+++ b/graphics/asymptote/beziercurve.cc
@@ -0,0 +1,181 @@
+/*****
+ * drawbezierpatch.cc
+ * Author: John C. Bowman
+ *
+ * Render a Bezier curve.
+ *****/
+
+#include "bezierpatch.h"
+#include "beziercurve.h"
+
+namespace camp {
+
+#ifdef HAVE_GL
+
+std::vector<vertexData1> BezierCurve::vertexbuffer;
+std::vector<GLuint> BezierCurve::indices;
+
+std::vector<pixelData> Pixel::vertexbuffer;
+
+GLuint BezierCurve::vertsBufferIndex;
+GLuint BezierCurve::elemBufferIndex;
+
+void BezierCurve::init(double res, const triple& Min, const triple& Max)
+{
+ this->res=res;
+ res2=res*res;
+ this->Min=Min;
+ this->Max=Max;
+
+ const size_t nbuffer=10000;
+ vertexbuffer.reserve(nbuffer);
+ indices.reserve(nbuffer);
+}
+
+// Use a uniform partition to draw a Bezier patch.
+// p is an array of 4 triples representing the control points.
+// Ii are the vertices indices.
+void BezierCurve::render(const triple *p, GLuint I0, GLuint I1)
+{
+ triple p0=p[0];
+ triple p1=p[1];
+ triple p2=p[2];
+ triple p3=p[3];
+ if(Distance1(p0,p1,p2,p3) < res2) { // Segment is flat
+ triple P[]={p0,p3};
+ if(!offscreen(2,P)) {
+ indices.push_back(I0);
+ indices.push_back(I1);
+ }
+ } else { // Segment is not flat
+ if(offscreen(4,p)) return;
+ triple m0=0.5*(p0+p1);
+ triple m1=0.5*(p1+p2);
+ triple m2=0.5*(p2+p3);
+ triple m3=0.5*(m0+m1);
+ triple m4=0.5*(m1+m2);
+ triple m5=0.5*(m3+m4);
+
+ triple s0[]={p0,m0,m3,m5};
+ triple s1[]={m5,m4,m2,p3};
+
+ GLuint i0=vertex(m5);
+
+ render(s0,I0,i0);
+ render(s1,i0,I1);
+ }
+}
+
+void BezierCurve::render(const triple *p, bool straight)
+{
+ GLuint i0=vertex(p[0]);
+ GLuint i3=vertex(p[3]);
+
+ if(straight) {
+ indices.push_back(i0);
+ indices.push_back(i3);
+ } else
+ render(p,i0,i3);
+}
+
+void BezierCurve::draw()
+{
+ if(indices.size() == 0)
+ return;
+
+ const size_t size=sizeof(GLfloat);
+ static const size_t bytestride=sizeof(vertexData1);
+
+ GLuint vao;
+ glGenVertexArrays(1,&vao);
+ glBindVertexArray(vao);
+ createBuffers();
+
+ glBindBuffer(GL_ARRAY_BUFFER,vertsBufferIndex);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,elemBufferIndex);
+
+ camp::setUniforms(noNormalShader);
+
+ const GLint posAttrib=glGetAttribLocation(noNormalShader, "position");
+ const GLint materialAttrib=glGetAttribLocation(noNormalShader,"material");
+
+ glVertexAttribPointer(posAttrib,3,GL_FLOAT,GL_FALSE,bytestride,(void *) 0);
+ glEnableVertexAttribArray(posAttrib);
+
+ glVertexAttribIPointer(materialAttrib,1,GL_INT,bytestride,(void *) (3*size));
+ glEnableVertexAttribArray(materialAttrib);
+
+ glFlush(); // Workaround broken MSWindows drivers for Intel GPU
+ glDrawElements(GL_LINES,indices.size(),GL_UNSIGNED_INT,(void*)(0));
+
+ glDisableVertexAttribArray(posAttrib);
+ glDisableVertexAttribArray(materialAttrib);
+
+ deleteUniforms();
+
+ glBindBuffer(GL_ARRAY_BUFFER,0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
+
+ glBindVertexArray(0);
+ glDeleteVertexArrays(1,&vao);
+
+ glDeleteBuffers(1,&vertsBufferIndex);
+ glDeleteBuffers(1,&elemBufferIndex);
+}
+
+void Pixel::queue(const triple& p, double width)
+{
+ vertex(p,width);
+}
+
+void Pixel::draw()
+{
+ if(vertexbuffer.size() == 0)
+ return;
+
+ const size_t size=sizeof(GLfloat);
+ static const size_t bytestride=sizeof(pixelData);
+
+ GLuint vbo;
+ glGenBuffers(1,&vbo);
+
+ GLuint vao;
+ glGenVertexArrays(1,&vao);
+ glBindVertexArray(vao);
+
+ glBindBuffer(GL_ARRAY_BUFFER,vbo);
+ glBufferData(GL_ARRAY_BUFFER,bytestride*vertexbuffer.size(),
+ vertexbuffer.data(),GL_STATIC_DRAW);
+
+ camp::setUniforms(pixelShader);
+
+ const GLint posAttrib=glGetAttribLocation(pixelShader, "position");
+ const GLint materialAttrib=glGetAttribLocation(pixelShader,"material");
+ const GLint widthAttrib=glGetAttribLocation(pixelShader,"width");
+
+ glVertexAttribPointer(posAttrib,3,GL_FLOAT,GL_FALSE,bytestride,(void*)(0));
+ glEnableVertexAttribArray(posAttrib);
+
+ glVertexAttribIPointer(materialAttrib,1,GL_INT,bytestride,(void *) (3*size));
+ glEnableVertexAttribArray(materialAttrib);
+
+ glVertexAttribPointer(widthAttrib,1,GL_FLOAT,GL_FALSE,bytestride,(void *) (4*size));
+ glEnableVertexAttribArray(widthAttrib);
+
+ glDrawArrays(GL_POINTS,0,vertexbuffer.size());
+
+ glDisableVertexAttribArray(posAttrib);
+ glDisableVertexAttribArray(materialAttrib);
+ glDisableVertexAttribArray(widthAttrib);
+
+ deleteUniforms();
+
+ glBindBuffer(GL_ARRAY_BUFFER,0);
+
+ glBindVertexArray(0);
+ glDeleteVertexArrays(1,&vao);
+}
+
+#endif
+
+} //namespace camp