This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/ww3d2/meshgeometry.h

288 lines
11 KiB
C++

/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WW3D *
* *
* $Archive:: /Commando/Code/ww3d2/meshgeometry.h $*
* *
* Original Author:: Greg Hjelstrom *
* *
* $Author:: Jani_p $*
* *
* $Modtime:: 11/24/01 7:28p $*
* *
* $Revision:: 11 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef MESHGEOMETRY_H
#define MESHGEOMETRY_H
#include "refcount.h"
#include "bittype.h"
#include "simplevec.h"
#include "sharebuf.h"
#include "w3derr.h"
#include "vector3.h"
#include "vector3i.h"
#include "vector4.h"
#include "wwdebug.h"
#include "multilist.h"
#include "coltest.h"
#include "inttest.h"
class AABoxClass;
class OBBoxClass;
class SphereClass;
class ChunkLoadClass;
class AABTreeClass;
// Define which kind of index vector to use (16- or 32 bit)
typedef Vector3i16 TriIndex;
//typedef Vector3i TriIndex;
/*
** The following two defines control two space-saving optimizations. In Renegade I've found
** that the plane equations are about 8% of the geometry space and vertex normals are about 10%
** so I'm trying to see if we can get by without them. The plane equations are mainly used
** by collision detection functions and those are culled pretty well. Anyway, collision is
** already so expensive that adding a cross product to it doesn't seem to matter.
**
** NOTE: currently with optimizations enabled, memory gets trashed if you use OPTIMIZE_VNORM_RAM
** I suspect this is due to the way Dynamesh uses (abuses) MeshGeometryClass and haven't had
** time to track it down yet.
*/
#define OPTIMIZE_PLANEEQ_RAM 1
#define OPTIMIZE_VNORM_RAM 0
/**
** MeshGeometryClass
** This class encapsulates the geometry data for a triangle mesh.
*/
class MeshGeometryClass : public RefCountClass, public MultiListObjectClass
{
public:
MeshGeometryClass(void);
MeshGeometryClass(const MeshGeometryClass & that);
virtual ~MeshGeometryClass(void);
MeshGeometryClass & operator = (const MeshGeometryClass & that);
enum FlagsType
{
DIRTY_BOUNDS = 0x00000001,
DIRTY_PLANES = 0x00000002,
DIRTY_VNORMALS = 0x00000004,
SORT = 0x00000010,
DISABLE_BOUNDING_BOX = 0x00000020,
DISABLE_BOUNDING_SPHERE = 0x00000040,
DISABLE_PLANE_EQ = 0x00000080,
TWO_SIDED = 0x00000100,
ALIGNED = 0x00000200,
SKIN = 0x00000400,
ORIENTED = 0x00000800,
CAST_SHADOW = 0x00001000,
PRELIT_MASK = 0x0000E000,
PRELIT_VERTEX = 0x00002000,
PRELIT_LIGHTMAP_MULTI_PASS = 0x00004000,
PRELIT_LIGHTMAP_MULTI_TEXTURE = 0x00008000,
ALLOW_NPATCHES = 0x00010000,
};
void Reset_Geometry(int polycount,int vertcount);
const char * Get_Name(void) const;
void Set_Name(const char * newname);
const char * Get_User_Text(void);
void Set_User_Text(char * usertext);
void Set_Flag(FlagsType flag,bool onoff) { if (onoff) { Flags |= flag; } else { Flags &= ~flag; } }
int Get_Flag(FlagsType flag) { return Flags & flag; }
void Set_Sort_Level(int level) { SortLevel = level; }
int Get_Sort_Level(void) const { return SortLevel; }
int Get_Polygon_Count(void) const { return PolyCount; }
int Get_Vertex_Count(void) const { return VertexCount; }
const TriIndex* Get_Polygon_Array(void) { return get_polys(); }
Vector3 * Get_Vertex_Array(void) { WWASSERT(Vertex); return Vertex->Get_Array(); }
const Vector3 * Get_Vertex_Normal_Array(void);
const Vector4 * Get_Plane_Array(bool create = true);
void Compute_Plane(int pidx,PlaneClass * set_plane) const;
const uint32 * Get_Vertex_Shade_Index_Array(bool create = true) { return get_shade_indices(create); }
const uint16 * Get_Vertex_Bone_Links(void) { return get_bone_links(); }
uint8 * Get_Poly_Surface_Type_Array(void) { WWASSERT(PolySurfaceType); return PolySurfaceType->Get_Array(); }
uint8 Get_Poly_Surface_Type(int poly_index) const;
void Get_Bounding_Box(AABoxClass * set_box);
void Get_Bounding_Sphere(SphereClass * set_sphere);
// exposed culling support
bool Has_Cull_Tree(void) { return CullTree != NULL; }
void Generate_Rigid_APT(const Vector3 & view_dir, SimpleDynVecClass<uint32> & apt);
void Generate_Rigid_APT(const OBBoxClass & local_box, SimpleDynVecClass<uint32> & apt);
void Generate_Rigid_APT(const OBBoxClass & local_box, const Vector3 & view_dir, SimpleDynVecClass<uint32> & apt);
void Generate_Skin_APT(const OBBoxClass & world_box, SimpleDynVecClass<uint32> & apt, const Vector3 *world_vertex_locs);
// containment
bool Contains(const Vector3 &point);
// ray casting and intersection (takes a transform for the mesh). Note that unlike the MeshClass
// functions with similar names, these work in object space.
bool Cast_Ray(RayCollisionTestClass & raytest);
bool Cast_AABox(AABoxCollisionTestClass & boxtest);
bool Cast_OBBox(OBBoxCollisionTestClass & boxtest);
bool Intersect_OBBox(OBBoxIntersectionTestClass & boxtest);
// This function analyses the transform passed into it to call various optimized functions if
// the transform is identity or a simple rotation about the z-axis. Otherwise it transforms
// boxtest into object space, performs an oob cast and transforms the result back.
bool Cast_World_Space_AABox(AABoxCollisionTestClass & boxtest, const Matrix3D &transform);
// W3D File Format support. Note that derived classes have to override these functions completely
// so that they can handle their extra chunks. Using these functions you could load mesh data out
// of a W3D file while ignoring all materials, textures, etc.
virtual WW3DErrorType Load_W3D(ChunkLoadClass & cload);
void Scale(const Vector3 &sc);
protected:
// internal accessor functions that are not exposed to the user (non-const...)
TriIndex * get_polys(void);
Vector3 * get_vert_normals(void);
uint32 * get_shade_indices(bool create = true);
Vector4 * get_planes(bool create = true);
uint16 * get_bone_links(bool create = true);
// Utility functions (used by collision/intersection functions)
int cast_semi_infinite_axis_aligned_ray(const Vector3 & start_point, int axis_dir, unsigned char & flags);
bool cast_aabox_identity(AABoxCollisionTestClass & boxtest,const Vector3 & trans);
bool cast_aabox_z90(AABoxCollisionTestClass & boxtest,const Vector3 & trans);
bool cast_aabox_z180(AABoxCollisionTestClass & boxtest,const Vector3 & trans);
bool cast_aabox_z270(AABoxCollisionTestClass & boxtest,const Vector3 & trans);
bool intersect_obbox_brute_force(OBBoxIntersectionTestClass & localtest);
bool cast_ray_brute_force(RayCollisionTestClass & raytest);
bool cast_aabox_brute_force(AABoxCollisionTestClass & boxtest);
bool cast_obbox_brute_force(OBBoxCollisionTestClass & boxtest);
// functions to recompute dirty normals and bounding volumes.
virtual void Compute_Plane_Equations(Vector4 * array);
virtual void Compute_Vertex_Normals(Vector3 * array);
virtual void Compute_Bounds(Vector3 * verts);
void Generate_Culling_Tree(void);
// W3D chunk reading
WW3DErrorType read_chunks(ChunkLoadClass & cload);
WW3DErrorType read_vertices(ChunkLoadClass & cload);
WW3DErrorType read_vertex_normals(ChunkLoadClass & cload);
WW3DErrorType read_triangles(ChunkLoadClass & cload);
WW3DErrorType read_user_text(ChunkLoadClass & cload);
WW3DErrorType read_vertex_influences(ChunkLoadClass & cload);
WW3DErrorType read_vertex_shade_indices(ChunkLoadClass & cload);
WW3DErrorType read_aabtree(ChunkLoadClass &cload);
// General info
ShareBufferClass<char> * MeshName;
ShareBufferClass<char> * UserText;
int Flags;
char SortLevel;
uint32 W3dAttributes;
// Geometry
int PolyCount;
int VertexCount;
ShareBufferClass<TriIndex> * Poly;
ShareBufferClass<Vector3> * Vertex;
ShareBufferClass<Vector3> * VertexNorm;
ShareBufferClass<Vector4> * PlaneEq;
ShareBufferClass<uint32> * VertexShadeIdx;
ShareBufferClass<uint16> * VertexBoneLink;
ShareBufferClass<uint8> * PolySurfaceType;
Vector3 BoundBoxMin;
Vector3 BoundBoxMax;
Vector3 BoundSphereCenter;
float BoundSphereRadius;
AABTreeClass * CullTree;
};
/*
** Inline functions for MeshGeometryClass
*/
inline TriIndex * MeshGeometryClass::get_polys(void)
{
WWASSERT(Poly);
return Poly->Get_Array();
}
inline uint32 * MeshGeometryClass::get_shade_indices(bool create)
{
if (create && !VertexShadeIdx) {
VertexShadeIdx = NEW_REF(ShareBufferClass<uint32>,(VertexCount));
}
if (VertexShadeIdx) {
return VertexShadeIdx->Get_Array();
}
return NULL;
}
inline uint16 * MeshGeometryClass::get_bone_links(bool create)
{
if (create && !VertexBoneLink) {
VertexBoneLink = NEW_REF(ShareBufferClass<uint16>,(VertexCount));
}
if (VertexBoneLink) {
return VertexBoneLink->Get_Array();
}
return NULL;
}
inline uint8 MeshGeometryClass::Get_Poly_Surface_Type(int poly_index) const
{
WWASSERT(PolySurfaceType);
WWASSERT(poly_index >= 0 && poly_index < PolyCount);
uint8 *type = PolySurfaceType->Get_Array();
return type[poly_index];
}
#endif //MESHGEOMETRY_H