#include "LBBCBillboardKdTreeClusterData.h" namespace LBBC { BillboardKdTreeClusterData::BillboardKdTreeClusterData() { } BillboardKdTreeClusterData::~BillboardKdTreeClusterData() { } void BillboardKdTreeClusterData::readBillboardClusterData(TiXmlNode *parentNode) { } void BillboardKdTreeClusterData::writeBillboardClusterData(TiXmlNode *parentNode) { BBC::EntityCluster *entityCluster = getEntityCluster(); Ogre::Vector3 normal = getNormal(); normal.normalise(); float d = 0; for (unsigned int iLeaf = 0; iLeaf < entityCluster->getNumEntitiesClusterData(); iLeaf++) { LeafKdTreeClusterData *leafKdTreeClusterData = (LeafKdTreeClusterData*)entityCluster->getEntityClusterData(iLeaf); Leaf *leaf = (Leaf*)leafKdTreeClusterData->getEntity(); d = d + leaf->getPosition().dotProduct(normal); } d = - d / entityCluster->getNumEntitiesClusterData(); TiXmlNode *billboardNode; TiXmlNode *coord4dNode; TiXmlNode *quadTopRightCornerNode; TiXmlNode *quadTopLeftCornerNode; TiXmlNode *quadBottomRightCornerNode; TiXmlNode *quadBottomLeftCornerNode; TiXmlNode *axisXNode; TiXmlNode *axisYNode; TiXmlNode *axisZNode; TiXmlNode *leavesNode; TiXmlNode *leafNode; billboardNode = parentNode->ToElement()->InsertEndChild(TiXmlElement("billboard"))->ToElement(); coord4dNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("coord4d"))->ToElement(); Ogre::String sNX = Ogre::StringConverter::toString(normal.x); coord4dNode->ToElement()->SetAttribute("nx",sNX.c_str()); Ogre::String sNY = Ogre::StringConverter::toString(normal.y); coord4dNode->ToElement()->SetAttribute("ny",sNY.c_str()); Ogre::String sNZ = Ogre::StringConverter::toString(normal.z); coord4dNode->ToElement()->SetAttribute("nz",sNZ.c_str()); Ogre::String sD = Ogre::StringConverter::toString(d); coord4dNode->ToElement()->SetAttribute("d",sD.c_str()); quadTopLeftCornerNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("topLeft"))->ToElement(); Ogre::String sTLX = Ogre::StringConverter::toString(getQuadTopLeftCorner().x); quadTopLeftCornerNode->ToElement()->SetAttribute("x",sTLX.c_str()); Ogre::String sTLY = Ogre::StringConverter::toString(getQuadTopLeftCorner().y); quadTopLeftCornerNode->ToElement()->SetAttribute("y",sTLY.c_str()); Ogre::String sTLZ = Ogre::StringConverter::toString(getQuadTopLeftCorner().z); quadTopLeftCornerNode->ToElement()->SetAttribute("z",sTLZ.c_str()); quadTopRightCornerNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("topRight"))->ToElement(); Ogre::String sTRX = Ogre::StringConverter::toString(getQuadTopRightCorner().x); quadTopRightCornerNode->ToElement()->SetAttribute("x",sTRX.c_str()); Ogre::String sTRY = Ogre::StringConverter::toString(getQuadTopRightCorner().y); quadTopRightCornerNode->ToElement()->SetAttribute("y",sTRY.c_str()); Ogre::String sTRZ = Ogre::StringConverter::toString(getQuadTopRightCorner().z); quadTopRightCornerNode->ToElement()->SetAttribute("z",sTRZ.c_str()); quadBottomRightCornerNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("bottomRight"))->ToElement(); Ogre::String sBRX = Ogre::StringConverter::toString(getQuadBottomRightCorner().x); quadBottomRightCornerNode->ToElement()->SetAttribute("x",sBRX.c_str()); Ogre::String sBRY = Ogre::StringConverter::toString(getQuadBottomRightCorner().y); quadBottomRightCornerNode->ToElement()->SetAttribute("y",sBRY.c_str()); Ogre::String sBRZ = Ogre::StringConverter::toString(getQuadBottomRightCorner().z); quadBottomRightCornerNode->ToElement()->SetAttribute("z",sBRZ.c_str()); quadBottomLeftCornerNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("bottomLeft"))->ToElement(); Ogre::String sBLX = Ogre::StringConverter::toString(getQuadBottomLeftCorner().x); quadBottomLeftCornerNode->ToElement()->SetAttribute("x",sBLX.c_str()); Ogre::String sBLY = Ogre::StringConverter::toString(getQuadBottomLeftCorner().y); quadBottomLeftCornerNode->ToElement()->SetAttribute("y",sBLY.c_str()); Ogre::String sBLZ = Ogre::StringConverter::toString(getQuadBottomLeftCorner().z); quadBottomLeftCornerNode->ToElement()->SetAttribute("z",sBLZ.c_str()); axisYNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("axisX"))->ToElement(); Ogre::String sAXX = Ogre::StringConverter::toString(getAxisX().x); axisYNode->ToElement()->SetAttribute("x",sAXX.c_str()); Ogre::String sAXY = Ogre::StringConverter::toString(getAxisX().y); axisYNode->ToElement()->SetAttribute("y",sAXY.c_str()); Ogre::String sAXZ = Ogre::StringConverter::toString(getAxisX().z); axisYNode->ToElement()->SetAttribute("z",sAXZ.c_str()); axisYNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("axisY"))->ToElement(); Ogre::String sAYX = Ogre::StringConverter::toString(getAxisY().x); axisYNode->ToElement()->SetAttribute("x",sAYX.c_str()); Ogre::String sAYY = Ogre::StringConverter::toString(getAxisY().y); axisYNode->ToElement()->SetAttribute("y",sAYY.c_str()); Ogre::String sAYZ = Ogre::StringConverter::toString(getAxisY().z); axisYNode->ToElement()->SetAttribute("z",sAYZ.c_str()); axisZNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("axisZ"))->ToElement(); Ogre::String sAZX = Ogre::StringConverter::toString(getAxisZ().x); axisZNode->ToElement()->SetAttribute("x",sAZX.c_str()); Ogre::String sAZY = Ogre::StringConverter::toString(getAxisZ().y); axisZNode->ToElement()->SetAttribute("y",sAZY.c_str()); Ogre::String sAZZ = Ogre::StringConverter::toString(getAxisZ().z); axisZNode->ToElement()->SetAttribute("z",sAZZ.c_str()); leavesNode = billboardNode->ToElement()->InsertEndChild(TiXmlElement("leaves"))->ToElement(); Ogre::String sLeaves = Ogre::StringConverter::toString(entityCluster->getNumEntitiesClusterData()); leavesNode->ToElement()->SetAttribute("count",sLeaves.c_str()); for (unsigned int iLeaf = 0; iLeaf < entityCluster->getNumEntitiesClusterData(); iLeaf++) { LeafKdTreeClusterData *leafKdTreeClusterData = (LeafKdTreeClusterData*)entityCluster->getEntityClusterData(iLeaf); Leaf *leaf = (Leaf*)leafKdTreeClusterData->getEntity(); leafNode = leavesNode->ToElement()->InsertEndChild(TiXmlElement("leaf"))->ToElement(); Ogre::String sLeaf = Ogre::StringConverter::toString(leaf->getEntityHandle()); leafNode->ToElement()->SetAttribute("id",sLeaf.c_str()); } } void BillboardKdTreeClusterData::generateBillboardBoundingQuad() { Ogre::Vector3 normal = getNormal(); Ogre::Vector3 planePosition; float d = getD(); normal.normalise(); if ((abs(normal[0] > abs(normal[1])) && (abs(normal[0] > abs(normal[2]))))) { planePosition[0] = -d / normal[0]; planePosition[1] = 0; planePosition[2] = 0; } else if ((abs(normal[1] > abs(normal[0])) && (abs(normal[1] > abs(normal[2]))))) { planePosition[0] = 0; planePosition[1] = -d / normal[1]; planePosition[2] = 0; } else { planePosition[0] = 0; planePosition[1] = 0; planePosition[2] = -d / normal[2]; } mAxisX = normal.perpendicular(); mAxisX.normalise(); mAxisY = normal.crossProduct(mAxisX); mAxisY.normalise(); mAxisZ = normal; Ogre::Matrix4 coordPlane; Ogre::Matrix4 constCoord; Ogre::Matrix4 invMCoordPlane; coordPlane[0][0] = mAxisX.x; coordPlane[0][1] = mAxisX.y; coordPlane[0][2] = mAxisX.z; coordPlane[0][3] = 0.0f; coordPlane[1][0] = mAxisY.x; coordPlane[1][1] = mAxisY.y; coordPlane[1][2] = mAxisY.z; coordPlane[1][3] = 0.0f; coordPlane[2][0] = mAxisZ.x; coordPlane[2][1] = mAxisZ.y; coordPlane[2][2] = mAxisZ.z; coordPlane[2][3] = 0.0f; coordPlane[3][0] = planePosition.x; coordPlane[3][1] = planePosition.y; coordPlane[3][2] = planePosition.z; coordPlane[3][3] = 1.0f; invMCoordPlane = coordPlane.inverse(); constCoord[0][0] = 1.0f; constCoord[0][1] = 0.0f; constCoord[0][2] = 0.0f; constCoord[0][3] = 0.0f; constCoord[1][0] = 0.0f; constCoord[1][1] = 1.0f; constCoord[1][2] = 0.0f; constCoord[1][3] = 0.0f; constCoord[2][0] = 0.0f; constCoord[2][1] = 0.0f; constCoord[2][2] = 0.0f; constCoord[2][3] = 0.0f; constCoord[3][0] = 0.0f; constCoord[3][1] = 0.0f; constCoord[3][2] = 0.0f; constCoord[3][3] = 1.0f; float xMax = -FLT_MAX; float xMin = FLT_MAX; float yMax = -FLT_MAX; float yMin = FLT_MAX; Ogre::Vector3 vXmax; Ogre::Vector3 vXmin; Ogre::Vector3 vYmax; Ogre::Vector3 vYmin; BBC::EntityCluster *entityCluster = getEntityCluster(); BBC::Entity *entity = entityCluster->getEntity(); for (unsigned int iVertex = 0; iVertex < entity->getSubEntity(0)->getNumVertices(); iVertex++) { Ogre::Vector3 position = entity->getSubEntity(0)->getPosition(iVertex); Ogre::Vector4 projPointP1d4 = Ogre::Vector4(position.x,position.y,position.z,1.0f) * invMCoordPlane * constCoord * coordPlane; // The point projected in the plane Ogre::Vector3 projPointP1(projPointP1d4.x,projPointP1d4.y,projPointP1d4.z); float v1 = normal.dotProduct(planePosition); float v2 = normal.dotProduct(position); float t = v1 - v2; projPointP1 = position + (normal * t); float x1 = mAxisX.dotProduct(projPointP1 - planePosition); float y1 = mAxisY.dotProduct(projPointP1 - planePosition); float z1 = mAxisZ.dotProduct(projPointP1 - planePosition); if (x1 > xMax) { xMax = x1; vXmax = projPointP1; } if (x1 < xMin) { xMin = x1; vXmin = projPointP1; } if (y1 > yMax) { yMax = y1; vYmax = projPointP1; } if (y1 < yMin) { yMin = y1; vYmin = projPointP1; } } Ogre::Vector3 aP; Ogre::Vector3 bP; Ogre::Vector3 pP; Ogre::Vector3 abV; Ogre::Vector3 apV; Ogre::Vector3 dProdV; float aLength; float abLength; float dist; Ogre::Vector3 intersectP; aP = vYmin; bP = vYmin + mAxisX; pP = vXmin; abV = bP - aP; apV = pP - aP; dProdV = abV.crossProduct(apV); aLength = dProdV.length(); abLength = abV.length(); dist = aLength / abLength; mBillboardCorners[QUAD_TOP_LEFT] = pP + (mAxisY * (-dist)); aP = vYmax; bP = vYmax + mAxisX; pP = vXmax; abV = bP - aP; apV = pP - aP; dProdV = abV.crossProduct(apV); aLength = dProdV.length(); abLength = abV.length(); dist = aLength / abLength; mBillboardCorners[QUAD_BOTTOM_RIGHT] = pP + (mAxisY * dist); aP = vXmax; bP = vXmax + mAxisY; pP = vYmin; abV = bP - aP; apV = pP - aP; dProdV = abV.crossProduct(apV); aLength = dProdV.length(); abLength = abV.length(); dist = aLength / abLength; mBillboardCorners[QUAD_BOTTOM_LEFT] = pP + (mAxisX * dist); Ogre::Vector3 vDirWidth = mBillboardCorners[QUAD_BOTTOM_LEFT] - mBillboardCorners[QUAD_BOTTOM_RIGHT]; float distWidth = vDirWidth.length(); mBillboardCorners[QUAD_TOP_RIGHT] = mBillboardCorners[QUAD_TOP_LEFT] + (mAxisY * distWidth); } }