/* * PVVMUD a 3D MUD * Copyright (C) 1998-1999 Programvareverkstedet (pvv@pvv.org) * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "pvvmud.H" #include #include #include "mudtypes.h" #include "geometry.H" #include "vector.H" /******************************************************************************* * * Constructor for CVertex * ******************************************************************************/ CVertex::CVertex(double x, double y, double z){ m_coord[0] = x; m_coord[1] = y; m_coord[2] = z; } /******************************************************************************* * * Get coordinnnates from CVertex * ******************************************************************************/ VertexCoord_t * CVertex::getCoord(){ return m_coord; } /******************************************************************************* * * Set coordinates in CVertex * ******************************************************************************/ void CVertex::setCoord(double x, double y, double z){ m_coord[0] = x; m_coord[1] = y; m_coord[2] = z; } /******************************************************************************* * * Constructor for CTexCoord * ******************************************************************************/ CTexCoord::CTexCoord(double u, double v){ m_coord[0] = u; m_coord[1] = v; } /******************************************************************************* * * Get coordinates from CTexCoord * ******************************************************************************/ TexCoordCoord_t * CTexCoord::getCoord(){ return m_coord; } /******************************************************************************* * * Set coordinates in CTexCoord * ******************************************************************************/ void CTexCoord::setCoord(double u, double v){ m_coord[0] = u; m_coord[1] = v; } double CTexCoord::getU(){ return m_coord[0]; } double CTexCoord::getV(){ return m_coord[1]; } /******************************************************************************* * * Constructor for CNormal * ******************************************************************************/ CNormal::CNormal(double x, double y, double z){ m_vector[0] = x; m_vector[1] = y; m_vector[2] = z; } /******************************************************************************* * * Get coordinates from CNormal * ******************************************************************************/ NormalVector_t * CNormal::getVector(){ return m_vector; } /******************************************************************************* * * Set coordinates in CNormal * ******************************************************************************/ void CNormal::setVector(double x, double y, double z){ m_vector[0] = x; m_vector[1] = y; m_vector[2] = z; } double CNormal::getX(){ return m_vector[0]; } double CNormal::getY(){ return m_vector[1]; } double CNormal::getZ(){ return m_vector[2]; } /******************************************************************************* * * Constructor for CVertexList * ******************************************************************************/ CVertexList::CVertexList(int size):CObjectArray(size){ } /******************************************************************************* * * Destructor for CVertexList * ******************************************************************************/ CVertexList::~CVertexList(){ deleteAll(); } /******************************************************************************* * * Add Vertex to CVertexList * ******************************************************************************/ int CVertexList::add( double x, double y, double z ){ CVertex * vertex = new CVertex(x, y, z); return CObjectArray::add((CObject*)vertex); }; /******************************************************************************* * * Get Vertex from CVertexList * ******************************************************************************/ void CVertexList::get( int index, double * x, double * y, double * z ){ VertexCoord_t * coord = get(index); *x = coord[0]; *y = coord[1]; *z = coord[2]; } VertexCoord_t * CVertexList::get( int index ){ CVertex * cv = (CVertex*)getItem(index); return cv->getCoord(); } CVertex * CVertexList::getVertex( int index ){ return (CVertex*)getItem(index); } /******************************************************************************* * * Set Vertex in CVertexList * ******************************************************************************/ void CVertexList::set( int index, double x, double y, double z ){ CVertex * cv = (CVertex*)getItem( index ); if (cv == NULL) { cv = new CVertex(x,y,z); CObjectArray::set(index,(CObject*)cv); } else cv->setCoord(x, y, z); } /******************************************************************************* * Get number of vertices * ******************************************************************************/ int CVertexList::getSize() { return this->getNumElements(); } /******************************************************************************* * * Constructor for CNormalList * ******************************************************************************/ CNormalList::CNormalList(int size) : CObjectArray(size){ } /******************************************************************************* * * Destructor for CNormalList * ******************************************************************************/ CNormalList::~CNormalList(){ deleteAll(); } /******************************************************************************* * * Add Normal to CNormalList * ******************************************************************************/ int CNormalList::add( double x, double y, double z ){ CNormal * cn = new CNormal(x, y, z); return CObjectArray::add((CNormal*)cn); } void CNormalList::set( int index, double x, double y, double z ){ CNormal * cn = (CNormal*)getItem( index ); if (cn == NULL) { cn = new CNormal(x, y, z); CObjectArray::set(index,(CObject*)cn); } else cn->setVector(x, y, z); } /******************************************************************************* * * Get Normal from CNormalList * ******************************************************************************/ void CNormalList::get( int index, double * x, double * y, double * z ){ NormalVector_t * vector = get(index); *x = vector[0]; *y = vector[1]; *z = vector[2]; } NormalVector_t * CNormalList::get( int index ) { CNormal * cn = (CNormal*)getItem( index ); return cn->getVector(); } CNormal * CNormalList::getNormal( int index ){ return (CNormal*)getItem(index); } /******************************************************************************* * * Constructor for CTexCoordList * ******************************************************************************/ CTexCoordList::CTexCoordList(int size) : CObjectArray(size){ } /******************************************************************************* * * Destructor for CTexCoordList * ******************************************************************************/ CTexCoordList::~CTexCoordList(){ deleteAll(); } /******************************************************************************* * * Add TexCoord to CTexCoordList * ******************************************************************************/ int CTexCoordList::add( double u, double v){ CTexCoord * ctc = new CTexCoord( u, v ); return CObjectArray::add( (CObject*)ctc ); } void CTexCoordList::set( int index, double u, double v){ CTexCoord * ctc = (CTexCoord*)getItem( index ); if (ctc == NULL) { ctc = new CTexCoord(u,v); CObjectArray::set( index, (CObject*)ctc ); } else ctc->setCoord(u, v); } /******************************************************************************* * * Get TexCoord from CTexCoordList * ******************************************************************************/ void CTexCoordList::get( int index, double * u, double * v ){ TexCoordCoord_t * coord = get(index); *u = coord[0]; *v = coord[1]; } TexCoordCoord_t * CTexCoordList::get( int index ) { CTexCoord * ct = (CTexCoord*)getItem( index ); return ct->getCoord(); } CTexCoord * CTexCoordList::getTexCoord( int index ){ return (CTexCoord*)getItem(index); } /******************************************************************************* * * Constructor for CPolygonList * ******************************************************************************/ CPolygonList::CPolygonList(CGeometry * geometry,int size) : CObjectArray(size){ m_geometry = geometry; } /******************************************************************************* * * Destructor for CPolygonList * ******************************************************************************/ CPolygonList::~CPolygonList(){ deleteAll(); } /******************************************************************************* * * Add polygon to CPolygonList * ******************************************************************************/ int CPolygonList::add( CPolygon * polygon ){ int index = CObjectArray::add( (CObject*)polygon ); polygon->setGeometry( m_geometry ); return index; } void CPolygonList::set(int index, CPolygon * polygon ){ CObjectArray::set(index, (CObject*)polygon ); polygon->setGeometry( m_geometry ); } /******************************************************************************* * * Get Polygon from PolygonList * ******************************************************************************/ CPolygon * CPolygonList::get( int index ){ return (CPolygon*)getItem(index); } /******************************************************************************* * * Constructors for CPolygon * ******************************************************************************/ CPolygon::CPolygon( int type, int materialId, int numVertices, int numNormals, int numTexCoords ){ m_type = type; m_materialId = materialId; m_vertexIndexList = new CIntArray(numVertices); m_normalIndexList = new CIntArray(numNormals); m_texCoordIndexList = new CIntArray(numTexCoords); } /******************************************************************************* * * Destructor for CPolygon * ******************************************************************************/ CPolygon::~CPolygon() { if (m_vertexIndexList != NULL) delete m_vertexIndexList; if (m_normalIndexList != NULL) delete m_normalIndexList; if (m_texCoordIndexList != NULL) delete m_texCoordIndexList; } /******************************************************************************* * * Destructor for CPolygon * ******************************************************************************/ void CPolygon::setGeometry(CGeometry * geometry) { m_geometry = geometry; } /******************************************************************************* * * Get polygon parameters * ******************************************************************************/ void CPolygon::get( int * type, int * materialId, int * numVertices, int * numNormals, int * numTexCoords ){ *type = m_type; *materialId = m_materialId; *numVertices = m_vertexIndexList->getNumElements(); *numNormals = m_normalIndexList->getNumElements(); *numTexCoords = m_texCoordIndexList->getNumElements(); } /****************************************************************************** * * Get polygon type * *****************************************************************************/ int CPolygon::getType(){ return m_type; } /****************************************************************************** * * Set polygon material * *****************************************************************************/ void CPolygon::setMaterial( int materialId ){ m_materialId = materialId; } /****************************************************************************** * * Set polygon material * *****************************************************************************/ int CPolygon::getMaterial(){ return m_materialId; } /******************************************************************************* * * Add vertex index to Polygon * ******************************************************************************/ int CPolygon::addVertexIndex( int vertexIndex ){ return m_vertexIndexList->add( vertexIndex ); } void CPolygon::setVertexIndex( int index, int vertexIndex ){ m_vertexIndexList->set( index, vertexIndex ); } /******************************************************************************* * * Get vertex index from Polygon * ******************************************************************************/ int CPolygon::getVertexIndex( int index ){ return m_vertexIndexList->get( index ); } CVertex * CPolygon::getVertex( int index ){ return m_geometry->getVertex( getVertexIndex(index) ); } /******************************************************************************* * * Add normal index to Polygon * ******************************************************************************/ int CPolygon::addNormalIndex( int normalIndex ){ return m_normalIndexList->add( normalIndex ); } void CPolygon::setNormalIndex( int index, int normalIndex ){ m_normalIndexList->set( index, normalIndex ); } /******************************************************************************* * * Get normal index from Polygon * ******************************************************************************/ int CPolygon::getNormalIndex( int index ){ return m_normalIndexList->get( index ); } CNormal * CPolygon::getNormal( int index ){ return m_geometry->getNormal( index ); } /******************************************************************************* * * Add TexCoord index to Polygon * ******************************************************************************/ int CPolygon::addTexCoordIndex( int texCoordIndex ){ return m_texCoordIndexList->add( texCoordIndex ); } void CPolygon::setTexCoordIndex( int index, int texCoordIndex ){ m_texCoordIndexList->set( index, texCoordIndex ); } /******************************************************************************* * * Get TexCoord index from Polygon * ******************************************************************************/ int CPolygon::getTexCoordIndex( int index ){ return m_texCoordIndexList->get( index ); } CTexCoord * CPolygon::getTexCoord( int index ){ return m_geometry->getTexCoord( index ); } /******************************************************************************* * * Get lists from polygon * ******************************************************************************/ CIntArray * CPolygon::getVertexIList(){ return m_vertexIndexList; } int CPolygon::getNumVertices(){ return m_vertexIndexList->getNumElements(); } CIntArray * CPolygon::getNormalIList(){ return m_normalIndexList; } CIntArray * CPolygon::getTexCoordIList(){ return m_texCoordIndexList; } /////////////////////////////////////////////////////////////////////////////// // distances // Info : Calculate distances from the startingpoint of a beam in the // beams direction to the polygon. // Throws : CException when beam outside polygon // Return : distance to polygon /////////////////////////////////////////////////////////////////////////////// void CPolygon::distances(CDoubleArray & distArray, const CBeam & beam){ int index; switch(m_type){ case POLYGON_POLYGON: cdebug << "CPolygon::distances: POLYGON Not impl!\n"; break; case POLYGON_QUAD_STRIP: cdebug << "CPolygon::distances: QUAD_STRIP Not impl!\n"; break; case POLYGON_TRIANGLE_STRIP: cdebug << "CPolygon::distances: TRIANGLE_STRIP Not impl!\n"; break; case POLYGON_TRIANGLE_FAN: cdebug << "CPolygon::distances: TRIANGLE_FAN Not impl!\n"; break; case POLYGON_QUADS: index = getNumVertices(); while (index > 0){ index -= 4; int inside = true; CVector edge; CPlane p; CVertex * last = getVertex(index+3); for (int ii = 0; ii < 4 && inside; ii++){ CVertex * next = getVertex(index+ii); edge = *next - *last; CVector norm = edge.cross(beam.getDirection()); p = CPlane(*next,norm); if (p.distance(beam.getPoint()) < 0.0) inside = false; last = next; } if (inside){ p = CPlane(*getVertex(index),*getVertex(index+1), *getVertex(index+2)); distArray.add(p.distance(beam.getPoint())); } } break; case POLYGON_TRIANGLES: index = getNumVertices(); while (index > 0){ index -= 3; int inside = true; CVector edge; CPlane p; CVertex * last = getVertex(index+2); for (int ii = 0; ii < 3 && inside; ii++){ CVertex * next = getVertex(index+ii); edge = *next - *last; CVector norm = edge.cross(beam.getDirection()); p = CPlane(*next,norm); if (p.distance(beam.getPoint()) < 0.0) inside = false; last = next; } if (inside){ p = CPlane(*getVertex(index),*getVertex(index+1), *getVertex(index+2)); distArray.add(p.distance(beam.getPoint())); } } break; } } /////////////////////////////////////////////////////////////////////////////// // distances // Info : Calculate distances from the startingpoint of a beam in the // beams direction to the polygon. If it is posible use this // distances(CDoubleArray & distArray, const CBeam & beam); // interface that don't need to alloc memory. // Throws : CException when beam outside polygon // Return : distance to polygon /////////////////////////////////////////////////////////////////////////////// CDoubleArray * CPolygon::distances(const CBeam & beam){ CDoubleArray * distArray = new CDoubleArray; distances(*distArray,beam); return distArray; } /******************************************************************************* * * Constructors for ObjectGeometry * ******************************************************************************/ CGeometry::CGeometry( int objectGeometryId ){ id = objectGeometryId; subid = -1; next = NULL; vertexList = NULL; normalList = NULL; texCoordList = NULL; polygonList = NULL; } CGeometry::CGeometry( int objectGeometryId, int numVertices, int numNormals, int numTexCoords, int numPolygons ){ this->id = objectGeometryId; this->subid = -1; this->next = NULL; this->vertexList = new CVertexList(numVertices); this->normalList = new CNormalList(numNormals); this->texCoordList = new CTexCoordList(numTexCoords); this->polygonList = new CPolygonList(this,numPolygons); } /******************************************************************************* * * Destructor for ObjectGeometry * ******************************************************************************/ CGeometry::~CGeometry() { if (next != NULL) delete next; if (vertexList != NULL) delete vertexList; if (normalList != NULL) delete normalList; if (texCoordList != NULL) delete texCoordList; if (polygonList != NULL) delete polygonList; } /******************************************************************************* * * Create a new Geometry * Note : Used when geometry create subobjects, as done when loading a file. * ******************************************************************************/ CGeometry * CGeometry::newGeometry(int geometryId){ new CGeometry(geometryId); } /******************************************************************************* * * Set max size for all tables in Geometry * ******************************************************************************/ void CGeometry::setSize( int numVertices, int numNormals, int numTexCoords, int numPolygons ){ if (vertexList != NULL) delete vertexList; if (normalList != NULL) delete normalList; if (texCoordList != NULL) delete texCoordList; if (polygonList != NULL) delete polygonList; vertexList = new CVertexList(numVertices); normalList = new CNormalList(numNormals); texCoordList = new CTexCoordList(numTexCoords); polygonList = new CPolygonList(this,numPolygons); } /******************************************************************************* * * Get id for CGeometry * ******************************************************************************/ int CGeometry::getId() { return id; } /******************************************************************************* * * Set id for CGeometry * ******************************************************************************/ void CGeometry::setId(int id){ this->id = id; } /******************************************************************************* * * Set subid for ObjectGeomtery * ******************************************************************************/ void CGeometry::setSubId( int subid ) { this->subid = subid; } /******************************************************************************* * * Get subid to ObjectGeomtry * ******************************************************************************/ int CGeometry::getSubId() { return this->subid; } /******************************************************************************* * * Get number of subobjects to ObjectGeometry * ******************************************************************************/ int CGeometry::getNumSubobjects() { if (this->next == NULL) return 1; else return (1 + this->next->getNumSubobjects()); } /******************************************************************************* * * Set next to ObjectGeomtry * ******************************************************************************/ void CGeometry::setNext( CGeometry * next ){ this->next = next; } CGeometry * CGeometry::getNext(){ return next; } /******************************************************************************* * * Add Vertex to ObjectGeometry * ******************************************************************************/ int CGeometry::addVertex( double x, double y, double z ){ return vertexList->add( x, y, z); } /******************************************************************************* * * Get Vertex from ObjectGeometry * ******************************************************************************/ void CGeometry::getVertex( int index, double * x, double * y, double * z ){ vertexList->get( index, x, y, z); } CVertex * CGeometry::getVertex( int index ){ return vertexList->getVertex( index ); } /******************************************************************************* * * Set Vertex from ObjectGeometry * ******************************************************************************/ void CGeometry::setVertex( int index, double x, double y, double z ){ vertexList->set( index, x, y, z); } /******************************************************************************* * * Add Normal to ObjectGeometry * ******************************************************************************/ int CGeometry::addNormal( double x, double y, double z ){ return normalList->add( x, y, z); } void CGeometry::setNormal( int index, double x, double y, double z ){ normalList->set( index, x, y, z); } /******************************************************************************* * * Get Normal from ObjectGeometry * ******************************************************************************/ void CGeometry::getNormal( int index, double * x, double * y, double * z ){ normalList->get( index, x, y, z); } CNormal * CGeometry::getNormal( int index ){ return normalList->getNormal( index ); } /******************************************************************************* * * Add TexCoord to ObjectGeometry * ******************************************************************************/ int CGeometry::addTexCoord( double u, double v ){ return texCoordList->add( u, v); } void CGeometry::setTexCoord( int index, double u, double v ){ texCoordList->set( index, u, v); } /******************************************************************************* * * Get TexCoord from ObjectGeometry * ******************************************************************************/ void CGeometry::getTexCoord( int index, double * u, double * v ){ texCoordList->get( index, u, v); } CTexCoord * CGeometry::getTexCoord( int index ){ return texCoordList->getTexCoord( index ); } /******************************************************************************* * * Draw ObjectGeometry * ******************************************************************************/ int CGeometry::draw( CMaterialCache * matCache, CTextureCache * texCache ){ return FALSE; } /******************************************************************************* * * Add Polygon to ObjectGeomtery * ******************************************************************************/ int CGeometry::addPolygon( CPolygon * polygon ){ return polygonList->add( polygon ); } void CGeometry::setPolygon( int index, CPolygon * polygon ){ polygonList->set( index, polygon ); } /******************************************************************************* * * Get Polygon from ObjectGeometry * ******************************************************************************/ CPolygon * CGeometry::getPolygon( int index ){ return polygonList->get( index ); } /******************************************************************************* * * Return number of Vertices in ObjectGeometry * ******************************************************************************/ int CGeometry::getNumVertices(){ // if (objGeo == NULL) return -1; if (vertexList == NULL) return -2; return vertexList->getNumElements(); } /******************************************************************************* * * Return number of Normals in ObjectGeometry * ******************************************************************************/ int CGeometry::getNumNormals(){ // if (objGeo == NULL) return -1; if (normalList == NULL) return -2; return normalList->getNumElements(); } /******************************************************************************* * * Return number of TexCoords in ObjectGeometry * ******************************************************************************/ int CGeometry::getNumTexCoords(){ // if (objGeo == NULL) return -1; if (texCoordList == NULL) return -2; return texCoordList->getNumElements(); } /******************************************************************************* * * Return number of Polygons in ObjectGeometry * ******************************************************************************/ int CGeometry::getNumPolygons(){ // if (objGeo == NULL) return -1; if (polygonList == NULL) return -2; return polygonList->getNumElements(); } /******************************************************************************* * * Scale ObjectGeometry * ******************************************************************************/ int CGeometry::scale( double scale ){ int vertex,vertices; double x,y,z; vertices = getNumVertices(); for (vertex = 0; vertex < vertices ; vertex++){ getVertex(vertex,&x,&y,&z); setVertex(vertex,x*scale,y*scale,z*scale); } return TRUE; } /////////////////////////////////////////////////////////////////////////////// // distances // Info : Calculate distances from the startingpoint of a beam in the // beams direction. // Arguments : // max : Give maximum distance to be stored in result // min : Give minimum distance to be stored in result // Return : DoubleArray of distances /////////////////////////////////////////////////////////////////////////////// CDoubleArray * CGeometry::distances(const CBeam & beam, double min, double max){ // Create array to store results CDoubleArray * distArray = new CDoubleArray(); distances(*distArray,beam,min,max); return distArray; } /////////////////////////////////////////////////////////////////////////////// // distances // Info : Calculate distances from the startingpoint of a beam in the // beams direction. // Arguments : // max : Give maximum distance to be stored in result // min : Give minimum distance to be stored in result // Return : DoubleArray of distances /////////////////////////////////////////////////////////////////////////////// void CGeometry::distances(CDoubleArray & distArray, const CBeam & beam, double min, double max){ // Create array to store results CDoubleArray * polyDistances = new CDoubleArray; // Get number of polygons to check int numPolygons = getNumPolygons(); // Check all polygons while (numPolygons-- > 0){ CPolygon * poly = getPolygon(numPolygons); polyDistances->deleteAll(); poly->distances(*polyDistances,beam); int index = polyDistances->getNumElements(); while (index-- > 0){ double distance = polyDistances->get(index); if ((distance <= max) && (distance >= min)) distArray.add(distance); } } delete polyDistances; } /////////////////////////////////////////////////////////////////////////////// // calculateBBox // Info : Calculate bounding box for geometry // Return : BBox of geometry /////////////////////////////////////////////////////////////////////////////// CBBox CGeometry::calculateBBox(){ CBBox bBox; CVertex * vertex; int vertexIndex = getNumVertices(); if (vertexIndex-- > 0){ vertex = getVertex(vertexIndex); bBox.initialize(CPosition(vertex->getCoord())); } while (vertexIndex-- > 0){ vertex = getVertex(vertexIndex); bBox.include(CPosition(vertex->getCoord())); } return bBox; } /******************************************************************************* * * Constructor for CGeometryCache * ******************************************************************************/ CGeometryCache::CGeometryCache() : CCache() { } /******************************************************************************* * * Destructor for CGeometryCache * ******************************************************************************/ CGeometryCache::~CGeometryCache(){ } /******************************************************************************* * * Add object to ObjectGeometryCache * ******************************************************************************/ CGeometry* CGeometryCache::add(CGeometry * objGeo){ return (CGeometry*)CCache::add(objGeo->getId(), (CObject*)objGeo ); } CGeometry * CGeometryCache::get(int id){ return (CGeometry*)CCache::get( id ); }