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
|
/*****
* drawbezierpatch.cc
* Author: John C. Bowman
*
* Render a Bezier curve.
*****/
#include "beziercurve.h"
namespace camp {
#ifdef HAVE_GL
std::vector<GLfloat> BezierCurve::buffer;
std::vector<GLuint> BezierCurve::indices;
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;
buffer.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()
{
size_t stride=3*sizeof(GLfloat);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3,GL_FLOAT,stride,&buffer[0]);
glDrawElements(GL_LINES,indices.size(),GL_UNSIGNED_INT,&indices[0]);
glDisableClientState(GL_VERTEX_ARRAY);
clear();
}
#endif
} //namespace camp
|