1 | |
---|
2 | #include "LBBCBillboardKdTreeClusterData.h" |
---|
3 | |
---|
4 | namespace LBBC { |
---|
5 | |
---|
6 | BillboardKdTreeClusterData::BillboardKdTreeClusterData() { |
---|
7 | } |
---|
8 | |
---|
9 | BillboardKdTreeClusterData::~BillboardKdTreeClusterData() { |
---|
10 | } |
---|
11 | |
---|
12 | void BillboardKdTreeClusterData::readBillboardClusterData(TiXmlNode *parentNode) |
---|
13 | { |
---|
14 | |
---|
15 | } |
---|
16 | |
---|
17 | void BillboardKdTreeClusterData::writeBillboardClusterData(TiXmlNode *parentNode) |
---|
18 | { |
---|
19 | BBC::EntityCluster *entityCluster = getEntityCluster(); |
---|
20 | Ogre::Vector3 normal = getNormal();
|
---|
21 | normal.normalise();
|
---|
22 |
|
---|
23 | float d = 0;
|
---|
24 | for (unsigned int iLeaf = 0; iLeaf < entityCluster->getNumEntitiesClusterData(); iLeaf++)
|
---|
25 | {
|
---|
26 | LeafKdTreeClusterData *leafKdTreeClusterData = (LeafKdTreeClusterData*)entityCluster->getEntityClusterData(iLeaf);
|
---|
27 | Leaf *leaf = (Leaf*)leafKdTreeClusterData->getEntity();
|
---|
28 | d = d + leaf->getPosition().dotProduct(normal);
|
---|
29 | }
|
---|
30 | d = - d / entityCluster->getNumEntitiesClusterData();
|
---|
31 |
|
---|
32 | TiXmlNode *billboardNode;
|
---|
33 | TiXmlNode *coord4dNode;
|
---|
34 | TiXmlNode *quadTopRightCornerNode;
|
---|
35 | TiXmlNode *quadTopLeftCornerNode;
|
---|
36 | TiXmlNode *quadBottomRightCornerNode;
|
---|
37 | TiXmlNode *quadBottomLeftCornerNode;
|
---|
38 | TiXmlNode *axisXNode;
|
---|
39 | TiXmlNode *axisYNode;
|
---|
40 | TiXmlNode *axisZNode;
|
---|
41 | TiXmlNode *leavesNode;
|
---|
42 | TiXmlNode *leafNode;
|
---|
43 | billboardNode = parentNode->ToElement()->InsertEndChild(TiXmlElement("billboard"))->ToElement();
|
---|
44 |
|
---|
45 | coord4dNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("coord4d"))->ToElement();
|
---|
46 | Ogre::String sNX = Ogre::StringConverter::toString(normal.x);
|
---|
47 | coord4dNode->ToElement()->SetAttribute("nx",sNX.c_str());
|
---|
48 | Ogre::String sNY = Ogre::StringConverter::toString(normal.y);
|
---|
49 | coord4dNode->ToElement()->SetAttribute("ny",sNY.c_str());
|
---|
50 | Ogre::String sNZ = Ogre::StringConverter::toString(normal.z);
|
---|
51 | coord4dNode->ToElement()->SetAttribute("nz",sNZ.c_str());
|
---|
52 | Ogre::String sD = Ogre::StringConverter::toString(d);
|
---|
53 | coord4dNode->ToElement()->SetAttribute("d",sD.c_str());
|
---|
54 |
|
---|
55 | quadTopLeftCornerNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("topLeft"))->ToElement();
|
---|
56 | Ogre::String sTLX = Ogre::StringConverter::toString(getQuadTopLeftCorner().x);
|
---|
57 | quadTopLeftCornerNode->ToElement()->SetAttribute("x",sTLX.c_str());
|
---|
58 | Ogre::String sTLY = Ogre::StringConverter::toString(getQuadTopLeftCorner().y);
|
---|
59 | quadTopLeftCornerNode->ToElement()->SetAttribute("y",sTLY.c_str());
|
---|
60 | Ogre::String sTLZ = Ogre::StringConverter::toString(getQuadTopLeftCorner().z);
|
---|
61 | quadTopLeftCornerNode->ToElement()->SetAttribute("z",sTLZ.c_str());
|
---|
62 |
|
---|
63 | quadTopRightCornerNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("topRight"))->ToElement();
|
---|
64 | Ogre::String sTRX = Ogre::StringConverter::toString(getQuadTopRightCorner().x);
|
---|
65 | quadTopRightCornerNode->ToElement()->SetAttribute("x",sTRX.c_str());
|
---|
66 | Ogre::String sTRY = Ogre::StringConverter::toString(getQuadTopRightCorner().y);
|
---|
67 | quadTopRightCornerNode->ToElement()->SetAttribute("y",sTRY.c_str());
|
---|
68 | Ogre::String sTRZ = Ogre::StringConverter::toString(getQuadTopRightCorner().z);
|
---|
69 | quadTopRightCornerNode->ToElement()->SetAttribute("z",sTRZ.c_str());
|
---|
70 |
|
---|
71 | quadBottomRightCornerNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("bottomRight"))->ToElement();
|
---|
72 | Ogre::String sBRX = Ogre::StringConverter::toString(getQuadBottomRightCorner().x);
|
---|
73 | quadBottomRightCornerNode->ToElement()->SetAttribute("x",sBRX.c_str());
|
---|
74 | Ogre::String sBRY = Ogre::StringConverter::toString(getQuadBottomRightCorner().y);
|
---|
75 | quadBottomRightCornerNode->ToElement()->SetAttribute("y",sBRY.c_str());
|
---|
76 | Ogre::String sBRZ = Ogre::StringConverter::toString(getQuadBottomRightCorner().z);
|
---|
77 | quadBottomRightCornerNode->ToElement()->SetAttribute("z",sBRZ.c_str());
|
---|
78 |
|
---|
79 | quadBottomLeftCornerNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("bottomLeft"))->ToElement();
|
---|
80 | Ogre::String sBLX = Ogre::StringConverter::toString(getQuadBottomLeftCorner().x);
|
---|
81 | quadBottomLeftCornerNode->ToElement()->SetAttribute("x",sBLX.c_str());
|
---|
82 | Ogre::String sBLY = Ogre::StringConverter::toString(getQuadBottomLeftCorner().y);
|
---|
83 | quadBottomLeftCornerNode->ToElement()->SetAttribute("y",sBLY.c_str());
|
---|
84 | Ogre::String sBLZ = Ogre::StringConverter::toString(getQuadBottomLeftCorner().z);
|
---|
85 | quadBottomLeftCornerNode->ToElement()->SetAttribute("z",sBLZ.c_str());
|
---|
86 |
|
---|
87 | axisYNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("axisX"))->ToElement();
|
---|
88 | Ogre::String sAXX = Ogre::StringConverter::toString(getAxisX().x);
|
---|
89 | axisYNode->ToElement()->SetAttribute("x",sAXX.c_str());
|
---|
90 | Ogre::String sAXY = Ogre::StringConverter::toString(getAxisX().y);
|
---|
91 | axisYNode->ToElement()->SetAttribute("y",sAXY.c_str());
|
---|
92 | Ogre::String sAXZ = Ogre::StringConverter::toString(getAxisX().z);
|
---|
93 | axisYNode->ToElement()->SetAttribute("z",sAXZ.c_str());
|
---|
94 |
|
---|
95 | axisYNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("axisY"))->ToElement();
|
---|
96 | Ogre::String sAYX = Ogre::StringConverter::toString(getAxisY().x);
|
---|
97 | axisYNode->ToElement()->SetAttribute("x",sAYX.c_str());
|
---|
98 | Ogre::String sAYY = Ogre::StringConverter::toString(getAxisY().y);
|
---|
99 | axisYNode->ToElement()->SetAttribute("y",sAYY.c_str());
|
---|
100 | Ogre::String sAYZ = Ogre::StringConverter::toString(getAxisY().z);
|
---|
101 | axisYNode->ToElement()->SetAttribute("z",sAYZ.c_str());
|
---|
102 |
|
---|
103 | axisZNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("axisZ"))->ToElement();
|
---|
104 | Ogre::String sAZX = Ogre::StringConverter::toString(getAxisZ().x);
|
---|
105 | axisZNode->ToElement()->SetAttribute("x",sAZX.c_str());
|
---|
106 | Ogre::String sAZY = Ogre::StringConverter::toString(getAxisZ().y);
|
---|
107 | axisZNode->ToElement()->SetAttribute("y",sAZY.c_str());
|
---|
108 | Ogre::String sAZZ = Ogre::StringConverter::toString(getAxisZ().z);
|
---|
109 | axisZNode->ToElement()->SetAttribute("z",sAZZ.c_str());
|
---|
110 |
|
---|
111 | leavesNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("leaves"))->ToElement();
|
---|
112 | Ogre::String sLeaves = Ogre::StringConverter::toString(entityCluster->getNumEntitiesClusterData());
|
---|
113 | leavesNode->ToElement()->SetAttribute("count",sLeaves.c_str());
|
---|
114 |
|
---|
115 | for (unsigned int iLeaf = 0; iLeaf < entityCluster->getNumEntitiesClusterData(); iLeaf++)
|
---|
116 | {
|
---|
117 | LeafKdTreeClusterData *leafKdTreeClusterData = (LeafKdTreeClusterData*)entityCluster->getEntityClusterData(iLeaf);
|
---|
118 | Leaf *leaf = (Leaf*)leafKdTreeClusterData->getEntity();
|
---|
119 | leafNode = leavesNode->ToElement()->InsertEndChild(TiXmlElement("leaf"))->ToElement();
|
---|
120 | Ogre::String sLeaf = Ogre::StringConverter::toString(leaf->getEntityHandle());
|
---|
121 | leafNode->ToElement()->SetAttribute("id",sLeaf.c_str());
|
---|
122 | } |
---|
123 | } |
---|
124 | |
---|
125 | void BillboardKdTreeClusterData::generateBillboardBoundingQuad() |
---|
126 | {
|
---|
127 |
|
---|
128 | Ogre::Vector3 normal = getNormal();
|
---|
129 | Ogre::Vector3 planePosition;
|
---|
130 | float d = getD();
|
---|
131 |
|
---|
132 | normal.normalise();
|
---|
133 |
|
---|
134 | if ((abs(normal[0] > abs(normal[1])) && (abs(normal[0] > abs(normal[2])))))
|
---|
135 | {
|
---|
136 | planePosition[0] = -d / normal[0];
|
---|
137 | planePosition[1] = 0;
|
---|
138 | planePosition[2] = 0;
|
---|
139 | }
|
---|
140 | else if ((abs(normal[1] > abs(normal[0])) && (abs(normal[1] > abs(normal[2])))))
|
---|
141 | {
|
---|
142 | planePosition[0] = 0;
|
---|
143 | planePosition[1] = -d / normal[1];
|
---|
144 | planePosition[2] = 0;
|
---|
145 | }
|
---|
146 | else
|
---|
147 | {
|
---|
148 | planePosition[0] = 0;
|
---|
149 | planePosition[1] = 0;
|
---|
150 | planePosition[2] = -d / normal[2];
|
---|
151 | }
|
---|
152 |
|
---|
153 | mAxisX = normal.perpendicular();
|
---|
154 | mAxisX.normalise();
|
---|
155 | mAxisY = normal.crossProduct(mAxisX);
|
---|
156 | mAxisY.normalise();
|
---|
157 | mAxisZ = normal;
|
---|
158 |
|
---|
159 | Ogre::Matrix4 coordPlane;
|
---|
160 | Ogre::Matrix4 constCoord;
|
---|
161 | Ogre::Matrix4 invMCoordPlane;
|
---|
162 |
|
---|
163 | coordPlane[0][0] = mAxisX.x;
|
---|
164 | coordPlane[0][1] = mAxisX.y;
|
---|
165 | coordPlane[0][2] = mAxisX.z;
|
---|
166 | coordPlane[0][3] = 0.0f;
|
---|
167 | coordPlane[1][0] = mAxisY.x;
|
---|
168 | coordPlane[1][1] = mAxisY.y;
|
---|
169 | coordPlane[1][2] = mAxisY.z;
|
---|
170 | coordPlane[1][3] = 0.0f;
|
---|
171 | coordPlane[2][0] = mAxisZ.x;
|
---|
172 | coordPlane[2][1] = mAxisZ.y;
|
---|
173 | coordPlane[2][2] = mAxisZ.z;
|
---|
174 | coordPlane[2][3] = 0.0f;
|
---|
175 | coordPlane[3][0] = planePosition.x;
|
---|
176 | coordPlane[3][1] = planePosition.y;
|
---|
177 | coordPlane[3][2] = planePosition.z;
|
---|
178 | coordPlane[3][3] = 1.0f;
|
---|
179 |
|
---|
180 | invMCoordPlane = coordPlane.inverse();
|
---|
181 |
|
---|
182 | constCoord[0][0] = 1.0f;
|
---|
183 | constCoord[0][1] = 0.0f;
|
---|
184 | constCoord[0][2] = 0.0f;
|
---|
185 | constCoord[0][3] = 0.0f;
|
---|
186 | constCoord[1][0] = 0.0f;
|
---|
187 | constCoord[1][1] = 1.0f;
|
---|
188 | constCoord[1][2] = 0.0f;
|
---|
189 | constCoord[1][3] = 0.0f;
|
---|
190 | constCoord[2][0] = 0.0f;
|
---|
191 | constCoord[2][1] = 0.0f;
|
---|
192 | constCoord[2][2] = 0.0f;
|
---|
193 | constCoord[2][3] = 0.0f;
|
---|
194 | constCoord[3][0] = 0.0f;
|
---|
195 | constCoord[3][1] = 0.0f;
|
---|
196 | constCoord[3][2] = 0.0f;
|
---|
197 | constCoord[3][3] = 1.0f;
|
---|
198 |
|
---|
199 | float xMax = -FLT_MAX;
|
---|
200 | float xMin = FLT_MAX;
|
---|
201 | float yMax = -FLT_MAX;
|
---|
202 | float yMin = FLT_MAX;
|
---|
203 |
|
---|
204 | Ogre::Vector3 vXmax;
|
---|
205 | Ogre::Vector3 vXmin;
|
---|
206 | Ogre::Vector3 vYmax;
|
---|
207 | Ogre::Vector3 vYmin;
|
---|
208 |
|
---|
209 | BBC::EntityCluster *entityCluster = getEntityCluster();
|
---|
210 | BBC::Entity *entity = entityCluster->getEntity();
|
---|
211 |
|
---|
212 | for (unsigned int iVertex = 0; iVertex < entity->getSubEntity(0)->getNumVertices(); iVertex++)
|
---|
213 | {
|
---|
214 | Ogre::Vector3 position = entity->getSubEntity(0)->getPosition(iVertex);
|
---|
215 | Ogre::Vector4 projPointP1d4 = Ogre::Vector4(position.x,position.y,position.z,1.0f) * invMCoordPlane * constCoord * coordPlane;
|
---|
216 |
|
---|
217 | // The point projected in the plane
|
---|
218 | Ogre::Vector3 projPointP1(projPointP1d4.x,projPointP1d4.y,projPointP1d4.z);
|
---|
219 |
|
---|
220 | float v1 = normal.dotProduct(planePosition);
|
---|
221 | float v2 = normal.dotProduct(position);
|
---|
222 | float t = v1 - v2;
|
---|
223 | projPointP1 = position + (normal * t);
|
---|
224 |
|
---|
225 | float x1 = mAxisX.dotProduct(projPointP1 - planePosition);
|
---|
226 | float y1 = mAxisY.dotProduct(projPointP1 - planePosition);
|
---|
227 | float z1 = mAxisZ.dotProduct(projPointP1 - planePosition);
|
---|
228 |
|
---|
229 | if (x1 > xMax)
|
---|
230 | {
|
---|
231 | xMax = x1;
|
---|
232 | vXmax = projPointP1;
|
---|
233 | }
|
---|
234 | if (x1 < xMin)
|
---|
235 | {
|
---|
236 | xMin = x1;
|
---|
237 | vXmin = projPointP1;
|
---|
238 | }
|
---|
239 | if (y1 > yMax)
|
---|
240 | {
|
---|
241 | yMax = y1;
|
---|
242 | vYmax = projPointP1;
|
---|
243 | }
|
---|
244 | if (y1 < yMin)
|
---|
245 | {
|
---|
246 | yMin = y1;
|
---|
247 | vYmin = projPointP1;
|
---|
248 | }
|
---|
249 | }
|
---|
250 |
|
---|
251 | Ogre::Vector3 aP;
|
---|
252 | Ogre::Vector3 bP;
|
---|
253 | Ogre::Vector3 pP;
|
---|
254 | Ogre::Vector3 abV;
|
---|
255 | Ogre::Vector3 apV;
|
---|
256 | Ogre::Vector3 dProdV;
|
---|
257 | float aLength;
|
---|
258 | float abLength;
|
---|
259 | float dist;
|
---|
260 | Ogre::Vector3 intersectP;
|
---|
261 |
|
---|
262 | aP = vYmin;
|
---|
263 | bP = vYmin + mAxisX;
|
---|
264 | pP = vXmin;
|
---|
265 | abV = bP - aP;
|
---|
266 | apV = pP - aP;
|
---|
267 | dProdV = abV.crossProduct(apV);
|
---|
268 | aLength = dProdV.length();
|
---|
269 | abLength = abV.length();
|
---|
270 | dist = aLength / abLength;
|
---|
271 | mBillboardCorners[QUAD_TOP_LEFT] = pP + (mAxisY * (-dist));
|
---|
272 |
|
---|
273 | aP = vYmax;
|
---|
274 | bP = vYmax + mAxisX;
|
---|
275 | pP = vXmax;
|
---|
276 | abV = bP - aP;
|
---|
277 | apV = pP - aP;
|
---|
278 | dProdV = abV.crossProduct(apV);
|
---|
279 | aLength = dProdV.length();
|
---|
280 | abLength = abV.length();
|
---|
281 | dist = aLength / abLength;
|
---|
282 | mBillboardCorners[QUAD_BOTTOM_RIGHT] = pP + (mAxisY * dist);
|
---|
283 |
|
---|
284 | aP = vXmax;
|
---|
285 | bP = vXmax + mAxisY;
|
---|
286 | pP = vYmin;
|
---|
287 | abV = bP - aP;
|
---|
288 | apV = pP - aP;
|
---|
289 | dProdV = abV.crossProduct(apV);
|
---|
290 | aLength = dProdV.length();
|
---|
291 | abLength = abV.length();
|
---|
292 | dist = aLength / abLength;
|
---|
293 | mBillboardCorners[QUAD_BOTTOM_LEFT] = pP + (mAxisX * dist);
|
---|
294 |
|
---|
295 | Ogre::Vector3 vDirWidth = mBillboardCorners[QUAD_BOTTOM_LEFT] - mBillboardCorners[QUAD_BOTTOM_RIGHT];
|
---|
296 | float distWidth = vDirWidth.length();
|
---|
297 | mBillboardCorners[QUAD_TOP_RIGHT] = mBillboardCorners[QUAD_TOP_LEFT] + (mAxisY * distWidth); |
---|
298 | } |
---|
299 | |
---|
300 | } |
---|