1 //#ident "$Id: AlignVisitor.cpp,v 1.5 2003/07/25 01:01:54 rzr Exp $"
2 /***************************************************************************
3                           AlignVisitor.cpp  -  description
4                              -------------------
5     begin                : Wed Jan 26 2000
6     copyright            : (C) 2000 by Henrik Enqvist
7     email                : henqvist@excite.com
8 ***************************************************************************/
9 
10 #include "Private.h"
11 #include "AlignVisitor.h"
12 #include "Group.h"
13 #include "Shape3D.h"
14 #include "Sound.h"
15 #include "Light.h"
16 #include "BillBoard.h"
17 #include "EMath.h"
18 
19 AlignVisitor * AlignVisitor::p_AlignVisitor = NULL;
20 
AlignVisitor()21 AlignVisitor::AlignVisitor() {
22   p_GroupCamera = NULL;
23   m_mtxInverse = EMath::identityMatrix;
24   m_vtxFront.x = 0.0;
25   m_vtxFront.y = 0.0;
26   m_vtxFront.z = -1.0;
27   m_vtxUp.x = 0.0;
28   m_vtxUp.y = 1.0;
29   m_vtxUp.z = 0.0;
30 }
31 
~AlignVisitor()32 AlignVisitor::~AlignVisitor() {
33   p_AlignVisitor = NULL;
34 }
35 
getInstance()36 AlignVisitor * AlignVisitor::getInstance() {
37   if (p_AlignVisitor == NULL) {
38     p_AlignVisitor = new AlignVisitor();
39   }
40   return p_AlignVisitor;
41 }
42 
43 /* Clean up camera matrix. */
empty()44 void AlignVisitor::empty() {
45   if (p_GroupCamera == NULL) return;
46 
47   EM_COUT("AlignVisitor::empty()", 0);
48   // backward matrix multiplication for the camera
49   if (p_GroupCamera == NULL) {
50     return;
51   }
52 
53 #if EM_USE_ALLEGRO
54   Matrix mtxTmp;
55   Matrix mtxScale = EMath::identityMatrix;
56   mtxScale.v[0][0] = 0.8;
57   mtxScale.v[1][1] = -0.6;
58   mtxScale.v[2][2] = -1;
59   EMath::matrixMulti(mtxScale, p_GroupCamera->m_mtxTrans, mtxTmp);
60   EMath::inverse(mtxTmp, m_mtxInverse);
61 #else
62   EMath::inverse(p_GroupCamera->m_mtxTrans, m_mtxInverse);
63 #endif
64 }
65 
setCamera(Group * g)66 void AlignVisitor::setCamera(Group * g) {
67   p_GroupCamera = g;
68 }
69 
70 /* Apply camera transform to all vertices and sounds. */
visit(Group * g)71 void AlignVisitor::visit(Group * g) {
72   EM_COUT("AlignVisitor::visit() *", 0);
73   // Apply transform to vertices in oShape3D.
74   vector<Shape3D*>::iterator shapeIter = g->m_vShape3D.begin();
75   vector<Shape3D*>::iterator shapeEnd = g->m_vShape3D.end();
76   for ( ; shapeIter != shapeEnd; shapeIter++) {
77 
78     vector<Vertex3D>::iterator transIter = (*shapeIter)->m_vVtxTrans.begin();
79     vector<Vertex3D>::iterator transEnd = (*shapeIter)->m_vVtxTrans.end();
80     vector<Vertex3D>::iterator alignIter = (*shapeIter)->m_vVtxAlign.begin();
81     //vector<Vertex3D>::iterator alignEnd = (*shapeIter)->m_vVtxAlign.end();
82     vector<Vertex3D>::iterator nmlTransIter = (*shapeIter)->m_vNmlTrans.begin();
83     //vector<Vertex3D>::iterator nmlTransEnd = (*shapeIter)->m_vNmlTrans.end();
84     vector<Vertex3D>::iterator nmlAlignIter = (*shapeIter)->m_vNmlAlign.begin();
85     //vector<Vertex3D>::iterator nmlAlignEnd = (*shapeIter)->m_vNmlAlign.end();
86 
87     EmAssert(((*shapeIter)->m_vVtxTrans.size () ==
88               (*shapeIter)->m_vVtxAlign.size ()) &&
89              ((*shapeIter)->m_vNmlTrans.size () ==
90               (*shapeIter)->m_vNmlAlign.size ()), "size miss match");
91 
92     for ( ; transIter != transEnd;
93           transIter++, alignIter++, nmlTransIter++, nmlAlignIter++) {
94       // Translation and rotation needs to be applied in wrong order
95       Vertex3D vtx;
96       vtx.x = (*transIter).x + m_mtxInverse.t[0];
97       vtx.y = (*transIter).y + m_mtxInverse.t[1];
98       vtx.z = (*transIter).z + m_mtxInverse.t[2];
99       EMath::applyMatrixRot(m_mtxInverse, vtx, (*alignIter));
100       // Normals only needs rotation
101       EMath::applyMatrixRot(m_mtxInverse, (*nmlTransIter), (*nmlAlignIter));
102       EMath::normalizeVector(*nmlAlignIter);
103       // TODO: optimize = macro instead of apply-fct calls, remove normalize
104 
105       EM_COUT("AlignVisitor::visit() " <<
106               (*transIter).x <<" "<< (*transIter).y <<" "<< (*transIter).z <<" -> "<<
107               (*alignIter).x <<" "<< (*alignIter).y <<" "<< (*alignIter).z, 0);
108     }
109   }
110   // Apply transform to BillBoard.
111   if (g->p_BillBoard != NULL) {
112     // Translation and rotation needs to be applied in wrong order
113     Vertex3D vtx = { 0 , 0 , 0 } ; //!rzr UMR
114     vtx.x = g->p_BillBoard->m_vtxTrans.x + m_mtxInverse.t[0];
115     vtx.y = g->p_BillBoard->m_vtxTrans.y + m_mtxInverse.t[1];
116     vtx.z = g->p_BillBoard->m_vtxTrans.z + m_mtxInverse.t[2];
117     EMath::applyMatrixRot(m_mtxInverse, vtx,  g->p_BillBoard->m_vtxAlign);
118     EM_COUT("AlignVisitor::visit() billboard " <<
119             g->p_BillBoard->m_vtxTrans.x <<" "<<
120             g->p_BillBoard->m_vtxTrans.y <<" "<<
121             g->p_BillBoard->m_vtxTrans.z <<" -> "<<
122             g->p_BillBoard->m_vtxAlign.x <<" "<<
123             g->p_BillBoard->m_vtxAlign.y <<" "<<
124             g->p_BillBoard->m_vtxAlign.z , 0);
125   }
126   // Apply transform to Light.
127   if (g->p_Light != NULL) {
128     // Translation and rotation needs to be applied in wrong order
129     Vertex3D vtx;
130     vtx.x = g->p_Light->m_vtxTrans.x + m_mtxInverse.t[0];
131     vtx.y = g->p_Light->m_vtxTrans.y + m_mtxInverse.t[1];
132     vtx.z = g->p_Light->m_vtxTrans.z + m_mtxInverse.t[2];
133     EMath::applyMatrixRot(m_mtxInverse, vtx,  g->p_Light->m_vtxAlign);
134   }
135   // Apply transform to oSound.
136   //    if (g->m_Sound != NULL) {
137   //            EMath::applyMatrix(mtxCamera, g->m_Sound->vtxTrans, g->m_Sound->vtxAlign);
138   //    }
139 
140   //    Apply transform to oNestedBounds.
141   //    if (g->m_CollisionBounds != NULL)       {
142   //            this->visit(g->oNestedBounds);
143   //    }
144 }
145 
146