Files
2025-09-18 17:55:52 -04:00

140 lines
4.3 KiB
C++

#pragma once
#include "V8World/Poly.h"
#include "V8World/GeometryPool.h"
#include "V8World/BlockCorners.h"
#include "V8World/BlockMesh.h"
#include "V8World/BulletGeometryPoolObjects.h"
#include "V8Kernel/ContactParams.h"
#include "Util/NormalID.h"
#include "rbx/Debug.h"
namespace RBX {
class Block : public Poly {
friend class TriangleMesh;
private:
typedef Poly Super;
public:
typedef GeometryPool<Vector3, POLY::BlockMesh, Vector3Comparer> BlockMeshPool;
typedef GeometryPool<Vector3, POLY::BlockCorners, Vector3Comparer> BlockCornersPool;
typedef GeometryPool<Vector3, BulletBoxShapeWrapper, Vector3Comparer> BulletBoxShapePool;
private:
BlockCornersPool::Token blockCorners;
BlockMeshPool::Token blockMesh;
BulletBoxShapePool::Token bulletBoxShape;
const Vector3* vertices; // in Real World units, object coords - shortcut to wrapper data
static const int BLOCK_FACE_TO_VERTEX[6][4];
static const int BLOCK_FACE_VERTEX_TO_EDGE[6][4];
// loading GeoPair stuff
const Vector3* getCornerPoint(const Vector3int16& clip) const;
const Vector3* getEdgePoint(const Vector3int16& clip, NormalId& normalID) const;
const Vector3* getPlanePoint(const Vector3int16& clip, NormalId& normalID) const;
Matrix3 getMomentHollow(float mass) const;
/*override*/ void setSize(const G3D::Vector3& _size);
// Primitive Overrides
/*override*/ virtual bool hitTest(const RbxRay& rayInMe, Vector3& localHitPoint, Vector3& surfaceNormal);
/*override*/ virtual GeometryType getGeometryType() const {return GEOMETRY_BLOCK;}
/*override*/ virtual CollideType getCollideType() const {return COLLIDE_BLOCK;}
public:
// Real Corner
/*override*/ virtual Vector3 getCenterToCorner(const Matrix3& rotation) const;
private:
// Moment
/*override*/ virtual Matrix3 getMoment(float mass) const {return getMomentHollow(mass);}
// Volume
/*override*/ float getVolume() const;
// Poly Overrides
/*override*/ void buildMesh();
void updateBulletCollisionData();
public:
Block() : vertices(NULL) {}
~Block() {}
static void init();
///////////////////////////////////////////////////////////////
//
// Block Specific Collision Detection
void projectToFace(Vector3& ray, Vector3int16& clip, int& onBorder);
GeoPairType getBallInsideInfo(const Vector3& ray, const Vector3* &offset,
NormalId& normalID);
GeoPairType getBallBlockInfo(int onBorder, const Vector3int16 clip, const Vector3* &offset,
NormalId& normalID);
inline const float* getVertices() const {
return (float*)vertices;
}
inline const Vector3& getExtent() const {
return vertices[0];
}
const Vector3* getFaceVertex(NormalId faceID, int vertID) const {
return &vertices[ BLOCK_FACE_TO_VERTEX[faceID][vertID] ];
}
int getClosestEdge(const Matrix3& rotation, NormalId normalID, const Vector3& crossAxis);
// tricky - given a face and a vertex on it, find the edge
// assumes that the vertices are in counterclockwise order on the face,
// and gives the edge that connects this vertex with the next one in
// counter-clockwise order
inline int faceVertexToEdge(NormalId faceID, int vertID) {
return BLOCK_FACE_VERTEX_TO_EDGE[faceID][vertID];
}
// same as the previsous, but gives the edge that
// connects with the next in clockwise order
inline int faceVertexToClockwiseEdge(NormalId faceID, int vertID) {
return 12 + BLOCK_FACE_VERTEX_TO_EDGE[faceID][vertID];
}
const Vector3* getEdgeVertex(int edgeId) const {
if (edgeId < 12) {
return &vertices[ Block::BLOCK_FACE_TO_VERTEX[edgeId / 4][edgeId % 4] ];
}
else {
int ccwEdge = edgeId - 12; // convert to regular..
NormalId faceId = (NormalId) (ccwEdge / 4);
RBXASSERT(validNormalId(faceId));
int vertId = ccwEdge+1 % 4; // one higher - add
return &vertices[ Block::BLOCK_FACE_TO_VERTEX[faceId][vertId] ];
}
}
// returns X,-X,X,-X,Y,-Y,Y,-Y,Z,-Z,Z,-Z
inline NormalId getEdgeNormal(int edgeId) {
NormalId ans = static_cast<NormalId>((edgeId / 4) + (3*(edgeId % 2)));
if (edgeId > 12) {
ans = static_cast<NormalId>((ans + 3) % 6);
}
return ans;
}
Vector2 getProjectedVertex(const Vector3& vertex, NormalId normalID);
// Currently used by dragger
/*override*/ CoordinateFrame getSurfaceCoordInBody( const size_t surfaceId ) const;
/*override*/ bool setUpBulletCollisionData(void);
};
} // namespace