1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
|
/*****
* drawbezierpatch.cc
* Author: John C. Bowman
*
* Render a Bezier curve.
*****/
#include "bezierpatch.h"
#include "beziercurve.h"
namespace camp {
#ifdef HAVE_GL
void BezierCurve::init(double res)
{
this->res=res;
res2=res*res;
MaterialIndex=materialIndex;
}
inline triple normal(triple bP, triple bPP)
{
return dot(bP,bP)*bPP-dot(bP,bPP)*bP;
}
void BezierCurve::render(const triple *p, bool straight)
{
triple p0=p[0];
triple p3=p[3];
triple n0,n1;
if(straight) {
n0=n1=triple(0.0,0.0,1.0);
} else {
triple p1=p[1];
triple p2=p[2];
n0=normal(p1-p0,p0+p2-2.0*p1);
n1=normal(p3-p2,p3+p1-2.0*p2);
}
GLuint i0=data.vertex(p0,n0);
GLuint i3=data.vertex(p3,n1);
if(straight) {
std::vector<GLuint> &q=data.indices;
q.push_back(i0);
q.push_back(i3);
} else
render(p,i0,i3);
append();
}
// Use a uniform partition to draw a Bezier curve.
// p is an array of 4 triples representing the control points.
// Ii are the vertex 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(Straightness(p0,p1,p2,p3) < res2) { // Segment is flat
triple P[]={p0,p3};
if(!offscreen(2,P)) {
std::vector<GLuint> &q=data.indices;
q.push_back(I0);
q.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};
triple n0=normal(bezierPh(p0,p1,p2,p3),bezierPPh(p0,p1,p2,p3));
GLuint i0=data.vertex(m5,n0);
render(s0,I0,i0);
render(s1,i0,I1);
}
}
#endif
} //namespace camp
|