1 | #ifndef MXGEOPRIMS_INCLUDED // -*- C++ -*-
|
---|
2 | #define MXGEOPRIMS_INCLUDED
|
---|
3 | #if !defined(__GNUC__)
|
---|
4 | # pragma once
|
---|
5 | #endif
|
---|
6 |
|
---|
7 | /************************************************************************
|
---|
8 |
|
---|
9 | MxGeoPrims
|
---|
10 |
|
---|
11 | Copyright (C) 1998 Michael Garland. See "COPYING.txt" for details.
|
---|
12 |
|
---|
13 | $Id: MxGeoPrims.h,v 1.1 2002/09/24 16:53:54 wimmer Exp $
|
---|
14 |
|
---|
15 | ************************************************************************/
|
---|
16 |
|
---|
17 | #include "MxMath.h"
|
---|
18 |
|
---|
19 | //
|
---|
20 | // Standard names for ID types
|
---|
21 | //
|
---|
22 | typedef unsigned int MxVertexID;
|
---|
23 | typedef unsigned int MxFaceID;
|
---|
24 |
|
---|
25 | //
|
---|
26 | // Convenient nicknames
|
---|
27 | //
|
---|
28 | #define VID MxVertexID
|
---|
29 | #define FID MxFaceID
|
---|
30 |
|
---|
31 | #if !defined(MX_COLOR_RGBA) && !defined(MX_COLOR_ABGR)
|
---|
32 | # define MX_COLOR_RGBA
|
---|
33 | #endif
|
---|
34 |
|
---|
35 | class MxColor : public MxEQ
|
---|
36 | {
|
---|
37 | private:
|
---|
38 | inline unsigned char _ftop(float x)
|
---|
39 | { return (unsigned char)((x>1.0f?1.0f:x)*255.0f); }
|
---|
40 | inline float _ptof(unsigned char c) const { return ((float)c) / 255.0f; }
|
---|
41 |
|
---|
42 | public:
|
---|
43 | union {
|
---|
44 | #if defined(MX_COLOR_RGBA)
|
---|
45 | struct { unsigned char r, g, b, a; } chan;
|
---|
46 | #elif defined(MX_COLOR_ABGR)
|
---|
47 | struct { unsigned char a, b, g, r; } chan;
|
---|
48 | #else
|
---|
49 | # error "Packed color format illegal or left unspecified"
|
---|
50 | #endif
|
---|
51 | unsigned int word;
|
---|
52 | } as;
|
---|
53 |
|
---|
54 | MxColor() { }
|
---|
55 | MxColor(float r, float g, float b) { as.chan.a=0; set(r, g, b); }
|
---|
56 |
|
---|
57 | void set(float r, float g, float b)
|
---|
58 | { as.chan.r=_ftop(r); as.chan.g=_ftop(g); as.chan.b=_ftop(b); }
|
---|
59 | void set(const float *c)
|
---|
60 | { as.chan.r=_ftop(c[0]);as.chan.g=_ftop(c[1]);as.chan.b=_ftop(c[2]); }
|
---|
61 | void set(const double *c)
|
---|
62 | { as.chan.r=_ftop(c[0]);as.chan.g=_ftop(c[1]);as.chan.b=_ftop(c[2]); }
|
---|
63 |
|
---|
64 | float R() const { return _ptof(as.chan.r); }
|
---|
65 | float G() const { return _ptof(as.chan.g); }
|
---|
66 | float B() const { return _ptof(as.chan.b); }
|
---|
67 | };
|
---|
68 |
|
---|
69 | class MxTexCoord : public MxEQ
|
---|
70 | {
|
---|
71 | public:
|
---|
72 | float u[2];
|
---|
73 |
|
---|
74 | MxTexCoord() { }
|
---|
75 | MxTexCoord(float s, float t) { u[0]=s; u[1]=t; }
|
---|
76 | MxTexCoord(const MxTexCoord& t) { *this = t; }
|
---|
77 |
|
---|
78 | float& operator[](int i) { return u[i]; }
|
---|
79 | float operator[](int i) const { return u[i]; }
|
---|
80 | operator const float*() const { return u; }
|
---|
81 | operator float*() { return u; }
|
---|
82 |
|
---|
83 | MxTexCoord& operator=(const MxTexCoord& t)
|
---|
84 | { u[0]=t[0]; u[1]=t[1]; return *this; }
|
---|
85 | };
|
---|
86 |
|
---|
87 |
|
---|
88 | class MxVertex : public MxEQ
|
---|
89 | {
|
---|
90 | public:
|
---|
91 | union {
|
---|
92 | float pos[3];
|
---|
93 | struct { MxVertexID parent, next, prev; } proxy;
|
---|
94 | } as;
|
---|
95 |
|
---|
96 | MxVertex() { }
|
---|
97 | MxVertex(float x, float y, float z) {as.pos[0]=x;as.pos[1]=y;as.pos[2]=z;}
|
---|
98 | MxVertex(const MxVertex& v) { *this = v; }
|
---|
99 |
|
---|
100 | MxVertex& operator=(const MxVertex& v)
|
---|
101 | { as.pos[0]=v.as.pos[0]; as.pos[1]=v.as.pos[1];
|
---|
102 | as.pos[2]=v.as.pos[2]; return *this; }
|
---|
103 | operator const float*() const { return as.pos; }
|
---|
104 | operator float*() { return as.pos; }
|
---|
105 |
|
---|
106 | float& operator()(int i) { return as.pos[i]; }
|
---|
107 | float operator()(int i) const { return as.pos[i]; }
|
---|
108 | //
|
---|
109 | // The [] operator is preferred over ()
|
---|
110 | //
|
---|
111 | float& operator[](int i) { return as.pos[i]; }
|
---|
112 | float operator[](int i) const { return as.pos[i]; }
|
---|
113 | };
|
---|
114 |
|
---|
115 | class MxNormal : public MxEQ
|
---|
116 | {
|
---|
117 | private:
|
---|
118 | inline short _ftos(float x)
|
---|
119 | { return (short)rint((x>1.0f?1.0f:x)*(float)SHRT_MAX); }
|
---|
120 | inline short _dtos(double x)
|
---|
121 | { return (short)rint((x>1.0?1.0:x)*(double)SHRT_MAX); }
|
---|
122 |
|
---|
123 | inline float _stof(short s) const { return (float)s/(float)SHRT_MAX; }
|
---|
124 | inline double _stod(short s) const { return (double)s/(double)SHRT_MAX; }
|
---|
125 |
|
---|
126 | short dir[3];
|
---|
127 |
|
---|
128 | public:
|
---|
129 | MxNormal() { }
|
---|
130 | MxNormal(float x, float y, float z) { set(x,y,z); }
|
---|
131 | MxNormal(const float *v) { set(v); }
|
---|
132 | MxNormal(const double *v) { set(v); }
|
---|
133 |
|
---|
134 | inline void set(double x, double y, double z)
|
---|
135 | { dir[0]=_dtos(x); dir[1]=_dtos(y); dir[2]=_dtos(z); }
|
---|
136 | inline void set(const float *v)
|
---|
137 | { dir[0]=_ftos(v[0]); dir[1]=_ftos(v[1]); dir[2]=_ftos(v[2]); }
|
---|
138 | inline void set(const double *v)
|
---|
139 | { dir[0]=_dtos(v[0]); dir[1]=_dtos(v[1]); dir[2]=_dtos(v[2]); }
|
---|
140 |
|
---|
141 | float operator[](uint i) const { AssertBound(i<3); return _stof(dir[i]); }
|
---|
142 | short raw(uint i) const { return dir[i]; }
|
---|
143 | };
|
---|
144 |
|
---|
145 | class MxEdge : public MxEQ
|
---|
146 | {
|
---|
147 | public:
|
---|
148 | MxVertexID v1, v2;
|
---|
149 |
|
---|
150 | MxEdge() { v1=v2=MXID_NIL; }
|
---|
151 | MxEdge(MxVertexID a, MxVertexID b) { v1=a; v2=b; }
|
---|
152 | MxEdge(const MxEdge& e) { v1=e.v1; v2=e.v2; }
|
---|
153 |
|
---|
154 | MxVertexID opposite_vertex(MxVertexID v)
|
---|
155 | {
|
---|
156 | if( v==v1 ) return v2;
|
---|
157 | else { SanityCheck(v==v2); return v1; }
|
---|
158 | }
|
---|
159 | };
|
---|
160 |
|
---|
161 | class MxFace : public MxEQ
|
---|
162 | {
|
---|
163 | public:
|
---|
164 | MxVertexID v[3];
|
---|
165 |
|
---|
166 | MxFace() { }
|
---|
167 | MxFace(MxVertexID v0, MxVertexID v1, MxVertexID v2)
|
---|
168 | { v[0]=v0; v[1]=v1; v[2]=v2; }
|
---|
169 | MxFace(const MxFace& f) { v[0]=f.v[0]; v[1]=f.v[1]; v[2]=f.v[2]; }
|
---|
170 |
|
---|
171 | MxVertexID& operator()(int i) { return v[i]; }
|
---|
172 | MxVertexID operator()(int i) const { return v[i]; }
|
---|
173 | //
|
---|
174 | // The [] operator is now preferred over the () operator.
|
---|
175 | //
|
---|
176 | MxVertexID& operator[](int i) { return v[i]; }
|
---|
177 | MxVertexID operator[](int i) const { return v[i]; }
|
---|
178 |
|
---|
179 | int remap_vertex(MxVertexID from, MxVertexID to)
|
---|
180 | {
|
---|
181 | int nmapped = 0;
|
---|
182 | for(int i=0; i<3; i++)
|
---|
183 | if( v[i]==from )
|
---|
184 | {
|
---|
185 | v[i]=to;
|
---|
186 | nmapped++;
|
---|
187 | }
|
---|
188 | return nmapped;
|
---|
189 | }
|
---|
190 |
|
---|
191 | uint find_vertex(MxVertexID i)
|
---|
192 | {
|
---|
193 | if( v[0]==i ) return 0;
|
---|
194 | else if( v[1]==i ) return 1;
|
---|
195 | else { SanityCheck(v[2]==i); return 2; }
|
---|
196 | }
|
---|
197 |
|
---|
198 | MxVertexID opposite_vertex(MxVertexID v0, MxVertexID v1)
|
---|
199 | {
|
---|
200 | if( v[0]!=v0 && v[0]!=v1 ) return v[0];
|
---|
201 | else if( v[1]!=v0 && v[1]!=v1 ) return v[1];
|
---|
202 | else { SanityCheck( v[2]!=v0 && v[2]!=v1 ); return v[2]; }
|
---|
203 | }
|
---|
204 |
|
---|
205 | bool is_inorder(MxVertexID v0, MxVertexID v1)
|
---|
206 | {
|
---|
207 | if( v[0]==v0 ) return v[1]==v1;
|
---|
208 | else if( v[1]==v0 ) return v[2]==v1;
|
---|
209 | else { SanityCheck(v[2]==v0); return v[0]==v1; }
|
---|
210 | }
|
---|
211 | };
|
---|
212 |
|
---|
213 |
|
---|
214 | inline ostream& operator<<(ostream& out, const MxVertex& v)
|
---|
215 | {
|
---|
216 | return out << "v " << v(0) << " " << v(1) << " " << v(2);
|
---|
217 | }
|
---|
218 |
|
---|
219 | inline ostream& operator<<(ostream& out, const MxFace& f)
|
---|
220 | {
|
---|
221 | return out << "f " << f(0)+1 << " " << f(1)+1 << " " << f(2)+1;
|
---|
222 | }
|
---|
223 |
|
---|
224 | inline ostream& operator<<(ostream& out, const MxColor& c)
|
---|
225 | {
|
---|
226 | return out << "c " << c.R() << " " << c.G() << " " << c.B();
|
---|
227 | }
|
---|
228 |
|
---|
229 | inline ostream& operator<<(ostream& out, const MxNormal& n)
|
---|
230 | {
|
---|
231 | return out << "n " << n[0] << " " << n[1] << " " << n[2];
|
---|
232 | }
|
---|
233 |
|
---|
234 | inline ostream& operator<<(ostream& out, const MxTexCoord& t)
|
---|
235 | {
|
---|
236 | return out << "r " << t[0] << " " << t[1];
|
---|
237 | }
|
---|
238 |
|
---|
239 | #ifdef MXGL_INCLUDED
|
---|
240 | inline void glC(const MxColor& c)
|
---|
241 | {
|
---|
242 | glColor3ub(c.as.chan.r, c.as.chan.g, c.as.chan.b);
|
---|
243 | }
|
---|
244 | inline void glT(const MxTexCoord& t) { glTexCoord2fv(t); }
|
---|
245 | inline void glV(const MxVertex& v) { glVertex3fv(v); }
|
---|
246 | inline void glN(const MxNormal& n) {
|
---|
247 | //
|
---|
248 | // !!WARNING!! glNormal3sv doesn't work for some reason, and neither
|
---|
249 | // glNormal3s. Oddly, glNormal3i correctly. Is this some sort of GL bug
|
---|
250 | // or am I doing something wrong??
|
---|
251 | //
|
---|
252 | glNormal3i(n.raw(0), n.raw(1), n.raw(2));
|
---|
253 | }
|
---|
254 |
|
---|
255 | inline void glC(const MxColor *c) { glC(*c); }
|
---|
256 | inline void glT(const MxTexCoord *t) { glT(*t); }
|
---|
257 | inline void glV(const MxVertex *v) { glV(*v); }
|
---|
258 | inline void glN(const MxNormal *n) { glN(*n); }
|
---|
259 | #endif
|
---|
260 |
|
---|
261 | // MXGEOPRIMS_INCLUDED
|
---|
262 | #endif
|
---|