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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
/*
* Copyright © 2010 Ian D. Romanick
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "glu3.h"
#include "revolve.h"
#include "mesh.h"
/**
* Call-back function for sphere generation routine
*/
static void sphere_revolve_cb(void *data,
const GLUvec4 *position,
const GLUvec4 *normal,
const GLUvec4 *tangent,
const GLUvec4 *uv,
unsigned count);
/**
* GLUsphereProducer decorator to implement call-backs
*
* To generate the sphere data, the \c GLUsphereProducer class interfaces with
* a C functions that uses a call-back mechanism. This call-backs is
* analogous to \c vertex_batch method that \c GLUshapeConsumer subclasses
* will provide.
*
* However, this method is \c protected. As a result the non-class call-back
* functions cannot call this method unless it is a \c friend function. It is
* undesireable to expose this implementation detail in the application-facing
* header file. This can be worked around by creating a dummy subclass of \c
* GLUshapeConsumer that only contains the \c friend function declaration.
* Pointers to \c GLUshapeConsumer objects can be cast to pointers to
* \c GLUconsumerFriend objects without side-effect.
*
* This is arguably a mis-use of the "decorator" pattern, but it is the most
* efficient way to do this.
*/
class GLUconsumerFriend : public GLUshapeConsumer {
friend void sphere_revolve_cb(void *data,
const GLUvec4 *position,
const GLUvec4 *normal,
const GLUvec4 *tangent,
const GLUvec4 *uv,
unsigned count);
};
GLUsphereProducer::GLUsphereProducer(GLdouble radius, GLint slices,
GLint stacks)
: GLUmeshProducer(slices, stacks + 1, stacks + 1)
{
this->radius = radius;
this->rows = (slices < 4) ? 4 : (unsigned) slices;
this->columns = (stacks < 3) ? 4 : (unsigned) (stacks + 1);
this->width = this->columns;
}
unsigned
GLUsphereProducer::vertex_count(void) const
{
/* Each line of vertices from the north pole to the south pole consists
* of (stacks+1) vertices. There are a total of (slices+1) of these
* lines of vertices.
*/
return (this->rows + 1) * (this->columns);
}
static void
sphere_revolve_cb(void *data, const GLUvec4 *position, const GLUvec4 *normal,
const GLUvec4 *tangent, const GLUvec4 *uv, unsigned count)
{
GLUconsumerFriend *c = (GLUconsumerFriend *) data;
c->vertex_batch(position, normal, tangent, uv, count);
}
void
GLUsphereProducer::generate(GLUshapeConsumer *consumer) const
{
GLUvec4 data[4 * 16];
cb_buffer buf;
if (consumer->vertex_count == 0) {
cb_buffer_init(&buf, &data[0], &data[16], &data[32],
&data[48], 16);
} else {
cb_buffer_init(&buf, consumer->position, consumer->normal,
consumer->tangent, consumer->uv,
consumer->vertex_count);
}
generate_sphere(this->radius, this->rows, this->columns - 1,
this->normals_point_out,
sphere_revolve_cb, (void *) consumer, &buf);
GLUmeshProducer::generate(consumer);
}
|