-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsglobjbase.cpp
More file actions
273 lines (242 loc) · 7.97 KB
/
Copy pathsglobjbase.cpp
File metadata and controls
273 lines (242 loc) · 7.97 KB
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
/***************************************************************************
* Copyright (C) 2003 by Enrico Reimer *
* enni@Willow.Reimer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#include "sglobjbase.h"
#include "sglmisc.h"
#include <typeinfo>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
#ifdef __APPLE__
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#endif
using boost::numeric::ublas::matrix;
/**
* Kopierkonstruktor.
* Alle Parameter bis auf is_free und shared werden kopiert.
* Das kopierte Objekt ist nocht nicht im Renderercache und gehört zu keiner Liste.
* Sein compileNextTime-Slot muss noch an ein Signal gebunden werden.
* @param src Das zu kopierende Objekt
*/
SGLObjBase::SGLObjBase(const SGLObjBase &src):
SGLMatrixObj(GL_MODELVIEW),
compileNextTime(this)
{
ID=0;
FaceAt = src.FaceAt;
FrontFace = src.FrontFace;
IgnoreClip = src.IgnoreClip;
IgnoreLight = src.IgnoreLight;
myList = src.myList;
ResetTransformMatrix(src.MyTransformMatrix);
priority = src.priority;
should_compile = 1;
is_free=shared=false;
}
/**
* Standardkonstruktor.
* Erzeugt ein Objekt an den gegebenen Raumkoordinaten.
* @param PosX die Raumkoordinaten, an denen das Objekt erz. wird
* @param PosY
* @param PosZ
* @param SizeFact Die Grundskalierung, mit der das Objekt erzeugt wird.
*/
SGLObjBase::SGLObjBase(GLdouble PosX,GLdouble PosY,GLdouble PosZ,GLdouble SizeFact):
SGLMatrixObj(GL_MODELVIEW),
compileNextTime(this)
{
ID=0;
ResetTransformMatrix(NULL);
MyTransformMatrix[12]=PosX;
MyTransformMatrix[13]=PosY;
MyTransformMatrix[14]=PosZ;
MyTransformMatrix[0]=MyTransformMatrix[5]=MyTransformMatrix[10]=SizeFact;
IgnoreClip=IgnoreLight=false;
FrontFace=GL_CCW;
FaceAt=NULL;
myList=NULL;
should_compile=1;
shared=false;
}
/**
* Destruktor.
* Sollte nicht explizit ausgelöst werden.
* Das Objekt wird automatisch gelöscht, wenn es nicht mehr verwedet wird.
* Ist das gelöschte Objekt noch in einer Objektliste eingetragen, wird eine Warnung ausgegeben.
*/
SGLObjBase::~SGLObjBase()
{
if(myList)
{
unsigned int count=myList->isThere(this);
if(count){SGLprintError("lösche noch %d mal verwendetes Objekt",count);}
}
glDeleteLists(ID,1);
if(!ID)
{SGLprintDebug("Nie generiertes Objekt 0x%x (%s) gelöscht",this,this->guesType());}//@todo prüfen, ob ID=0 immer heißt, daß obj nie gen wurde
}
/**
* Bestimmt die Normale auf der durch zwei Vektoren bestimmten Ebene.
* Die Ebene schneidet den Koordinatenursprung.
* @param Vekt1 die zwei Vektoren zur beschreibung der Ebene
* @param Vekt2
* @return einen Vektor, der senkrecht auf der Ebene steht
*/
SGLVektor SGLObjBase::Normale(SGLVektor Vekt1,SGLVektor Vekt2)
{
SGLVektor ret=Vekt1.cross_prod(Vekt2);
if(!glIsEnabled(GL_NORMALIZE))
ret/=boost::numeric::ublas::norm_2(ret);
return ret;
}
/**
* Bestimmt die Normale auf der durch zwei Vektoren und einen Stützvektor bestimmten Ebene.
* Die Ebene schneidet den durch den Stützvektor gegebenen Punkt im Raum.
* @param Pkt1 @param Pkt2 die zwei Vektoren zur beschreibung der Ebene
* @param Pkt3 der Stützvektor der Ebene
* @return
*/
SGLVektor SGLObjBase::Normale(SGLVektor Pkt1,SGLVektor Pkt2,SGLVektor Pkt3)
{return Normale(SGLVektor(Pkt2-Pkt1),SGLVektor(Pkt3-Pkt1));}
/**
* Basis-Zeichenfunktion.
* Lädt die Transformationsmatrix des Objektes, richtet es danach gegebenfalls nach dem FaceAt-Punkt aus und ruft generate() auf.
*/
void SGLObjBase::metaGenerate()
{
loadMatrix();
if(FaceAt)
{
glMatrixMode(GL_MODELVIEW);
GLdouble ebene_wink,steigung;
SGLVektor tVekt=getCenterInSpace();
tVekt.resize(3);
tVekt=*FaceAt-tVekt;
tVekt.toWink(ebene_wink,steigung);
glRotated(-ebene_wink,0,1,0);
glRotated(90,0,1,0);
glRotated(-steigung,1,0,0);
}
GLenum error;
while((error=glGetError()))
{
SGLprintError("%s [GLerror] vor dem Generieren von %s",gluErrorString(GLenum(error)),guesType());
}
generate();
while((error=glGetError()))
{
SGLprintError("%s [GLerror] beim Generieren von %s",gluErrorString(GLenum(error)),guesType());
}
unloadMatrix();
notifyChange();
}
/**
* Wendet die Transformationen des Objektes auf das Ergebniss von getCenter() an und gibt das Ergebniss zurück.
* @return die Position des Objektzentrums im Raum.
*/
SGLVektor SGLObjBase::getCenterInSpace()
{
dvector ret=getCenter();
ret.resize(4);
ret[3]=1;
matrix<GLdouble,boost::numeric::ublas::column_major> Matr(4,4);
std::copy(MyTransformMatrix,MyTransformMatrix+16,Matr.data().begin());
ret=boost::numeric::ublas::prod(Matr,ret);
ret.resize(3);
return ret;
}
/**
* Wendet die Transformationen des Objektes auf einen Nullvektor an und gibt das Ergebniss zurück.
* @return die Position des Objektes im Raum.
*/
SGLVektor SGLObjBase::getMyPos()
{
dvector ret(4);
dmatrix tMatr(4,4);
ret[3]=1;
std::copy(MyTransformMatrix,MyTransformMatrix+16,tMatr.data().begin());
ret=boost::numeric::ublas::prod(tMatr,ret);
ret.resize(3);
return ret;
}
/**
* Stellt sicher, das dieses Objekt im Renderer-Cache vorliegt und liefert seine ID.
* Wenn force_compile war ist, das Objekt noch nicht in der OpenGL-Pipeline vorliegt
* oder wenn es neu berechnet werden muss, wird Compile() aufgerufen.
* Das Objekt wird dabei jedoch nicht gezeichnet.
* @param force_compile wenn true wird das Objekt in jedem Fall neu generiert.
* @return die ID, die das Objekt im Cache des Renderers hat. Diese ID ist innerhalb eines Renderers eindeutig.
*/
GLuint SGLObjBase::metaCompile(bool force_compile)
{
GLuint ret;
ret = (force_compile || should_compile || !glIsList(ID)) ?
Compile():
ID;
if(should_compile>0)should_compile=0;
return ret;
}
/**
* Bindet das Objekt an ein Anderes.
* Löst dieses Objekt das Signal notifyChange aus, wird das gebundene Objekt bei nächster Gelegenheit neu berechnet.
* Da beim Generieren notifyChange nicht ausgelöst wird, ist auch gegenseitiges Binden möglich.
* \code
* objA.link(objB);
* objB.link(objA);
* \endcode
* @param obj das Zeilobjekt an das bei notifyChange neu berechnet werden soll.
* @return
*/
SGLConnection SGLObjBase::link(SGLObjBase &obj)
{
return notifyChange.connect(obj.compileNextTime);
}
void SGLObjBase::unlink(SGLConnection conn)
{
conn.disconnect();
}
/**
* Bereitet den Renderercache für das Objekt vor.
* Hat das Objekt noch keine ID, wird ihm eine zugewiesen.
* @param draw Wenn true, wird gleichzeitig in den Renderercache geschrieben und das Objekt gezeichnet.
* @return die ID des Objektes.
*/
GLint SGLObjBase::beginList(bool draw)
{
if(!(glIsList(ID) || (ID=glGenLists(1))))
{
GLuint error=glGetError();
SGLprintError("Konnte Zeichencache für das %s-Objekt nicht erzeugen. (%s) Wurde openGL vielleicht noch nicht initialisiert?",guesType(),gluErrorString(GLenum(error)));
}
rendering=true;
glNewList(ID,draw ? GL_COMPILE_AND_EXECUTE:GL_COMPILE);
return ID;
}
/**
* Schließt den Renderercache für das Objekt ab.
* Alle GL-Zeichenoperationen müssen zwischen beginList() und endList aufgerufen werden.
*/
void SGLObjBase::endList()
{
glEndList();
rendering=false;
}
SGLObjBase::CompilerMerker::CompilerMerker(SGLObjBase *obj){this->obj=obj;}
/**
* Stellt sicher, daß der Renderercache dieses Objektes bei nächster Gelegenheit neu berechnet wird
*/
void SGLObjBase::CompilerMerker::operator()() const
{
if(obj->myList)
obj->myList->check_recompile=true;
else if(!obj->is_free)
{SGLprintDebug("Objekt vom Typ %s ist scheinbar in (noch) keiner Objektliste.\nKann nicht vermerken, daß es neu generiert werden muß", obj->guesType());}
if(!obj->should_compile)obj->should_compile=1;
}