summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/bezierpatch.h
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/utils/asymptote/bezierpatch.h')
-rw-r--r--Build/source/utils/asymptote/bezierpatch.h225
1 files changed, 225 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/bezierpatch.h b/Build/source/utils/asymptote/bezierpatch.h
new file mode 100644
index 00000000000..b4159fe3ac7
--- /dev/null
+++ b/Build/source/utils/asymptote/bezierpatch.h
@@ -0,0 +1,225 @@
+/*****
+ * bezierpatch.h
+ * Authors: John C. Bowman and Jesse Frohlich
+ *
+ * Render Bezier patches and triangles.
+ *****/
+
+#ifndef BEZIERPATCH_H
+#define BEZIERPATCH_H
+
+#include "drawelement.h"
+
+namespace camp {
+
+#ifdef HAVE_GL
+
+struct BezierPatch
+{
+ vertexBuffer data;
+
+ bool transparent;
+ bool color;
+ double epsilon;
+ double Epsilon;
+ double res2;
+ double Res2; // Reduced resolution for Bezier triangles flatness test.
+ typedef GLuint (vertexBuffer::*vertexFunction)(const triple &v,
+ const triple& n);
+ vertexFunction pvertex;
+ bool Onscreen;
+
+ void init(double res);
+
+ triple normal(triple left3, triple left2, triple left1, triple middle,
+ triple right1, triple right2, triple right3) {
+ triple lp=3.0*(left1-middle);
+ triple rp=3.0*(right1-middle);
+
+ triple n=cross(rp,lp);
+ if(abs2(n) > epsilon)
+ return n;
+
+ triple lpp=bezierPP(middle,left1,left2);
+ triple rpp=bezierPP(middle,right1,right2);
+
+ n=cross(rpp,lp)+cross(rp,lpp);
+ if(abs2(n) > epsilon)
+ return n;
+
+ triple lppp=bezierPPP(middle,left1,left2,left3);
+ triple rppp=bezierPPP(middle,right1,right2,right3);
+
+ n=cross(rpp,lpp)+cross(rppp,lp)+cross(rp,lppp);
+ if(abs2(n) > epsilon)
+ return n;
+
+ n=cross(rppp,lpp)+cross(rpp,lppp);
+ if(abs2(n) > epsilon)
+ return n;
+
+ return cross(rppp,lppp);
+ }
+
+ // Return the differential of the Bezier curve p0,p1,p2,p3 at 0
+ triple differential(triple p0, triple p1, triple p2, triple p3) {
+ triple p=p1-p0;
+ if(abs2(p) > epsilon)
+ return p;
+
+ p=bezierPP(p0,p1,p2);
+ if(abs2(p) > epsilon)
+ return p;
+
+ return bezierPPP(p0,p1,p2,p3);
+ }
+
+ // Determine the flatness of a Bezier patch.
+ pair Distance(const triple *p) {
+ triple p0=p[0];
+ triple p3=p[3];
+ triple p12=p[12];
+ triple p15=p[15];
+
+ // Check the horizontal flatness.
+ double h=Flatness(p0,p12,p3,p15);
+ // Check straightness of the horizontal edges and interior control curves.
+ h=max(h,Straightness(p0,p[4],p[8],p12));
+ h=max(h,Straightness(p[1],p[5],p[9],p[13]));
+ h=max(h,Straightness(p[2],p[6],p[10],p[14]));
+ h=max(h,Straightness(p3,p[7],p[11],p15));
+
+ // Check the vertical flatness.
+ double v=Flatness(p0,p3,p12,p15);
+ // Check straightness of the vertical edges and interior control curves.
+ v=max(v,Straightness(p0,p[1],p[2],p3));
+ v=max(v,Straightness(p[4],p[5],p[6],p[7]));
+ v=max(v,Straightness(p[8],p[9],p[10],p[11]));
+ v=max(v,Straightness(p12,p[13],p[14],p15));
+
+ return pair(h,v);
+ }
+
+ struct Split3 {
+ triple m0,m2,m3,m4,m5;
+ Split3() {}
+ Split3(triple z0, triple c0, triple c1, triple z1) {
+ m0=0.5*(z0+c0);
+ triple m1=0.5*(c0+c1);
+ m2=0.5*(c1+z1);
+ m3=0.5*(m0+m1);
+ m4=0.5*(m1+m2);
+ m5=0.5*(m3+m4);
+ }
+ };
+
+ // Approximate bounds by bounding box of control polyhedron.
+ bool offscreen(size_t n, const triple *v) {
+ if(bbox2(n,v).offscreen()) {
+ Onscreen=false;
+ return true;
+ }
+ return false;
+ }
+
+ virtual void render(const triple *p, bool straight, GLfloat *c0=NULL);
+ void render(const triple *p,
+ GLuint I0, GLuint I1, GLuint I2, GLuint I3,
+ triple P0, triple P1, triple P2, triple P3,
+ bool flat0, bool flat1, bool flat2, bool flat3,
+ GLfloat *C0=NULL, GLfloat *C1=NULL, GLfloat *C2=NULL,
+ GLfloat *C3=NULL);
+
+ void append() {
+ if(transparent)
+ transparentData.Append(data);
+ else {
+ if(color)
+ colorData.Append(data);
+ else
+ materialData.append(data);
+ }
+ }
+
+ virtual void notRendered() {
+ if(transparent)
+ transparentData.rendered=false;
+ else {
+ if(color)
+ colorData.rendered=false;
+ else
+ materialData.rendered=false;
+ }
+ }
+
+ void queue(const triple *g, bool straight, double ratio, bool Transparent,
+ GLfloat *colors=NULL) {
+ data.clear();
+ Onscreen=true;
+ transparent=Transparent;
+ color=colors;
+ notRendered();
+ init(pixel*ratio);
+ render(g,straight,colors);
+ }
+
+};
+
+struct BezierTriangle : public BezierPatch {
+public:
+ BezierTriangle() : BezierPatch() {}
+
+ double Distance(const triple *p) {
+ triple p0=p[0];
+ triple p6=p[6];
+ triple p9=p[9];
+
+ // Check how far the internal point is from the centroid of the vertices.
+ double d=abs2((p0+p6+p9)*third-p[4]);
+
+ // Determine how straight the edges are.
+ d=max(d,Straightness(p0,p[1],p[3],p6));
+ d=max(d,Straightness(p0,p[2],p[5],p9));
+ return max(d,Straightness(p6,p[7],p[8],p9));
+ }
+
+ void render(const triple *p, bool straight, GLfloat *c0=NULL);
+ void render(const triple *p,
+ GLuint I0, GLuint I1, GLuint I2,
+ triple P0, triple P1, triple P2,
+ bool flat0, bool flat1, bool flat2,
+ GLfloat *C0=NULL, GLfloat *C1=NULL, GLfloat *C2=NULL);
+};
+
+struct Triangles : public BezierPatch {
+public:
+ Triangles() : BezierPatch() {}
+
+ void queue(size_t nP, const triple* P, size_t nN, const triple* N,
+ size_t nC, const prc::RGBAColour* C, size_t nI,
+ const uint32_t (*PI)[3], const uint32_t (*NI)[3],
+ const uint32_t (*CI)[3], bool transparent);
+
+ void append() {
+ if(transparent)
+ transparentData.Append(data);
+ else
+ triangleData.Append(data);
+ }
+
+ void notRendered() {
+ if(transparent)
+ transparentData.rendered=false;
+ else
+ triangleData.rendered=false;
+ }
+
+};
+
+extern void sortTriangles();
+
+#endif
+
+} //namespace camp
+
+#endif