263 lines
9.5 KiB
C++
263 lines
9.5 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================//
|
|
|
|
#ifndef DISP_COMMON_H
|
|
#define DISP_COMMON_H
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
#include "bspfile.h"
|
|
#include "disp_vertindex.h"
|
|
#include "utlvector.h"
|
|
|
|
class CPowerInfo;
|
|
class CCoreDispInfo;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// // Classes.
|
|
// -----------------------------------------------------------------------------
|
|
// //
|
|
|
|
// This class provides a set of utility functions for displacements that work in
|
|
// the tools and the engine.
|
|
abstract_class CDispUtilsHelper {
|
|
// Derived classes must implement these.
|
|
public:
|
|
virtual const CPowerInfo *GetPowerInfo() const = 0;
|
|
virtual CDispNeighbor *GetEdgeNeighbor(int index) = 0;
|
|
virtual CDispCornerNeighbors *GetCornerNeighbors(int index) = 0;
|
|
virtual CDispUtilsHelper *GetDispUtilsByIndex(int index) = 0;
|
|
|
|
// Helper functions.
|
|
public:
|
|
int GetPower() const;
|
|
int GetSideLength() const;
|
|
const CVertIndex &GetCornerPointIndex(int iCorner) const;
|
|
int VertIndexToInt(const CVertIndex &i) const;
|
|
CVertIndex GetEdgeMidPoint(int iEdge) const;
|
|
};
|
|
|
|
// Use this to walk along two neighboring displacements and touch all the
|
|
// common vertices.
|
|
class CDispSubEdgeIterator {
|
|
public:
|
|
CDispSubEdgeIterator();
|
|
|
|
// Normally, this will iterate all shared verts along the edge except the
|
|
// corners. If you want the corners to be touched too, then pass in
|
|
// bTouchCorners=true.
|
|
void Start(CDispUtilsHelper *pDisp, int iEdge, int iSub,
|
|
bool bTouchCorners = false);
|
|
bool Next();
|
|
|
|
const CVertIndex &GetVertIndex() const {
|
|
return m_Index;
|
|
} // Get the vert index for the displacement in pUtils.
|
|
const CVertIndex &GetNBVertIndex() const {
|
|
return m_NBIndex;
|
|
} // Get the neighbor's vert index.
|
|
CDispUtilsHelper *GetNeighbor() const { return m_pNeighbor; }
|
|
|
|
// Returns true if you're on the last vert (ie: the next Next() call will
|
|
// return false).ssssss
|
|
bool IsLastVert() const;
|
|
|
|
private:
|
|
CDispUtilsHelper
|
|
*m_pNeighbor; // The neighbor to the edge we were setup on.
|
|
|
|
CVertIndex m_Index;
|
|
CVertIndex m_Inc;
|
|
|
|
CVertIndex m_NBIndex;
|
|
CVertIndex m_NBInc;
|
|
|
|
int m_End;
|
|
int m_FreeDim;
|
|
};
|
|
|
|
// Use this to walk along the edge of a displacement, touching the points in
|
|
// common between the two neighbors. Note: this won't hit the corner points of
|
|
// any of the displacements. (As a result, it won't hit the midpoint of pDisps's
|
|
// edge if there are 2 neighbors).
|
|
class CDispEdgeIterator {
|
|
public:
|
|
CDispEdgeIterator(CDispUtilsHelper *pDisp, int iEdge);
|
|
|
|
// Seek to the next point on the edge.
|
|
bool Next();
|
|
|
|
const CVertIndex &GetVertIndex() const {
|
|
return m_It.GetVertIndex();
|
|
} // Get the vert index for the displacement in pUtils.
|
|
const CVertIndex &GetNBVertIndex() const {
|
|
return m_It.GetNBVertIndex();
|
|
} // Get the neighbor's vert index.
|
|
|
|
// What is the current neighbor?
|
|
CDispUtilsHelper *GetCurrentNeighbor() const { return m_It.GetNeighbor(); }
|
|
|
|
private:
|
|
CDispUtilsHelper *m_pDisp;
|
|
int m_iEdge;
|
|
int m_iCurSub;
|
|
|
|
CDispSubEdgeIterator m_It;
|
|
};
|
|
|
|
// Use this to walk all the corners and edge verts in the displacement.
|
|
// It walks the edges in the order of the NEIGHBOREDGE_ defines.
|
|
// Iterate like this:
|
|
// CDispCircumferenceIterator iterator( pDisp->GetSideLength() );
|
|
// while ( iterator.Next() )
|
|
// ...
|
|
class CDispCircumferenceIterator {
|
|
public:
|
|
CDispCircumferenceIterator(int sideLength);
|
|
|
|
// Seek to the next point. Returns false when there are no more points.
|
|
bool Next();
|
|
|
|
const CVertIndex &GetVertIndex() const { return m_VertIndex; }
|
|
|
|
private:
|
|
int m_SideLengthM1;
|
|
int m_iCurEdge;
|
|
CVertIndex m_VertIndex;
|
|
};
|
|
|
|
// These store info about how to scale and shift coordinates between neighbors
|
|
// of different relations (in g_ShiftInfos).
|
|
class CShiftInfo {
|
|
public:
|
|
int m_MidPointScale;
|
|
int m_PowerShiftAdd;
|
|
bool m_bValid;
|
|
};
|
|
|
|
class CDispBox {
|
|
public:
|
|
Vector m_Min, m_Max;
|
|
};
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// // Globals.
|
|
// -----------------------------------------------------------------------------
|
|
// //
|
|
|
|
extern int g_EdgeDims[4]; // This tells which dimension (0 or 1) is locked on
|
|
// an edge for each NEIGHBOREDGE_ enum.
|
|
extern CShiftInfo g_ShiftInfos[3][3]; // See CShiftInfo.
|
|
extern int g_EdgeSideLenMul[4]; // Multiply these by the side length to get the
|
|
// index of the edge.
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// // Helper functions.
|
|
// -----------------------------------------------------------------------------
|
|
// //
|
|
|
|
// Reference implementation to generate triangle indices for a displacement.
|
|
int DispCommon_GetNumTriIndices(int power);
|
|
void DispCommon_GenerateTriIndices(int power, unsigned short *indices);
|
|
|
|
// Returns a NEIGHBOREDGE_ value for the edge that the index is on.
|
|
// Returns -1 if the index is not on a side.
|
|
// If the point is on a corner, the edges are tested in the order of the
|
|
// NEIGHBOREDGE_ defines.
|
|
int GetEdgeIndexFromPoint(CVertIndex const &index, int iPower);
|
|
|
|
// Returns a CORNER_ value for the corner the point is on, or -1 if it's not on
|
|
// a corner.
|
|
int GetEdgeIndexFromPoint(CVertIndex const &index, int iPower);
|
|
|
|
// This returns the neighbor's power, possibly +1 or -1.
|
|
//
|
|
// It will add one if the neighbor takes up half of your edge (ie: if it took up
|
|
// your whole edge, its resolution would be twice what it really is).
|
|
//
|
|
// It will subtract one if you take up half of its edge (ie: you only touch half
|
|
// of its verts).
|
|
//
|
|
// Returns -1 if the edge connection is invalid.
|
|
int GetNeighborEdgePower(CDispUtilsHelper *pDisp, int iEdge, int iSub);
|
|
|
|
// This function sets you up so you can walk along an edge that joins two
|
|
// neighbors. Add myInc to myIndex and nbInc to nbIndex until myIndex[iFreeDim]
|
|
// >= myEnd.
|
|
//
|
|
// Returns the neighbor displacement, or NULL if the specified sub neighbor
|
|
// isn't valid.
|
|
CDispUtilsHelper *SetupEdgeIncrements(CDispUtilsHelper *pDisp, int iEdge,
|
|
int iSub, CVertIndex &myIndex,
|
|
CVertIndex &myInc, CVertIndex &nbIndex,
|
|
CVertIndex &nbInc, int &myEnd,
|
|
int &iFreeDim);
|
|
|
|
// Figure out which sub neighbor nodeIndex touches.
|
|
// Returns -1 if there is no valid sub neighbor at the specified index.
|
|
int GetSubNeighborIndex(CDispUtilsHelper *pDisp, int iEdge,
|
|
CVertIndex const &nodeIndex);
|
|
|
|
// Given a vert index and the CSubNeighbor the vert lies on, this
|
|
// transforms the specified vert into the neighbor's space.
|
|
//
|
|
// Note: for corner verts, there may be multiple neighbors touching the same
|
|
// vert, so the
|
|
// result you get depends on the edge you specify in iEdge (ie: if you
|
|
// specify the same node index but a different edge, you may get a
|
|
// different neighbor).
|
|
//
|
|
// Note: This only returns a point if the point at nodeIndex actually touches a
|
|
// neighbor point.
|
|
// An example where this might be unexpected is if pDisp is power 4 and
|
|
// its neighbor on iEdge is power 3, and nodeIndex points at a vert in
|
|
// between two of its neighbor's verts. In that case, even though there is
|
|
// a neighbor displacement, nodeIndex doesn't touch any points on it, so
|
|
// NULL is returned.
|
|
CDispUtilsHelper *TransformIntoSubNeighbor(CDispUtilsHelper *pDisp, int iEdge,
|
|
int iSub,
|
|
CVertIndex const &nodeIndex,
|
|
CVertIndex &out);
|
|
|
|
// Transform pDisp's node at nodeIndex into its neighboring connection.
|
|
// Returns the neighbor displacement and sets out to the index in the neighbor.
|
|
//
|
|
// Note: for corner verts, there may be multiple neighbors touching the same
|
|
// vert, so the
|
|
// result you get depends on the edge you specify in iEdge (ie: if you
|
|
// specify the same node index but a different edge, you may get a
|
|
// different neighbor).
|
|
//
|
|
// Note: This only returns a point if the point at nodeIndex actually touches a
|
|
// neighbor point.
|
|
// An example where this might surprise you is if pDisp is power 4 and its
|
|
// neighbor on iEdge is power 3, and nodeIndex points at a vert in between
|
|
// two of its neighbor's verts. In that case, even though there is a
|
|
// neighbor displacement, nodeIndex doesn't touch any points on it, so
|
|
// NULL is returned.
|
|
CDispUtilsHelper *TransformIntoNeighbor(CDispUtilsHelper *pDisp, int iEdge,
|
|
CVertIndex const &nodeIndex,
|
|
CVertIndex &out);
|
|
|
|
// Returns true if the specified point has one or more neighbors.
|
|
bool DoesPointHaveAnyNeighbors(CDispUtilsHelper *pDisp,
|
|
const CVertIndex &index);
|
|
|
|
void FindNeighboringDispSurfs(CCoreDispInfo **ppListBase, int nListSize);
|
|
void SetupAllowedVerts(CCoreDispInfo **ppListBase, int nListSize);
|
|
void GetDispBox(CCoreDispInfo *pDisp, CDispBox &box);
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// // Inlines.
|
|
// -----------------------------------------------------------------------------
|
|
// //
|
|
|
|
#include "disp_powerinfo.h"
|
|
|
|
#endif // DISP_COMMON_H
|