1 /*
2 * NodeGeoTransform.cpp
3 *
4 * Copyright (C) 2009, 2019 J. "MUFTI" Scheurich
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program (see the file "COPYING" for details); if
18 * not, write to the Free Software Foundation, Inc., 675 Mass Ave,
19 * Cambridge, MA 02139, USA.
20 */
21
22 #include <stdio.h>
23 #include "stdafx.h"
24
25 #include "NodeGeoTransform.h"
26 #include "Proto.h"
27 #include "FieldValue.h"
28 #include "MFNode.h"
29 #include "MFNode.h"
30 #include "MFNode.h"
31 #include "SFVec3d.h"
32 #include "SFRotation.h"
33 #include "SFVec3f.h"
34 #include "SFRotation.h"
35 #include "SFVec3f.h"
36 #include "SFVec3f.h"
37 #include "SFVec3f.h"
38 #include "SFNode.h"
39 #include "MFString.h"
40 #include "Scene.h"
41 #include "DuneApp.h"
42
43 #include "NodeGeoOrigin.h"
44
ProtoGeoTransform(Scene * scene)45 ProtoGeoTransform::ProtoGeoTransform(Scene *scene)
46 : GeoProto(scene, "GeoTransform")
47 {
48 children.set(
49 addExposedField(MFNODE, "children", new MFNode()));
50 geoCenter.set(
51 addExposedField(SFVEC3D, "geoCenter", new SFVec3d(0, 0, 0)));
52 rotation.set(
53 addExposedField(SFROTATION, "rotation", new SFRotation(0, 0, 1, 0)));
54 scale.set(
55 addExposedField(SFVEC3F, "scale", new SFVec3f(1, 1, 1)));
56 scaleOrientation.set(
57 addExposedField(SFROTATION, "scaleOrientation", new SFRotation(0, 0, 1, 0)));
58 translation.set(
59 addExposedField(SFVEC3F, "translation", new SFVec3f(0, 0, 0)));
60 bboxCenter.set(
61 addField(SFVEC3F, "bboxCenter", new SFVec3f(0, 0, 0)));
62 bboxSize.set(
63 addField(SFVEC3F, "bboxSize", new SFVec3f(-1, -1, -1)));
64
65 globalGeoOrigin.set(
66 addExposedField(SFBOOL, "globalGeoOrigin", new SFBool(false)));
67 setFieldFlags(globalGeoOrigin, FF_X3DOM_ONLY);
68
69 render.set(
70 addExposedField(SFBOOL, "render", new SFBool(true)));
71 setFieldFlags(render, FF_X3DOM_ONLY);
72
73 addEventIn(MFNODE, "addChildren");
74 addEventIn(MFNODE, "removeChildren");
75 }
76
77 Node *
create(Scene * scene)78 ProtoGeoTransform::create(Scene *scene)
79 {
80 return new NodeGeoTransform(scene, this);
81 }
82
NodeGeoTransform(Scene * scene,Proto * def)83 NodeGeoTransform::NodeGeoTransform(Scene *scene, Proto *def)
84 : GeoNode(scene, def)
85 {
86 m_matrixDirty = true;
87 }
88
89 void
transform()90 NodeGeoTransform::transform()
91 {
92 const double *fcenter = geoCenter()->getValue();
93 const float *frotation = rotation()->getValue();
94 const float *fscale = scale()->getValue();
95 const float *fscaleOrientation = scaleOrientation()->getValue();
96 const float *ftranslation = translation()->getValue();
97
98 if (m_matrixDirty) {
99 double rotAngle = frotation[3];
100 double oriAngle = fscaleOrientation[3];
101 if (m_scene) {
102 double angleUnit = m_scene->getUnitAngle();
103 if (angleUnit != 0) {
104 rotAngle *= angleUnit;
105 oriAngle *= angleUnit;
106 }
107 }
108 double identity[16] = { 1, 0, 0, 0,
109 0, 1, 0, 0,
110 0, 0, 1, 0,
111 0, 0, 0, 1 };
112 glPushMatrix();
113 glMatrixMode(GL_MODELVIEW);
114 glLoadMatrixd(identity);
115 glTranslatef(ftranslation[0], ftranslation[1], ftranslation[2]);
116 glTranslated(fcenter[0], fcenter[1], fcenter[2]);
117 glRotatef(RAD2DEG(rotAngle),
118 frotation[0], frotation[1], frotation[2]);
119 glRotatef(RAD2DEG(oriAngle),
120 fscaleOrientation[0], fscaleOrientation[1], fscaleOrientation[2]);
121 glScalef(fscale[0], fscale[1], fscale[2]);
122 glRotatef(-RAD2DEG(oriAngle),
123 fscaleOrientation[0], fscaleOrientation[1], fscaleOrientation[2]);
124 glTranslated(-fcenter[0], -fcenter[1], -fcenter[2]);
125
126 glGetDoublev(GL_MODELVIEW_MATRIX, m_matrix);
127
128 m_matrixDirty = false;
129 glPopMatrix();
130 }
131 //for (int i = 0; i < 16; i++)
132 //printf("%lf ", m_matrix[i]);
133 //printf("\n");
134 glMultMatrixd(m_matrix);
135 }
136
137 void
preDraw()138 NodeGeoTransform::preDraw()
139 {
140 NodeList *childList = children()->getValues();
141
142 glPushMatrix();
143 transform();
144
145 for (long i = 0; i < childList->size(); i++)
146 if (childList->get(i) != this)
147 childList->get(i)->preDraw();
148
149 glPopMatrix();
150 }
151
152 void
draw(int pass)153 NodeGeoTransform::draw(int pass)
154 {
155 int i;
156 NodeList *childList = children()->getValues();
157 int n = childList->size();
158
159 glPushMatrix();
160
161 NodeGeoOrigin *origin = (NodeGeoOrigin *)geoOrigin()->getValue();
162
163 transform();
164
165 if (origin) {
166 Vec3d vec = origin->getVec();
167 glTranslated(vec.x, vec.y, vec.z);
168 }
169
170 for (i = 0; i < n; i++)
171 childList->get(i)->bind();
172
173 glPushName(children_Field()); // field
174 glPushName(0); // index
175 for (i = 0; i < n; i++) {
176 glLoadName(i);
177 if (childList->get(i) != this)
178 childList->get(i)->draw(pass);
179 }
180 glPopName();
181 glPopName();
182
183 for (i = 0; i < n; i++)
184 childList->get(i)->unbind();
185
186 glPopMatrix();
187 }
188
189
190