/*************************************************************************** collisionmodel.cpp - A collision model ------------------- begin : wo sep 24 2003 copyright : (C) 2003 by CJP email : cornware-cjp@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 #include #include "collisionmodel.h" #include "datafile.h" #include "glbfile.h" CCollisionModel::CCollisionModel(CDataManager *manager) : CDataObject(manager, CDataObject::eCollisionModel) {} CCollisionModel::~CCollisionModel(){ } CString CCollisionModel::getSubset() const { return m_Subset; } bool CCollisionModel::load(const CString &filename, const CParamList &list) { CDataObject::load(filename, list); return loadGLB(filename, list); } bool CCollisionModel::loadGLB(const CString &filename, const CParamList &list) { CGLBFile f; if(!f.load(filename)) return false; m_Subset = m_ParamList.getValue("subset", ""); vector matarray; if(m_Subset != "") matarray = m_DataManager->getSubset(CDataObject::eMaterial, m_Subset); //Initial bounding volume state m_BSphere_r = 0.0; m_OBB_min = CVector(0,0,0); m_OBB_max = CVector(0,0,0); //initial state CMaterial *mat = NULL; for(unsigned int p=0; p < f.m_Primitives.size(); p++) { CGLBFile::SPrimitive &pr = f.m_Primitives[p]; if((pr.material.LODs & (16+32)) == 0) continue; //only collision+surface primitives //printf(" Processing primitive %s\n", pr.Name.c_str()); if(pr.material.Texture < 0) { mat = NULL; } //TODO: assign a number for non-texturised materials else { if(pr.material.Texture < int(matarray.size())) {mat = (CMaterial *)(matarray[pr.material.Texture]);} else {mat = NULL;} } for(unsigned int t=0; t < pr.index.size()/3; t++) { CVector v1 = pr.vertex[pr.index[3*t]].pos; CVector v2 = pr.vertex[pr.index[3*t+1]].pos; CVector v3 = pr.vertex[pr.index[3*t+2]].pos; m_Faces.push_back(CCollisionFace()); CCollisionFace &theFace = m_Faces.back(); theFace.push_back(v1); theFace.push_back(v2); theFace.push_back(v3); theFace.isSurface = (pr.material.LODs & 32) != 0; //if(theFace.isSurface) printf("%d is is a surface\n", t); theFace.isWater = (pr.material.LODs & 32) != 0 && (pr.material.LODs & 16) != 0; if(theFace.isWater) theFace.isSurface = false; theFace.material = mat; theFace.reverse = false; //printf(" Face %d: %d points\n", t, theFace.size()); } } determineOBVs(); determinePlaneEquations(); return true; } void CCollisionModel::determineOBVs() { //Generating oriented bounding volumes for(unsigned int i=0; i m_BSphere_r) m_BSphere_r = v.abs(); if(v.x > m_OBB_max.x) m_OBB_max.x = v.x; if(v.y > m_OBB_max.y) m_OBB_max.y = v.y; if(v.z > m_OBB_max.z) m_OBB_max.z = v.z; if(v.x < m_OBB_min.x) m_OBB_min.x = v.x; if(v.y < m_OBB_min.y) m_OBB_min.y = v.y; if(v.z < m_OBB_min.z) m_OBB_min.z = v.z; } } } void CCollisionModel::determinePlaneEquations() { //Determine a plane equation for each face for(unsigned int i=0; i dist2) {p2 = theFace[j]; dist2 = d2; index_2nd = j;} } //the third point: try to maximise cross product CVector crosspr; float crosspr_abs2 = 0.0; bool reverse = false; //2 and 3 in reverse order CVector p1p2 = p2 - p1; for(unsigned int j=1; j crosspr_abs2) { crosspr = cp; crosspr_abs2 = abs2; reverse = (j