mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-11-22 18:30:27 +01:00
827 lines
34 KiB
C++
827 lines
34 KiB
C++
/* Copyright (c) 2002-2012 Croteam Ltd.
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of version 2 of the GNU General Public License as published by
|
|
the Free Software Foundation
|
|
|
|
|
|
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.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
|
|
|
#ifndef SE_INCL_BRUSH_H
|
|
#define SE_INCL_BRUSH_H
|
|
#ifdef PRAGMA_ONCE
|
|
#pragma once
|
|
#endif
|
|
|
|
#include <Engine/Base/Lists.h>
|
|
#include <Engine/Base/Relations.h>
|
|
#include <Engine/Math/Vector.h>
|
|
#include <Engine/Math/Plane.h>
|
|
#include <Engine/Math/TextureMapping.h>
|
|
#include <Engine/Math/AABBox.h>
|
|
#include <Engine/Math/Projection.h>
|
|
#include <Engine/Graphics/Texture.h>
|
|
#include <Engine/Graphics/ShadowMap.h>
|
|
#include <Engine/Brushes/BrushBase.h>
|
|
#include <Engine/Templates/DynamicArray.h>
|
|
#include <Engine/Templates/StaticArray.h>
|
|
#include <Engine/Templates/Selection.h>
|
|
|
|
// a vertex in brush
|
|
#define BVXF_DRAWNINWIREFRAME (1L<<0) // vertex is already drawn in wireframe
|
|
#define BVXF_SELECTED (1L<<1) // vertex is selected
|
|
class ENGINE_API CBrushVertex {
|
|
public:
|
|
class CWorkingVertex *bvx_pwvxWorking; // used for rendering and ray casting
|
|
FLOAT3D bvx_vAbsolute;
|
|
FLOAT3D bvx_vRelative; // relative coordinates used for collision
|
|
DOUBLE3D bvx_vdPreciseRelative; // precise relative coordinates used for editing
|
|
DOUBLE3D *bvx_pvdPreciseAbsolute; // precise vertex coordinates in absolute space
|
|
ULONG bvx_ulFlags; // flags
|
|
CBrushSector *bvx_pbscSector; // back-pointer to sector
|
|
|
|
/* Default constructor. */
|
|
inline CBrushVertex(void) : bvx_pwvxWorking(NULL), bvx_ulFlags(0) {};
|
|
/* Clear the object. */
|
|
inline void Clear(void) {};
|
|
|
|
// vertices may be selected
|
|
IMPLEMENT_SELECTING(bvx_ulFlags)
|
|
|
|
// set new absolute position for the vertex
|
|
void SetAbsolutePosition(const DOUBLE3D &vAbsolute);
|
|
|
|
// get amount of memory used by this object
|
|
inline SLONG GetUsedMemory(void) { return sizeof(CBrushVertex); };
|
|
};
|
|
|
|
|
|
// selection of brush vertices
|
|
typedef CSelection<CBrushVertex, BVXF_SELECTED> CBrushVertexSelection;
|
|
|
|
// a plane in brush
|
|
class ENGINE_API CBrushPlane {
|
|
public:
|
|
class CWorkingPlane *bpl_pwplWorking; // use for rendering and ray casting
|
|
FLOATplane3D bpl_plAbsolute;
|
|
FLOATplane3D bpl_plRelative; // relative coordinates used for collision
|
|
DOUBLEplane3D *bpl_ppldPreciseAbsolute; // precise relative plane coordinates in absolute space
|
|
DOUBLEplane3D bpl_pldPreciseRelative; // precise coordinates used for editing
|
|
INDEX bpl_iPlaneMajorAxis1; // major axes of the plane in apsolute space
|
|
INDEX bpl_iPlaneMajorAxis2;
|
|
|
|
/* Default constructor. */
|
|
inline CBrushPlane(void) : bpl_pwplWorking(NULL) {};
|
|
/* Clear the object. */
|
|
inline void Clear(void) {};
|
|
|
|
// get amount of memory used by this object
|
|
inline SLONG GetUsedMemory(void) { return sizeof(CBrushPlane); };
|
|
};
|
|
|
|
|
|
// an edge in brush
|
|
class ENGINE_API CBrushEdge {
|
|
public:
|
|
CBrushVertex *bed_pbvxVertex0; // start vertex
|
|
CBrushVertex *bed_pbvxVertex1; // end vertex
|
|
CWorkingEdge *bed_pwedWorking; // pointer to screen edge if active in rendering
|
|
|
|
/* Default constructor. */
|
|
inline CBrushEdge(void) : bed_pwedWorking(NULL) {};
|
|
/* Constructor with two vertices. */
|
|
inline CBrushEdge(CBrushVertex *pbvx0, CBrushVertex *pbvx1)
|
|
: bed_pbvxVertex0(pbvx0), bed_pbvxVertex1(pbvx1), bed_pwedWorking(NULL) {};
|
|
/* Clear the object. */
|
|
inline void Clear(void) {};
|
|
/* Test if this edge touches another one. */
|
|
BOOL TouchesInSameSector(CBrushEdge &bedOther);
|
|
BOOL TouchesInAnySector(CBrushEdge &bedOther);
|
|
|
|
// get amount of memory used by this object
|
|
inline SLONG GetUsedMemory(void) { return sizeof(CBrushEdge); };
|
|
};
|
|
|
|
// a reference to edge used in brush polygon
|
|
class ENGINE_API CBrushPolygonEdge {
|
|
public:
|
|
CBrushEdge *bpe_pbedEdge; // pointer to the edge
|
|
BOOL bpe_bReverse; // true if the vertex0 and vertex1 must be swapped
|
|
|
|
/* Clear the object. */
|
|
inline void Clear(void) {};
|
|
/* Get coordinates of the end vertices. */
|
|
inline void GetVertices(CBrushVertex *&pbvx0, CBrushVertex *&pbvx1) {
|
|
if (bpe_bReverse) {
|
|
pbvx0 = bpe_pbedEdge->bed_pbvxVertex1;
|
|
pbvx1 = bpe_pbedEdge->bed_pbvxVertex0;
|
|
} else {
|
|
pbvx0 = bpe_pbedEdge->bed_pbvxVertex0;
|
|
pbvx1 = bpe_pbedEdge->bed_pbvxVertex1;
|
|
}
|
|
}
|
|
inline void GetVertexCoordinatesAbsolute(FLOAT3D &v0, FLOAT3D &v1) {
|
|
if (bpe_bReverse) {
|
|
v0 = bpe_pbedEdge->bed_pbvxVertex1->bvx_vAbsolute;
|
|
v1 = bpe_pbedEdge->bed_pbvxVertex0->bvx_vAbsolute;
|
|
} else {
|
|
v0 = bpe_pbedEdge->bed_pbvxVertex0->bvx_vAbsolute;
|
|
v1 = bpe_pbedEdge->bed_pbvxVertex1->bvx_vAbsolute;
|
|
}
|
|
};
|
|
inline void GetVertexCoordinatesRelative(FLOAT3D &v0, FLOAT3D &v1) {
|
|
if (bpe_bReverse) {
|
|
v0 = bpe_pbedEdge->bed_pbvxVertex1->bvx_vRelative;
|
|
v1 = bpe_pbedEdge->bed_pbvxVertex0->bvx_vRelative;
|
|
} else {
|
|
v0 = bpe_pbedEdge->bed_pbvxVertex0->bvx_vRelative;
|
|
v1 = bpe_pbedEdge->bed_pbvxVertex1->bvx_vRelative;
|
|
}
|
|
};
|
|
inline void GetVertexCoordinatesPreciseRelative(DOUBLE3D &v0, DOUBLE3D &v1) {
|
|
if (bpe_bReverse) {
|
|
v0 = bpe_pbedEdge->bed_pbvxVertex1->bvx_vdPreciseRelative;
|
|
v1 = bpe_pbedEdge->bed_pbvxVertex0->bvx_vdPreciseRelative;
|
|
} else {
|
|
v0 = bpe_pbedEdge->bed_pbvxVertex0->bvx_vdPreciseRelative;
|
|
v1 = bpe_pbedEdge->bed_pbvxVertex1->bvx_vdPreciseRelative;
|
|
}
|
|
};
|
|
inline void GetVertexCoordinatesPreciseAbsolute(DOUBLE3D &v0, DOUBLE3D &v1) {
|
|
if (bpe_bReverse) {
|
|
v0 = *bpe_pbedEdge->bed_pbvxVertex1->bvx_pvdPreciseAbsolute;
|
|
v1 = *bpe_pbedEdge->bed_pbvxVertex0->bvx_pvdPreciseAbsolute;
|
|
} else {
|
|
v0 = *bpe_pbedEdge->bed_pbvxVertex0->bvx_pvdPreciseAbsolute;
|
|
v1 = *bpe_pbedEdge->bed_pbvxVertex1->bvx_pvdPreciseAbsolute;
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
// one layer on brush shadow map (cross link between brush shadow map and light source)
|
|
#define BSLF_CALCULATED (1L<<0)
|
|
#define BSLF_RECTANGLE (1L<<1) // new version of layer with only influenced rectangle
|
|
#define BSLF_ALLDARK (1L<<2) // polygon is not lighted by the light at all
|
|
#define BSLF_ALLLIGHT (1L<<3) // whole polygon is lighted by the light (there are no shadows)
|
|
class ENGINE_API CBrushShadowLayer {
|
|
public:
|
|
// implementation:
|
|
ULONG bsl_ulFlags; // flags
|
|
CListNode bsl_lnInShadowMap; // node in list of all layers of a shadow map
|
|
CListNode bsl_lnInLightSource; // node in list of all layers of a light source
|
|
class CBrushShadowMap *bsl_pbsmShadowMap; // the shadow map
|
|
class CLightSource *bsl_plsLightSource; // the light source
|
|
PIX bsl_pixMinU; // rectangle where the light influences the polygon
|
|
PIX bsl_pixMinV;
|
|
PIX bsl_pixSizeU;
|
|
PIX bsl_pixSizeV;
|
|
SLONG bsl_slSizeInPixels; // size of bit mask in pixels (with all mip-maps)
|
|
UBYTE *bsl_pubLayer; // bit mask set where the polygon is lighted
|
|
COLOR bsl_colLastAnim; // last animating color cached
|
|
|
|
// interface:
|
|
CBrushShadowLayer();
|
|
~CBrushShadowLayer(void);
|
|
// discard shadows but keep the layer
|
|
void DiscardShadows(void);
|
|
// get shadow/light percentage at given coordinates in shadow layer
|
|
FLOAT GetLightStrength(PIX pixU, PIX pixV, FLOAT fLt, FLOAT fUp);
|
|
|
|
// get amount of memory used by this object
|
|
SLONG GetUsedMemory(void);
|
|
};
|
|
|
|
|
|
class ENGINE_API CBrushShadowMap : public CShadowMap {
|
|
public:
|
|
// implementation:
|
|
// for linking in list of all shadow maps that need calculation
|
|
CListNode bsm_lnInUncalculatedShadowMaps;
|
|
|
|
CListHead bsm_lhLayers; // list of all layers of this shadow map
|
|
UBYTE *bsm_pubPolygonMask; // bit packed polygon mask
|
|
|
|
// get pointer to embedding brush polygon
|
|
inline CBrushPolygon *GetBrushPolygon(void);
|
|
|
|
// overrides from CShadowMap:
|
|
// mix all layers into cached shadow map
|
|
virtual void MixLayers(INDEX iFirstMip, INDEX iLastMip, BOOL bDynamic=FALSE); // iFirstMip<iLastMip
|
|
// read/write layers from/to stream
|
|
virtual void ReadLayers_t( CTStream *pstrm); // throw char *
|
|
virtual void WriteLayers_t( CTStream *pstrm); // throw char *
|
|
// check if all layers are up to date
|
|
virtual void CheckLayersUpToDate(void);
|
|
// test if there is any dynamic layer
|
|
virtual BOOL HasDynamicLayers(void);
|
|
|
|
// returns TRUE if shadowmap is all flat along with colFlat variable set to that color
|
|
virtual BOOL IsShadowFlat( COLOR &colFlat);
|
|
|
|
// calculate the rectangle where a light influences the shadow map
|
|
void FindLightRectangle(CLightSource &ls, class CLightRectangle &lr);
|
|
// queue the shadow map for calculation
|
|
void QueueForCalculation(void);
|
|
// interface:
|
|
// constructor
|
|
CBrushShadowMap(void);
|
|
// destructor
|
|
~CBrushShadowMap(void);
|
|
// discard all layers on this shadow map
|
|
void DiscardAllLayers(void);
|
|
// discard shadows on all layers on this shadow map
|
|
void DiscardShadows(void);
|
|
// remove shadow layers without valid light source
|
|
void RemoveDummyLayers(void);
|
|
|
|
// get number of shadow layers
|
|
INDEX GetShadowLayersCount(void) { return bsm_lhLayers.Count(); };
|
|
// get amount of memory used by this object
|
|
SLONG GetUsedMemory(void);
|
|
};
|
|
|
|
|
|
// one texture on a brush polygon
|
|
#define BPTF_CLAMPU (1U<<0) // clamp u coordinate in texture
|
|
#define BPTF_CLAMPV (1U<<1) // clamp v coordinate in texture
|
|
#define BPTF_DISCARDABLE (1U<<2) // texture doesn't have to be drawn
|
|
#define BPTF_AFTERSHADOW (1U<<3) // texture is to be applied after shadow
|
|
#define BPTF_REFLECTION (1U<<4) // texture will be reflection-mapped
|
|
|
|
// first few blending type must be these:
|
|
#define BPT_BLEND_OPAQUE 0
|
|
#define BPT_BLEND_SHADE 1
|
|
#define BPT_BLEND_BLEND 2
|
|
#define BPT_BLEND_ADD 3
|
|
|
|
class ENGINE_API CBrushPolygonTexture {
|
|
public:
|
|
CTextureObject bpt_toTexture; // texture object
|
|
CMappingDefinition bpt_mdMapping; // mapping of texture on polygon
|
|
|
|
union {
|
|
struct {
|
|
UBYTE bpt_ubScroll; // texture scroll
|
|
UBYTE bpt_ubBlend; // type of texture blending used
|
|
UBYTE bpt_ubFlags; // additional flags
|
|
UBYTE bpt_ubDummy; // unused (alignment)
|
|
COLOR bpt_colColor; // defines constant color and alpha of polygon
|
|
} s;
|
|
UBYTE bpt_auProperties[8];
|
|
};
|
|
|
|
// ATTENTION! If you add/edit/remove any data member, PLEASE update the
|
|
// operator = method, below! --ryan.
|
|
CBrushPolygonTexture& operator =(const CBrushPolygonTexture &src)
|
|
{
|
|
if (this != &src)
|
|
{
|
|
bpt_toTexture = src.bpt_toTexture;
|
|
bpt_mdMapping = src.bpt_mdMapping;
|
|
memcpy(&bpt_auProperties, &src.bpt_auProperties, sizeof (bpt_auProperties));
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
|
|
CBrushPolygonTexture(void)
|
|
{
|
|
s.bpt_ubScroll = 0;
|
|
s.bpt_ubBlend = 0;
|
|
s.bpt_ubFlags = BPTF_DISCARDABLE;
|
|
s.bpt_ubDummy = 0;
|
|
s.bpt_colColor = 0xFFFFFFFF;
|
|
}
|
|
|
|
/* Copy polygon properties */
|
|
CBrushPolygonTexture &CopyTextureProperties(CBrushPolygonTexture &bptOther, BOOL bCopyMapping) {
|
|
bpt_toTexture.SetData( bptOther.bpt_toTexture.GetData());
|
|
s.bpt_ubScroll = bptOther.s.bpt_ubScroll;
|
|
s.bpt_ubBlend = bptOther.s.bpt_ubBlend;
|
|
s.bpt_ubFlags = bptOther.s.bpt_ubFlags;
|
|
s.bpt_ubDummy = bptOther.s.bpt_ubDummy;
|
|
s.bpt_colColor = bptOther.s.bpt_colColor;
|
|
if( bCopyMapping) bpt_mdMapping = bptOther.bpt_mdMapping;
|
|
return *this;
|
|
};
|
|
void Clear(void) {
|
|
bpt_toTexture.SetData(NULL);
|
|
};
|
|
// read/write to stream
|
|
void Read_t( CTStream &strm); // throw char *
|
|
void Write_t( CTStream &strm); // throw char *
|
|
|
|
// get amount of memory used by this object
|
|
inline SLONG GetUsedMemory(void) { return sizeof(CBrushPolygonTexture); };
|
|
};
|
|
|
|
|
|
// a polygon in brush
|
|
// Flags
|
|
// flags 0-2 are used by CObjectPolygon, flags 3-31 are used by CBrushPolygon
|
|
// OPOF_PORTAL // set if the polygon is a portal - used for CSG in CObject3D
|
|
#define BPOF_DOUBLESIDED (1UL<< 3) // polygon is renderable from both sides
|
|
#define BPOF_SHOOTTHRU (1UL<< 4) // physical ray-casts can pass through the polygon, even if it is not passable
|
|
#define BPOF_TRANSPARENT (1UL<< 5) // render with alpha-testing and write z-buffer
|
|
#define BPOF_RENDERASPORTAL (1UL<< 6) // internal used in rendering
|
|
#define BPOF_STAIRS (1UL<< 7) // polygon is part of a staircase
|
|
#define BPOF_SELECTED (1UL<< 8) // set if the polygon is selected
|
|
#define BPOF_SELECTEDFORCSG (1UL<< 9) // set if the polygon is selected for CSG
|
|
#define BPOF_WASPORTAL (1UL<<10) // set if it was portal before CSG
|
|
#define BPOF_PASSABLE (1UL<<11) // set if not a physical barrier
|
|
#define BPOF_DOESNOTCASTSHADOW (1UL<<12) // set to make a wall passable for light beams
|
|
#define BPOF_WASBRUSHPOLYGON (1UL<<13) // this polygon was brush polygon before (not just created)
|
|
#define BPOF_FULLBRIGHT (1UL<<14) // set to make a wall full-bright
|
|
#define BPOF_TRANSLUCENT (1UL<<15) // set for translucent portals
|
|
#define BPOF_HASDIRECTIONALLIGHT (1UL<<16) // set if polygon accepts directional lights
|
|
#define BPOF_INVISIBLE (1UL<<17) // set if the polygon is ignored during rendering
|
|
#define BPOF_DARKCORNERS (1UL<<18) // polygons will have dark corners (here was gouraud!!!!)
|
|
#define BPOF_RENDERTRANSLUCENT (1UL<<19) // internal used in rendering
|
|
#define BPOF_NOPLANEDIFFUSION (1UL<<20) // plane normal is ignored when shading
|
|
#define BPOF_DETAILPOLYGON (1UL<<21) // not used for visibility determination
|
|
#define BPOF_PORTAL (1UL<<22) // should behave like a portal (not same as OPOF_PORTAL)
|
|
#define BPOF_ACCURATESHADOWS (1UL<<23) // shadows are calculated for each mip-map independently
|
|
#define BPOF_HASDIRECTIONALAMBIENT (1UL<<24) // set if polygon accepts directional ambient
|
|
#define BPOF_MARKEDLAYER (1UL<<25) // used in FindShadowLayers()
|
|
#define BPOF_DYNAMICLIGHTSONLY (1UL<<26) // only dynamic lights used in shadow map
|
|
#define BPOF_DOESNOTRECEIVESHADOW (1UL<<27) // has lightmap, but no shadows on it
|
|
#define BPOF_NODYNAMICLIGHTS (1UL<<28) // dynamic lights do not influence it
|
|
#define BPOF_INVALIDTRIANGLES (1UL<<29) // polygons could not be triangulated well
|
|
#define BPOF_OCCLUDER (1UL<<30) // occluder polygon
|
|
#define BPOF_MARKED_FOR_USE (1UL<<31) // used in triangularization when polygon vertex is moved
|
|
|
|
#define BPOF_MASK_FOR_COPYING \
|
|
(BPOF_PASSABLE|BPOF_DOESNOTCASTSHADOW|BPOF_FULLBRIGHT|BPOF_TRANSLUCENT|BPOF_TRANSPARENT|\
|
|
BPOF_HASDIRECTIONALLIGHT|BPOF_INVISIBLE|BPOF_NOPLANEDIFFUSION|\
|
|
BPOF_DETAILPOLYGON|BPOF_PORTAL|BPOF_ACCURATESHADOWS|BPOF_HASDIRECTIONALAMBIENT|\
|
|
BPOF_DYNAMICLIGHTSONLY|BPOF_DOESNOTRECEIVESHADOW|BPOF_NODYNAMICLIGHTS|BPOF_DARKCORNERS|BPOF_OCCLUDER)
|
|
|
|
// properties that are retained in conversions to/from CObjectPolygon
|
|
struct CBrushPolygonProperties {
|
|
UBYTE bpp_ubSurfaceType; // surface type on this polygon
|
|
UBYTE bpp_ubIlluminationType; // type of illuminating polygon, 0 if not illuminating
|
|
UBYTE bpp_ubShadowBlend; // type of texture blending used for shadow map
|
|
UBYTE bpp_ubMirrorType; // mirror or warp
|
|
UBYTE bpp_ubGradientType; // for gradiental shadows
|
|
SBYTE bpp_sbShadowClusterSize; // size of shadow clusters (size=(1<<ub)*0.5m)
|
|
UWORD bpp_uwPretenderDistance; // distance for pretender switching [m]
|
|
/* Default constructor. */
|
|
CBrushPolygonProperties(void) { memset(this, 0, sizeof(*this)); };
|
|
friend __forceinline CTStream &operator>>(CTStream &strm, CBrushPolygonProperties &cbpp)
|
|
{
|
|
strm>>cbpp.bpp_ubSurfaceType;
|
|
strm>>cbpp.bpp_ubIlluminationType;
|
|
strm>>cbpp.bpp_ubShadowBlend;
|
|
strm>>cbpp.bpp_ubMirrorType;
|
|
strm>>cbpp.bpp_ubGradientType;
|
|
strm>>cbpp.bpp_sbShadowClusterSize;
|
|
strm>>cbpp.bpp_uwPretenderDistance;
|
|
return strm;
|
|
}
|
|
friend __forceinline CTStream &operator<<(CTStream &strm, const CBrushPolygonProperties &cbpp)
|
|
{
|
|
strm<<cbpp.bpp_ubSurfaceType;
|
|
strm<<cbpp.bpp_ubIlluminationType;
|
|
strm<<cbpp.bpp_ubShadowBlend;
|
|
strm<<cbpp.bpp_ubMirrorType;
|
|
strm<<cbpp.bpp_ubGradientType;
|
|
strm<<cbpp.bpp_sbShadowClusterSize;
|
|
strm<<cbpp.bpp_uwPretenderDistance;
|
|
return strm;
|
|
}
|
|
};
|
|
class ENGINE_API CBrushPolygon {
|
|
public:
|
|
// implementation:
|
|
/* Calculate area of the polygon. */
|
|
DOUBLE CalculateArea(void);
|
|
/* Calculate bounding box of this polygon. */
|
|
void CalculateBoundingBox(void);
|
|
/* Create a BSP polygon from this polygon. */
|
|
void CreateBSPPolygon(BSPPolygon<DOUBLE, 3> &bspo);
|
|
void CreateBSPPolygonNonPrecise(BSPPolygon<DOUBLE, 3> &bspo);
|
|
/* Create shadow map for the polygon. */
|
|
void MakeShadowMap(CWorld *pwoWorld, BOOL bDoDirectionalLights);
|
|
/* Initialize shadow map for the polygon. */
|
|
void InitializeShadowMap(void);
|
|
// discard all cached shading info for models
|
|
void DiscardShadingInfos(void);
|
|
// move edges from another polygon into this one
|
|
void MovePolygonEdges(CBrushPolygon &bpoSource);
|
|
/* Test if this polygon touches another one. */
|
|
BOOL TouchesInSameSector(CBrushPolygon &bpoOther);
|
|
BOOL TouchesInAnySector(CBrushPolygon &bpoOther);
|
|
// make triangular representation of the polygon
|
|
void Triangulate(void);
|
|
public:
|
|
// interface:
|
|
CBrushPlane *bpo_pbplPlane; // plane of this polygon
|
|
CStaticArray<CBrushPolygonEdge> bpo_abpePolygonEdges; // edges in this polygon
|
|
CStaticArray<CBrushVertex *> bpo_apbvxTriangleVertices; // triangle vertices
|
|
CStaticArray<INDEX> bpo_aiTriangleElements; // element indices inside vertex arrays
|
|
CBrushPolygonTexture bpo_abptTextures[3]; // texture on this polygon
|
|
COLOR bpo_colColor; // color of this polygon
|
|
ULONG bpo_ulFlags; // flags
|
|
COLOR bpo_colShadow; // color of shadow on this polygon
|
|
CBrushShadowMap bpo_smShadowMap; // shadow map of this polygon
|
|
CMappingDefinition bpo_mdShadow; // mapping of shadow on polygon
|
|
CBrushPolygonProperties bpo_bppProperties; // additional properties
|
|
class CScreenPolygon *bpo_pspoScreenPolygon; // used in rendering
|
|
|
|
FLOATaabbox3D bpo_boxBoundingBox; // bounding box
|
|
CBrushSector *bpo_pbscSector; // sector of this polygon
|
|
|
|
CRelationSrc bpo_rsOtherSideSectors; // relation to sectors on other side of portal
|
|
CListHead bpo_lhShadingInfos; // for linking shading infos of entities
|
|
INDEX bpo_iInWorld; // index of the polygon in entire world
|
|
|
|
/* Default constructor. */
|
|
inline CBrushPolygon(void) : bpo_ulFlags(0) {};
|
|
/* Clear the object. */
|
|
void Clear(void);
|
|
/* Destructor. */
|
|
inline ~CBrushPolygon(void) { Clear(); };
|
|
CBrushPolygon &CopyPolygon(CBrushPolygon &bp);
|
|
/* Copy polygon within same sector. */
|
|
void CopyFromSameSector(CBrushPolygon &bpoOriginal);
|
|
|
|
/* Copy polygon properties */
|
|
CBrushPolygon &CopyProperties(CBrushPolygon &bpoOther, BOOL bCopyMapping = TRUE);
|
|
/* Copy polygon properties without texture */
|
|
CBrushPolygon &CopyPropertiesWithoutTexture(CBrushPolygon &bpoOther);
|
|
/* Copy polygon's textures */
|
|
CBrushPolygon &CopyTextures(CBrushPolygon &bpoOther);
|
|
|
|
// polygons may be selected
|
|
IMPLEMENT_SELECTING(bpo_ulFlags)
|
|
|
|
/* Select group of adjacent polygons with same color. */
|
|
void SelectSimilarByColor(CSelection<CBrushPolygon, BPOF_SELECTED> &selbpoSimilar);
|
|
/* Select group of adjacent polygons with same texture. */
|
|
void SelectSimilarByTexture(CSelection<CBrushPolygon, BPOF_SELECTED> &selbpoSimilar, INDEX iTexture);
|
|
/* Select all polygons in sector with same texture. */
|
|
void SelectByTextureInSector(CSelection<CBrushPolygon, BPOF_SELECTED> &selbpoSimilar, INDEX iTexture);
|
|
/* Select all polygons in sector with same color. */
|
|
void SelectByColorInSector(CSelection<CBrushPolygon, BPOF_SELECTED> &selbpoSimilar);
|
|
|
|
/* Discard shadows on the polygon. */
|
|
void DiscardShadows(void);
|
|
|
|
// find minimum distance of a given point from the polygon edges
|
|
FLOAT GetDistanceFromEdges(const FLOAT3D &v);
|
|
|
|
// get amount of memory used by this object
|
|
SLONG GetUsedMemory(void);
|
|
};
|
|
|
|
// get pointer to embedding brush polygon
|
|
inline CBrushPolygon *CBrushShadowMap::GetBrushPolygon(void) {
|
|
return (CBrushPolygon *) ((UBYTE*)this-_offsetof(CBrushPolygon, bpo_smShadowMap));
|
|
return(NULL);
|
|
}
|
|
|
|
// selection of brush polygons
|
|
typedef CSelection<CBrushPolygon, BPOF_SELECTED> CBrushPolygonSelection;
|
|
// selection of brush polygons used for CSG
|
|
typedef CSelection<CBrushPolygon, BPOF_SELECTEDFORCSG> CBrushPolygonSelectionForCSG;
|
|
|
|
// sector flags
|
|
#define BSCF_SELECTED (1L<<0) // set if the sector is selected
|
|
#define BSCF_HIDDEN (1L<<1) // set if the sector is hidden (for editing)
|
|
#define BSCF_SELECTEDFORCSG (1L<<2) // set if the sector is selected for CSG
|
|
#define BSCF_OPENSECTOR (1L<<3) // set if the sector polygons are facing outwards
|
|
#define BSCF_NEARTESTED (1L<<4) // already tested for near polygon
|
|
#define BSCF_INVISIBLE (1L<<5) // active, but not visible
|
|
#define BSCF_RAYTESTED (1L<<6) // already tested by ray
|
|
#define BSCF_NEEDSCLIPPING (1L<<7) // set if its polygons needs clipping
|
|
#define BSCB_CONTENTTYPE 24 // upper 8 bits are used for sector content type
|
|
#define BSCB_FORCETYPE 16 // next 8 bits are used for sector gravity type
|
|
#define BSCB_FOGTYPE 12 // 4 bits for fog
|
|
#define BSCB_HAZETYPE 8 // 4 bits for haze
|
|
|
|
#define BSCB2_ENVIRONMENTTYPE 0 // 8 bits for environment sound effects (EAX and similar)
|
|
#define BSCF2_VISIBILITYINCLUDE (1<<8) // toggle include/exclude for visibility (exclude is default)
|
|
|
|
// vis flags
|
|
#define VISM_INCLUDEEXCLUDE (0x0000FFFF) // for visibility include/exclude
|
|
#define VISM_DONTCLASSIFY (0xFFFF0000) // to disable classification in certain sectors
|
|
|
|
// NOTE on how visibility tweaks are implemented
|
|
// - low 16 bits determine visibility from current sector
|
|
// if BSCF2_VISIBILITYINCLUDE is on, entity is visible from sector only if EntityVisTweaks&SectorVisFlags&VISM_INCLUDEEXCLUDE
|
|
// if BSCF2_VISIBILITYINCLUDE is off, entity is visible from sector only if !(EntityVisTweaks&SectorVisFlags&VISM_INCLUDEEXCLUDE)
|
|
// - high 16 bits limit entity classification to sectors
|
|
// if EntityVisTweaks&SectorVisFlags&VISM_DONTCLASSIFY, entity is treated as if not classified to that sector
|
|
|
|
// temporary flags
|
|
#define BSCTF_PRELOADEDBSP (1L<<0) // bsp is loaded, no need to calculate it
|
|
#define BSCTF_PRELOADEDLINKS (1L<<1) // portallinks are loaded, no need to calculate them
|
|
|
|
// a sector in brush
|
|
class ENGINE_API CBrushSector {
|
|
public:
|
|
// implementation:
|
|
/* Fill an object sector from a sector in brush. */
|
|
void ToObjectSector(CObjectSector &osc);
|
|
/* Fill a brush sector from a sector in object3d. */
|
|
void FromObjectSector_t(CObjectSector &osc); // throw char *
|
|
// recalculate planes for polygons from their vertices
|
|
void MakePlanesFromVertices();
|
|
// update changed sector's data after dragging vertices or importing
|
|
void UpdateSector(void);
|
|
|
|
/* Calculate volume of the sector. */
|
|
DOUBLE CalculateVolume(void);
|
|
// make triangular representation of the polygons in the sector
|
|
void Triangulate(void);
|
|
public:
|
|
// implementation:
|
|
CStaticArray<CBrushVertex> bsc_abvxVertices; // vertices
|
|
CStaticArray<CBrushEdge> bsc_abedEdges; // edges
|
|
CStaticArray<CBrushPlane> bsc_abplPlanes; // planes
|
|
CStaticArray<CBrushPolygon> bsc_abpoPolygons; // polygons
|
|
|
|
CStaticArray<CWorkingVertex> bsc_awvxVertices; // working vertices
|
|
CStaticArray<CWorkingPlane> bsc_awplPlanes; // working planes
|
|
CStaticArray<CWorkingEdge> bsc_awedEdges; // working edges
|
|
|
|
class CBrushMip *bsc_pbmBrushMip; // pointer to brush mip of this sector
|
|
COLOR bsc_colColor; // color of this sector
|
|
COLOR bsc_colAmbient; // ambient light for that sector
|
|
ULONG bsc_ulFlags; // flags
|
|
ULONG bsc_ulFlags2; // second set of flags
|
|
ULONG bsc_ulTempFlags; // flags that are not saved
|
|
ULONG bsc_ulVisFlags; // special visibility flags
|
|
FLOATaabbox3D bsc_boxBoundingBox; // bounding box in absolute space
|
|
FLOATaabbox3D bsc_boxRelative; // bounding box in relative space
|
|
CListNode bsc_lnInActiveSectors; // node in sectors active in some operation (e.g. rendering)
|
|
DOUBLEbsptree3D &bsc_bspBSPTree; // the local bsp tree of the sector
|
|
CRelationDst bsc_rdOtherSidePortals; // relation to portals pointing to this sector
|
|
CRelationSrc bsc_rsEntities; // relation to all entities in this sector
|
|
CTString bsc_strName; // sector name
|
|
INDEX bsc_iInWorld; // index of the sector in entire world
|
|
CRelationLnk *bsc_prlLink; // for optimized link removal
|
|
INDEX bsc_ispo0; // screen polygons used in rendering
|
|
INDEX bsc_ctspo;
|
|
INDEX bsc_ivvx0; // view vertices used in rendering
|
|
|
|
/* Default constructor. */
|
|
CBrushSector(void);
|
|
~CBrushSector(void);
|
|
DECLARE_NOCOPYING(CBrushSector);
|
|
|
|
/* Clear the object. */
|
|
void Clear(void);
|
|
/* Lock all arrays. */
|
|
void LockAll(void);
|
|
/* Unlock all arrays. */
|
|
void UnlockAll(void);
|
|
|
|
/* Update sector after moving vertices */
|
|
void UpdateVertexChanges(void);
|
|
// triangularize given polygon
|
|
void TriangularizePolygon( CBrushPolygon *pbpo);
|
|
/* Triangularize polygons contining vertices from selection */
|
|
void TriangularizeForVertices( CBrushVertexSelection &selVertex);
|
|
// Triangularize marked polygons
|
|
void TriangularizeMarkedPolygons( void);
|
|
// Subdivide given triangles
|
|
void SubdivideTriangles( CBrushPolygonSelection &selPolygon);
|
|
// Insert given vertex into triangle
|
|
void InsertVertexIntoTriangle( CBrushPolygonSelection &selPolygon, FLOAT3D vVertex);
|
|
// Retriple two triangles given trough selection
|
|
BOOL IsReTripleAvailable( CBrushPolygonSelection &selPolygon);
|
|
void ReTriple( CBrushPolygonSelection &selPolygon);
|
|
|
|
/* Calculate bounding boxes of all polygons. */
|
|
void CalculateBoundingBoxes(CSimpleProjection3D_DOUBLE &prRelativeToAbsolute);
|
|
|
|
// sectors may be selected
|
|
IMPLEMENT_SELECTING(bsc_ulFlags)
|
|
|
|
// overrides from CSerial
|
|
/* Read from stream. */
|
|
void Read_t( CTStream *istrFile); // throw char *
|
|
/* Write to stream. */
|
|
void Write_t( CTStream *ostrFile); // throw char *
|
|
|
|
/* Uncache lightmaps on all shadows on the sector. */
|
|
void UncacheLightMaps(void);
|
|
/* Find and remember all entities in this sector. */
|
|
void FindEntitiesInSector(void);
|
|
|
|
/* Get/set properties. */
|
|
inline INDEX GetContentType(void) {
|
|
return (bsc_ulFlags>>BSCB_CONTENTTYPE)&0xff;
|
|
}
|
|
void SetContentType(INDEX iNewContent)
|
|
{
|
|
iNewContent&=0xff;
|
|
bsc_ulFlags &= ~(0xff<<BSCB_CONTENTTYPE);
|
|
bsc_ulFlags |= (iNewContent<<BSCB_CONTENTTYPE);
|
|
}
|
|
INDEX GetForceType(void) {
|
|
return (bsc_ulFlags>>BSCB_FORCETYPE)&0xff;
|
|
}
|
|
void SetForceType(INDEX iNewForce) {
|
|
iNewForce&=0xff;
|
|
bsc_ulFlags &= ~(0xff<<BSCB_FORCETYPE);
|
|
bsc_ulFlags |= (iNewForce<<BSCB_FORCETYPE);
|
|
}
|
|
INDEX GetFogType(void) {
|
|
return (bsc_ulFlags>>BSCB_FOGTYPE)&0xf;
|
|
}
|
|
void SetFogType(INDEX iNewForce) {
|
|
iNewForce&=0xf;
|
|
bsc_ulFlags &= ~(0xf<<BSCB_FOGTYPE);
|
|
bsc_ulFlags |= (iNewForce<<BSCB_FOGTYPE);
|
|
}
|
|
INDEX GetHazeType(void) {
|
|
return (bsc_ulFlags>>BSCB_HAZETYPE)&0xf;
|
|
}
|
|
void SetHazeType(INDEX iNewForce) {
|
|
iNewForce&=0xf;
|
|
bsc_ulFlags &= ~(0xf<<BSCB_HAZETYPE);
|
|
bsc_ulFlags |= (iNewForce<<BSCB_HAZETYPE);
|
|
}
|
|
inline INDEX GetEnvironmentType(void) {
|
|
return (bsc_ulFlags2>>BSCB2_ENVIRONMENTTYPE)&0xFF;
|
|
}
|
|
void SetEnvironmentType(INDEX iNewEnvironment)
|
|
{
|
|
iNewEnvironment&=0xFF;
|
|
bsc_ulFlags2 &= ~(0xFF<<BSCB2_ENVIRONMENTTYPE);
|
|
bsc_ulFlags2 |= (iNewEnvironment<<BSCB2_ENVIRONMENTTYPE);
|
|
}
|
|
|
|
// get amount of memory used by this object
|
|
SLONG GetUsedMemory(void);
|
|
};
|
|
|
|
|
|
// selection of brush sectors
|
|
typedef CSelection<CBrushSector, BSCF_SELECTED> CBrushSectorSelection;
|
|
// selection of brush sectors used for CSG
|
|
typedef CSelection<CBrushSector, BSCF_SELECTEDFORCSG> CBrushSectorSelectionForCSG;
|
|
|
|
/*
|
|
* One detail level of a brush.
|
|
*/
|
|
class ENGINE_API CBrushMip {
|
|
public:
|
|
// implementation:
|
|
CDynamicArray<CBrushSector> bm_abscSectors; // sectors
|
|
CBrush3D *bm_pbrBrush; // pointer to brush
|
|
|
|
/* Select all sectors within a range. */
|
|
void SelectSectorsInRange(CBrushSectorSelectionForCSG &selbscInRange, FLOATaabbox3D boxRange);
|
|
void SelectSectorsInRange(CBrushSectorSelection &selbscInRange, FLOATaabbox3D boxRange);
|
|
/* Select all sectors in brush. */
|
|
void SelectAllSectors(CBrushSectorSelectionForCSG &selbscAll);
|
|
void SelectAllSectors(CBrushSectorSelection &selbscAll);
|
|
/* Select open sector in brush. */
|
|
void SelectOpenSector(CBrushSectorSelectionForCSG &selbscOpen);
|
|
/* Select closed sectors in brush. */
|
|
void SelectClosedSectors(CBrushSectorSelectionForCSG &selbscClosed);
|
|
/* Fill a 3d object from a selection in a brush. */
|
|
void ToObject3D(CObject3D &ob, CBrushSectorSelection &selbscToCopy);
|
|
void ToObject3D(CObject3D &ob, CBrushSectorSelectionForCSG &selbscToCopy);
|
|
/* Add an object3d to brush. (returns pointer to the first created sector) */
|
|
CBrushSector *AddFromObject3D_t(CObject3D &ob); // throw char *
|
|
/* Delete all sectors in a selection. */
|
|
void DeleteSelectedSectors(CBrushSectorSelectionForCSG &selbscToDelete);
|
|
/* Spread all brush mips after this one. */
|
|
void SpreadFurtherMips(void);
|
|
/* Reoptimize all sectors in the brush mip. */
|
|
void Reoptimize(void);
|
|
/* Find all portals that have no links and kill their portal flag. */
|
|
void RemoveDummyPortals(BOOL bClearPortalFlags);
|
|
public:
|
|
// interface:
|
|
CListNode bm_lnInBrush; // for linking in list of mip-brushes for a brush
|
|
FLOAT bm_fMaxDistance; // distance after which this mip-brush is not displayed
|
|
FLOATaabbox3D bm_boxBoundingBox; // bounding box of entire mip-brush in absolute space
|
|
FLOATaabbox3D bm_boxRelative; // bounding box of entire mip-brush in relative space
|
|
|
|
/* Constructor. */
|
|
CBrushMip(void);
|
|
/* Free all memory and leave empty brush mip. */
|
|
void Clear(void);
|
|
/* Fill a brush mip from 3d object. */
|
|
void FromObject3D_t(CObject3D &ob); // throw char *
|
|
/* Copy brush mip from another brush mip. */
|
|
void Copy(CBrushMip &bmOther, FLOAT fStretch, BOOL bMirrorX);
|
|
|
|
/* Set mip distance of this mip, spread all that are further. */
|
|
void SetMipDistance(FLOAT fMipDistance);
|
|
/* Get mip factor of this mip. */
|
|
FLOAT GetMipDistance(void);
|
|
/* Get mip index of this mip. */
|
|
INDEX GetMipIndex(void);
|
|
// get next brush mip
|
|
CBrushMip *GetNext(void);
|
|
// get previous brush mip
|
|
CBrushMip *GetPrev(void);
|
|
// check if this is the first mip in this brush
|
|
inline BOOL IsFirstMip(void);
|
|
|
|
// overrides from CSerial
|
|
/* Read from stream. */
|
|
void Read_new_t( CTStream *istrFile); // throw char *
|
|
void Read_old_t( CTStream *istrFile); // throw char *
|
|
/* Write to stream. */
|
|
void Write_t( CTStream *ostrFile); // throw char *
|
|
|
|
/* Update bounding box from bounding boxes of all sectors. */
|
|
void UpdateBoundingBox(void);
|
|
/* Calculate bounding boxes in all sectors. */
|
|
void CalculateBoundingBoxes(CSimpleProjection3D_DOUBLE &prRelativeToAbsolute);
|
|
};
|
|
|
|
/*
|
|
* Brush class -- a piece of level that can be moved independently
|
|
*/
|
|
#define BRF_DRAWSELECTED (1L<<0) // internal marker for rendering selected brushes
|
|
#define BRF_DRAWFIRSTMIP (1L<<1) // viewer is inside this brush
|
|
|
|
class ENGINE_API CBrush3D : public CBrushBase {
|
|
public:
|
|
// implementation:
|
|
CListNode br_lnInActiveBrushes; // for linking in list of active brushes in renderer
|
|
CAnyProjection3D br_prProjection; // projection currently used by this brush
|
|
CEntity *br_penEntity; // back pointer from brush to its entity
|
|
class CFieldSettings *br_pfsFieldSettings;// field settings for field brushes
|
|
ULONG br_ulFlags; // brush flags
|
|
|
|
/* Wrapper for CObject3D::Optimize(), updates profiling information. */
|
|
static void OptimizeObject3D(CObject3D &ob);
|
|
|
|
/* Prepare a projection from brush space to absolute space. */
|
|
void PrepareRelativeToAbsoluteProjection(CSimpleProjection3D_DOUBLE &prRelativeToAbsolute);
|
|
/* Calculate bounding boxes in all brush mips. */
|
|
void CalculateBoundingBoxes(void);
|
|
void CalculateBoundingBoxesForOneMip(CBrushMip *pbmOnly); // for only one mip
|
|
INDEX GetBrushType() { return CBrushBase::BT_BRUSH3D; } // this is brush not terrain
|
|
|
|
public:
|
|
// interface:
|
|
CListHead br_lhBrushMips; // mip brushes in this brush
|
|
|
|
// constructor
|
|
CBrush3D(void);
|
|
// destructor
|
|
~CBrush3D(void);
|
|
|
|
/* Free all memory and leave empty brush. */
|
|
void Clear(void);
|
|
/* Fill a brush from 3d object. */
|
|
void FromObject3D_t(CObject3D &ob); // throw char *
|
|
void AddMipBrushFromObject3D_t(CObject3D &ob, FLOAT fSwitchDistance); // throw char *
|
|
/* Copy brush from another brush with possible mirror and stretch. */
|
|
void Copy(CBrush3D &brOther, FLOAT fStretch, BOOL bMirrorX);
|
|
|
|
/* Delete a brush mip with given factor. */
|
|
void DeleteBrushMip(CBrushMip *pbmToDelete);
|
|
/* Create a new brush mip. */
|
|
CBrushMip *NewBrushMipAfter(CBrushMip *pbm, BOOL bCopy);
|
|
CBrushMip *NewBrushMipBefore(CBrushMip *pbm, BOOL bCopy);
|
|
/* Get a brush mip for given mip-factor. */
|
|
CBrushMip *GetBrushMipByDistance(FLOAT fDistance);
|
|
/* Get a brush mip by its given index. */
|
|
CBrushMip *GetBrushMipByIndex(INDEX iMip);
|
|
// get first brush mip
|
|
CBrushMip *GetFirstMip(void);
|
|
// get last brush mip
|
|
CBrushMip *GetLastMip(void);
|
|
|
|
// switch from zoning to non-zoning
|
|
void SwitchToNonZoning(void);
|
|
// switch from non-zoning to zoning
|
|
void SwitchToZoning(void);
|
|
|
|
// overrides from CSerial
|
|
/* Read from stream. */
|
|
void Read_t( CTStream *istrFile); // throw char *
|
|
void Read_new_t( CTStream *istrFile); // throw char *
|
|
void Read_old_t( CTStream *istrFile); // throw char *
|
|
/* Write to stream. */
|
|
void Write_t( CTStream *ostrFile); // throw char *
|
|
};
|
|
|
|
// check if this is the first mip in this brush
|
|
inline BOOL CBrushMip::IsFirstMip(void) {
|
|
return &bm_pbrBrush->br_lhBrushMips.IterationHead() == &bm_lnInBrush;
|
|
};
|
|
|
|
|
|
|
|
#endif /* include-once check. */
|
|
|