Files
2025-03-05 08:37:43 +01:00

1108 lines
31 KiB
C

/*
* 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 <stdlib.h>
#include <stdio.h>
#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 );
}