mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-07 05:57:47 +00:00
GEEKING
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
#pragma once
|
||||
|
||||
#include "Util/G3DCore.h"
|
||||
#include "Voxel/Cell.h"
|
||||
#include "rbx/Debug.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This file has methods for reading and writing individual voxel cells
|
||||
|
||||
namespace RBX {
|
||||
using namespace Voxel;
|
||||
namespace V1Deprecated {
|
||||
|
||||
const unsigned char UNIQUE_EMPTY_CELL_REPRESENTATION = ((unsigned char)CELL_BLOCK_Empty << 3);
|
||||
const unsigned char WATER_ON_WEDGE_CELL = ((unsigned char) UNIQUE_EMPTY_CELL_REPRESENTATION + 3);
|
||||
|
||||
|
||||
// Helper functions to access bit aligned properties of the cell grid
|
||||
// opted for this instead of a bit field struct in case of portability requirements
|
||||
/*struct Terrain
|
||||
{
|
||||
unused: 3;
|
||||
unsigned block : 3;
|
||||
unsigned orientation: 2;
|
||||
};*/
|
||||
/*struct Water
|
||||
{
|
||||
water_state : 3;
|
||||
unsigned block : 3;
|
||||
water_state : 2;
|
||||
};*/
|
||||
// Water state has 5 bits total, so 32 possibilities. 30 of them used as (6 water cell directions x 5 water forces)
|
||||
inline CellMaterial getCellMaterial_Deprecated( unsigned char cell ) { return (CellMaterial)(cell & 0x07); }
|
||||
inline CellBlock getCellBlock( unsigned char cell ) { return (CellBlock)((cell & 0x38) >> 3); }
|
||||
inline CellOrientation getCellOrientation( unsigned char cell ) { return (CellOrientation)((cell & 0xc0) >> 6); }
|
||||
inline WaterCellForce getWaterCellForce( unsigned char cell ) {
|
||||
unsigned char nonBlockData = (((cell >> 3) & 0x18) | (cell & 0x7)) - 1;
|
||||
return (WaterCellForce) ((nonBlockData / MAX_WATER_CELL_DIRECTIONS) % MAX_WATER_CELL_FORCES);
|
||||
}
|
||||
inline WaterCellDirection getWaterCellDirection( unsigned char cell ) {
|
||||
unsigned char nonBlockData = (((cell >> 3) & 0x18) | (cell & 0x7)) - 1;
|
||||
return (WaterCellDirection) (nonBlockData % MAX_WATER_CELL_DIRECTIONS);
|
||||
}
|
||||
|
||||
// IMPORTANT! DUE TO THE ENCODING, THIS ONLY WORKS WHEN THE MATERIALS
|
||||
// POINTER PASSED IN IS MEANT TO INDICATE cellIndex 0 and cellIndex 1
|
||||
// (for example, if you created a cell box pointing to cell 5 as cell
|
||||
// index 0, then this computation will have an off-by-one error).
|
||||
// To account for this restriction, anywhere that material pointers are
|
||||
// stored, be sure to only store pointers corresponding to even-indexed
|
||||
// cells.
|
||||
inline unsigned char readMaterial(const unsigned char* materials, const unsigned int cellIndex, const unsigned char cellValue) {
|
||||
return getCellBlock(cellValue) == CELL_BLOCK_Empty ?
|
||||
CELL_MATERIAL_Water :
|
||||
((materials[cellIndex >> 1] >> (4 * (cellIndex & 0x1))) & 0x0f) + 1;
|
||||
}
|
||||
inline void writeMaterial(unsigned char* materials, unsigned int cellIndex, const unsigned char newMaterial) {
|
||||
RBXASSERT(newMaterial > 0);
|
||||
unsigned char& wholeByte = materials[cellIndex >> 1];
|
||||
unsigned int shift = (4 * (cellIndex & 0x1));
|
||||
unsigned char mask = 0x0f << shift;
|
||||
wholeByte &= (~mask);
|
||||
wholeByte |= (((newMaterial-1) << shift) & mask);
|
||||
}
|
||||
|
||||
inline void setCellMaterial_Deprecated( unsigned char& cell, CellMaterial material ) { cell = (cell & 0xf8) | ((int)material & 0x07); }
|
||||
inline void setCellBlock( unsigned char& cell, CellBlock block ) { cell = (cell & 0xc7) | (((int)block & 0x07) << 3); }
|
||||
inline void setCellOrientation( unsigned char& cell, CellOrientation orientation ) { cell = (cell & 0x3f) | (((int)orientation & 0x03) << 6); }
|
||||
inline void setWaterForceAndDirection( unsigned char& cell, WaterCellForce force, WaterCellDirection direction) {
|
||||
unsigned char rawData = force * MAX_WATER_CELL_DIRECTIONS + direction + 1;
|
||||
cell = (cell & (0x38)) | (rawData & 0x7) | ((rawData & 0x18) << 3);
|
||||
}
|
||||
|
||||
inline bool isCellEmpty( unsigned char cell ) { return cell == UNIQUE_EMPTY_CELL_REPRESENTATION; }
|
||||
|
||||
struct CellChangeInfo {
|
||||
const Vector3int16 position;
|
||||
|
||||
unsigned char beforeCell;
|
||||
unsigned char afterCell;
|
||||
unsigned char beforeWaterCell;
|
||||
unsigned char afterWaterCell;
|
||||
unsigned char afterMaterial;
|
||||
|
||||
CellChangeInfo(const Vector3int16& position,
|
||||
unsigned char beforeCell, unsigned char afterCell,
|
||||
unsigned char beforeWaterCell, unsigned char afterWaterCell,
|
||||
unsigned char afterMaterial)
|
||||
: position(position)
|
||||
, beforeCell(beforeCell)
|
||||
, afterCell(afterCell)
|
||||
, beforeWaterCell(beforeWaterCell)
|
||||
, afterWaterCell(afterWaterCell)
|
||||
, afterMaterial(afterMaterial)
|
||||
{ }
|
||||
};
|
||||
|
||||
enum FaceDirection
|
||||
{
|
||||
PlusX = 0,
|
||||
PlusZ = 1,
|
||||
MinusX = 2,
|
||||
MinusZ = 3,
|
||||
PlusY = 4,
|
||||
MinusY = 5,
|
||||
Invalid = 6
|
||||
};
|
||||
|
||||
struct BlockAxisFace {
|
||||
enum SkippedCorner {
|
||||
TopRight = 0,
|
||||
TopLeft = 1,
|
||||
BottomLeft = 2,
|
||||
BottomRight = 3,
|
||||
EmptyAllSkipped = 4,
|
||||
FullNoneSkipped = 5
|
||||
};
|
||||
|
||||
SkippedCorner skippedCorner;
|
||||
|
||||
static inline SkippedCorner rotate(SkippedCorner corner, const CellOrientation orient) {
|
||||
return (SkippedCorner) (corner < 4 ? (corner + orient) % 4 : corner);
|
||||
}
|
||||
|
||||
static inline bool divideTopLeftToBottomRight(SkippedCorner corner) {
|
||||
return corner == TopRight || corner == BottomLeft || corner == FullNoneSkipped;
|
||||
}
|
||||
|
||||
static inline SkippedCorner XZAxisMirror(SkippedCorner corner) {
|
||||
static SkippedCorner MIRROR[6] =
|
||||
{ TopLeft, TopRight, BottomRight, BottomLeft, EmptyAllSkipped, FullNoneSkipped };
|
||||
return MIRROR[corner];
|
||||
}
|
||||
|
||||
static inline SkippedCorner YAxisMirror(SkippedCorner corner) {
|
||||
static SkippedCorner MIRROR[6] =
|
||||
{ BottomRight, BottomLeft, TopLeft, TopRight, EmptyAllSkipped, FullNoneSkipped };
|
||||
return MIRROR[corner];
|
||||
}
|
||||
|
||||
static BlockAxisFace inverse(const BlockAxisFace other) {
|
||||
static const SkippedCorner OPPOSITE_CORNER[6] = {
|
||||
BottomLeft,
|
||||
BottomRight,
|
||||
TopRight,
|
||||
TopLeft,
|
||||
FullNoneSkipped,
|
||||
EmptyAllSkipped
|
||||
};
|
||||
|
||||
BlockAxisFace out;
|
||||
out.skippedCorner = OPPOSITE_CORNER[other.skippedCorner];
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
struct BlockFaceInfo {
|
||||
// indexed by FaceDirection
|
||||
BlockAxisFace faces[6];
|
||||
};
|
||||
|
||||
extern const BlockFaceInfo UnOrientedBlockFaceInfos[6];
|
||||
extern BlockAxisFace OrientedFaceMap[ 1536 ]; // 2^8 * 6
|
||||
|
||||
// ComputeOrientedFace is not declared because it is an implementation detail
|
||||
void initBlockOrientationFaceMap();
|
||||
|
||||
inline const BlockAxisFace& GetOrientedFace(unsigned char cell, FaceDirection f)
|
||||
{
|
||||
return OrientedFaceMap[ cell*6 + f ];
|
||||
}
|
||||
|
||||
inline bool isWedgeSideNotFull(unsigned char cell, FaceDirection f) {
|
||||
return GetOrientedFace(cell, f).skippedCorner != BlockAxisFace::FullNoneSkipped;
|
||||
}
|
||||
|
||||
// WARNING: Most of the time you want to use getWaterCellInternal().
|
||||
// There are many edge cases when using either of these methods, don't use them
|
||||
// unless you understand the edge cases. getWaterCellInternal encapsulates all
|
||||
// of the edge cases for you.
|
||||
inline bool isExplicitWaterCell(const unsigned char test) {
|
||||
return getCellBlock(test) == CELL_BLOCK_Empty && !isCellEmpty(test);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user