14 |
#include "libcolor/spaces.hxx" |
#include "libcolor/spaces.hxx" |
15 |
#include "libtext/Text.hxx" |
#include "libtext/Text.hxx" |
16 |
|
|
17 |
|
#include "libcoords/Coords.hxx" |
18 |
|
|
19 |
//#include <map> // XXX: used by ../demo/clamptexture.cxx hack |
//#include <map> // XXX: used by ../demo/clamptexture.cxx hack |
20 |
|
|
21 |
#define GLERR { int er = glGetError(); if(er != GL_NO_ERROR) \ |
#define GLERR { int er = glGetError(); if(er != GL_NO_ERROR) \ |
100 |
|
|
101 |
void setStandardCoordinates(Vec windowSize); |
void setStandardCoordinates(Vec windowSize); |
102 |
|
|
|
/** A general affine coordinate system. |
|
|
*/ |
|
|
struct AffineCoords { |
|
|
Pt center; |
|
|
Vec x; |
|
|
Vec y; |
|
|
float z; |
|
|
AffineCoords() { } |
|
|
AffineCoords(Pt center, Vec x, Vec y) : center(center), x(x), y(y) {} |
|
|
|
|
|
/** Create a new affinecoords that contains an orthogonal transformation before |
|
|
* the coords. |
|
|
*/ |
|
|
AffineCoords(float wmult, float hmult, float xoffs, float yoffs, float zoffs, AffineCoords &other) { |
|
|
center = other.center; center += xoffs * other.x; center += yoffs * other.y; |
|
|
x = wmult * other.x; |
|
|
y = hmult * other.y; |
|
|
z = other.z + zoffs; |
|
|
} |
|
|
|
|
|
/** Return the inverse of this coordinate system |
|
|
*/ |
|
|
AffineCoords getInverse() const { |
|
|
float m = 1.0 / (x.x * y.y - x.y * y.x); |
|
|
AffineCoords r(Pt(0, 0), Vec(m * y.y, -m * x.y), Vec(-m * y.x, m * x.x)); |
|
|
r.center -= center.x * r.x + center.y * r.y; |
|
|
r.z = -z; |
|
|
return r; |
|
|
} |
|
|
|
|
|
void dump() { |
|
|
cout << "Affinecoords: "; |
|
|
cout << center << " " << x << " " << y << " " << z <<"\n\n"; |
|
|
} |
|
|
|
|
|
enum { nFloatParams = 7 }; |
|
|
void load(float *f) { |
|
|
center = Pt(f[0], f[1]); |
|
|
x = Vec(f[2], f[3]); |
|
|
y = Vec(f[4], f[5]); |
|
|
z = f[6]; |
|
|
} |
|
|
|
|
|
void vertex(const ZPt &p) const { |
|
|
ZPt tmp = transform(p); |
|
|
// std::cout << "Affine vertex: "<<tmp<<" z "<<z<<"\n"; |
|
|
glVertex3f(tmp.x, tmp.y, tmp.z); |
|
|
} |
|
|
void vertex(const Pt &p) const { |
|
|
ZPt tmp = transform(p); |
|
|
// std::cout << "Affine vertex: "<<tmp<<" z "<<z<<"\n"; |
|
|
glVertex3f(tmp.x, tmp.y, tmp.z); |
|
|
} |
|
|
ZPt transform(const Pt &p) const { |
|
|
Pt tmp = center + x * p.x + y * p.y; |
|
|
return ZPt(tmp.x, tmp.y, z); |
|
|
} |
|
|
ZPt transform(const ZPt &p) const { |
|
|
Pt tmp = center + x * p.x + y * p.y; |
|
|
return ZPt(tmp.x, tmp.y, z + p.z); |
|
|
} |
|
|
Vec transform(const Vec &p) const { |
|
|
return x * p.x + y * p.y; |
|
|
} |
|
|
|
|
|
void performGL_xy() { |
|
|
GLfloat matrix[16] = { |
|
|
x.x, x.y, 0, 0, |
|
|
y.x, y.y, 0, 0, |
|
|
0, 0, 1, 0, |
|
|
center.x, center.y, 0, 1 |
|
|
}; |
|
|
glMultMatrixf(matrix); |
|
|
} |
|
|
|
|
|
void performGL() { |
|
|
GLfloat matrix[16] = { |
|
|
x.x, x.y, 0, 0, |
|
|
y.x, y.y, 0, 0, |
|
|
0, 0, 1, 0, |
|
|
center.x, center.y, z, 1 |
|
|
}; |
|
|
glMultMatrixf(matrix); |
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
/* A coordinate system which only translates |
|
|
* and scales. |
|
|
*/ |
|
|
/* |
|
|
struct OrthoCoords { |
|
|
Pt center; |
|
|
float xScale; |
|
|
float yScale; |
|
|
float z; |
|
|
OrthoCoords() { } |
|
|
OrthoCoords(Pt center, float xScale, float yScale) |
|
|
: center(center), xScale(xScale), yScale(yScale) {} |
|
|
void load(float *f) { |
|
|
center = Pt(f[0], f[1]); |
|
|
xScale = f[2]; |
|
|
yScale = f[3]; |
|
|
z = f[4]; |
|
|
} |
|
|
void vertex(const ZPt &p) const { |
|
|
Pt tmp = center + Vec(xScale * p.x, yScale * p.y); |
|
|
// std::cout << "Ortho vertex: "<<tmp<<" z "<<z<<"\n"; |
|
|
glVertex3f(tmp.x, tmp.y, z + p.z); |
|
|
} |
|
|
void vertex(const Pt &p) const { |
|
|
Pt tmp = center + Vec(xScale * p.x, yScale * p.y); |
|
|
// std::cout << "Ortho vertex: "<<tmp<<" z "<<z<<"\n"; |
|
|
glVertex3f(tmp.x, tmp.y, z); |
|
|
} |
|
|
ZPt transform(const Pt &p) const { |
|
|
return ZPt(center.x + xScale * p.x, |
|
|
center.y + yScale*p.y, |
|
|
z); |
|
|
} |
|
|
}; |
|
|
*/ |
|
|
|
|
103 |
/** An OpenGL thing that can be rendered without a coordinate |
/** An OpenGL thing that can be rendered without a coordinate |
104 |
* system. |
* system. |
105 |
*/ |
*/ |
115 |
*/ |
*/ |
116 |
struct Renderable1 { |
struct Renderable1 { |
117 |
virtual ~Renderable1() { } |
virtual ~Renderable1() { } |
118 |
virtual void render(AffineCoords &c) = 0; |
virtual void render(Coords::CoordSys &c) = 0; |
|
// virtual void render(OrthoCoords &c) = 0; |
|
119 |
}; |
}; |
120 |
|
|
121 |
#define IMPLEMENTRENDER1 \ |
#define IMPLEMENTRENDER1 \ |
122 |
void render(AffineCoords &c) { renderImpl(c); } |
void render(Coords::CoordSys &c) { renderImpl(c); } |
123 |
|
|
124 |
|
|
|
// void render(OrthoCoords &c) { renderImpl(c); } |
|
125 |
|
|
126 |
/** An OpenGL thing which starts in one coordinate |
/** An OpenGL thing which starts in one coordinate |
127 |
* system and ends in another. Used for connections. |
* system and ends in another. Used for connections. |
128 |
*/ |
*/ |
129 |
struct Renderable2 { |
struct Renderable2 { |
130 |
virtual ~Renderable2() { } |
virtual ~Renderable2() { } |
131 |
virtual void render(AffineCoords &c1, AffineCoords &c2) = 0; |
virtual void render(Coords::CoordSys &c1, Coords::CoordSys &c2) = 0; |
|
// virtual void render(OrthoCoords &c1, OrthoCoords &c2) = 0; |
|
132 |
}; |
}; |
133 |
|
|
134 |
#define IMPLEMENTRENDER2 \ |
#define IMPLEMENTRENDER2 \ |
135 |
virtual void render(AffineCoords &c1, AffineCoords &c2) \ |
virtual void render(Coords::CoordSys &c1, Coords::CoordSys &c2) \ |
136 |
{ renderImpl(c1, c2); } \ |
{ renderImpl(c1, c2); } \ |
137 |
|
|
|
// virtual void render(OrthoCoords &c1, OrthoCoords &c2) |
|
|
// { renderImpl(c1, c2); } |
|
138 |
|
|
|
// XXX Move |
|
|
inline float lerp(float a, float b, float fract) { |
|
|
return a + fract * (b-a); |
|
|
} |
|
139 |
|
|
140 |
using std::vector; |
using std::vector; |
141 |
|
|
142 |
/** Render renderables in interpolated coordinate systems |
class Renderer { |
143 |
* from lists of integers. |
Coords::CoordSet coordset; |
144 |
*/ |
public: |
145 |
template<class CoordsType> class Renderer { |
void setPoints( int ninds, |
146 |
vector<float> floatBuffer; |
int *inds1, float *points1, |
147 |
vector<CoordsType> coordsBuffer; |
int *interpinds, |
148 |
vector<bool> coordsValid; |
int *inds2, float *points2, |
149 |
|
float fract, bool show1) { |
150 |
public: |
coordset.clean(); |
151 |
Renderer() : floatBuffer(), coordsBuffer() { } |
coordset.setPoints(ninds, inds1, points1, interpinds, inds2, points2, fract, show1); |
|
|
|
|
void setPoints(int npts, float *points1, |
|
|
int *indices2, |
|
|
float *points2, float fract, |
|
|
bool showFinal) { |
|
|
floatBuffer.reserve(npts); |
|
|
coordsValid.reserve(npts / CoordsType::nFloatParams); |
|
|
for(int i=0; i<npts; i++) { |
|
|
int ind2 = i / CoordsType::nFloatParams; |
|
|
if(indices2) { |
|
|
if(indices2[i / CoordsType::nFloatParams] <= 0) { |
|
|
if(showFinal) { |
|
|
coordsValid[i / CoordsType::nFloatParams] = true; |
|
|
floatBuffer[i] = points1[i]; |
|
|
} else { |
|
|
coordsValid[i / CoordsType::nFloatParams] = false; |
|
|
} |
|
|
continue; |
|
|
} else { |
|
|
coordsValid[i / CoordsType::nFloatParams] = true; |
|
|
ind2 = indices2[i / CoordsType::nFloatParams]; |
|
|
} |
|
|
} else |
|
|
coordsValid[i / CoordsType::nFloatParams] = true; |
|
|
|
|
|
floatBuffer[i] = lerp(points1[i], |
|
|
points2[ind2 * CoordsType::nFloatParams + |
|
|
i % CoordsType::nFloatParams], |
|
|
fract); |
|
|
} |
|
|
int ncoords = npts / CoordsType::nFloatParams; |
|
|
coordsBuffer.reserve(ncoords); |
|
|
for(int i=0; i<ncoords; i++) |
|
|
coordsBuffer[i].load( & floatBuffer[i * CoordsType::nFloatParams] ); |
|
152 |
} |
} |
153 |
|
|
154 |
void setPoints(int npts, float *points1) { |
void setPoints( int ninds, int *inds1, float *points1) { |
155 |
floatBuffer.reserve(npts); |
coordset.clean(); |
156 |
coordsValid.reserve(npts / CoordsType::nFloatParams); |
coordset.setPoints(ninds, inds1, points1, 0, 0, 0, 0, true); |
|
for(int i=0; i<npts; i++) { |
|
|
floatBuffer[i] = points1[i]; |
|
|
coordsValid[i / CoordsType::nFloatParams] = true; |
|
|
} |
|
|
int ncoords = npts / CoordsType::nFloatParams; |
|
|
coordsBuffer.reserve(ncoords); |
|
|
for(int i=0; i<ncoords; i++) |
|
|
coordsBuffer[i].load( & floatBuffer[i * CoordsType::nFloatParams] ); |
|
157 |
} |
} |
|
|
|
|
/** Render the scene specified. |
|
|
* This method is called once per each frame to render |
|
|
* everything. The list of integers given is interpreted as |
|
|
* indices of renderables and coordinate systems, with |
|
|
* the following formats: |
|
|
* <pre> |
|
|
* renderable0id | RENDERABLE0 |
|
|
* |
|
|
* renderable1id | RENDERABLE1 |
|
|
* coordinatesystemId |
|
|
* |
|
|
* renderable2id | RENDERABLE2 |
|
|
* coordinatesystemId |
|
|
* coordinatesystemId |
|
|
* </pre> |
|
|
* where '|' is bitwise or. |
|
|
* Each renderable is only rendered if each of its |
|
|
* coordinate systems is valid (set in setPoints). |
|
|
* @param codes The identifiers of the objects to render. |
|
|
*/ |
|
158 |
void renderScene(int *codes, |
void renderScene(int *codes, |
159 |
ObjectStorer<Renderable0> &r0s, |
ObjectStorer<Renderable0> &r0s, |
160 |
ObjectStorer<Renderable1> &r1s, |
ObjectStorer<Renderable1> &r1s, |
172 |
} |
} |
173 |
else if(codes[i] & RENDERABLE1) { |
else if(codes[i] & RENDERABLE1) { |
174 |
if(dbg) std::cout << "rend1 "<<r1s[code]<<"\n"; |
if(dbg) std::cout << "rend1 "<<r1s[code]<<"\n"; |
175 |
if(coordsValid[codes[i+1]]) |
Coords::CoordSys *cs1 = coordset.get(codes[i+1]); |
176 |
r1s[code]->render(coordsBuffer[codes[i+1]]); |
if(cs1) |
177 |
|
r1s[code]->render(*cs1); |
178 |
i += 2; |
i += 2; |
179 |
} |
} |
180 |
else if(codes[i] & RENDERABLE2) { |
else if(codes[i] & RENDERABLE2) { |
181 |
if(dbg) std::cout << "rend2 "<<r2s[code]<<"\n"; |
if(dbg) std::cout << "rend2 "<<r2s[code]<<"\n"; |
182 |
if(coordsValid[codes[i+1]] && |
Coords::CoordSys *cs1 = coordset.get(codes[i+1]); |
183 |
coordsValid[codes[i+2]]) |
Coords::CoordSys *cs2 = coordset.get(codes[i+2]); |
184 |
r2s[code]->render(coordsBuffer[codes[i+1]], |
if(cs1 && cs2) |
185 |
coordsBuffer[codes[i+2]]); |
r2s[code]->render(*cs1, *cs2); |
186 |
i += 3; |
i += 3; |
187 |
} |
} |
188 |
else { |
else { |