mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-16 19:15:14 -04:00
Combine PickedPos and RayTracer into one struct
This commit is contained in:
parent
37109cb18a
commit
3e0e83a60a
@ -11,7 +11,7 @@
|
||||
#include "Options.h"
|
||||
|
||||
struct _CameraData Camera;
|
||||
static struct PickedPos cameraClipPos;
|
||||
static struct RayTracer cameraClipPos;
|
||||
static Vec2 cam_rotOffset;
|
||||
static cc_bool cam_isForwardThird;
|
||||
static int cam_deltaX, cam_deltaY;
|
||||
@ -42,12 +42,12 @@ static void PerspectiveCamera_GetView(struct Matrix* mat) {
|
||||
Matrix_MulBy(mat, &Camera.TiltM);
|
||||
}
|
||||
|
||||
static void PerspectiveCamera_GetPickedBlock(struct PickedPos* pos) {
|
||||
static void PerspectiveCamera_GetPickedBlock(struct RayTracer* t) {
|
||||
struct Entity* p = &LocalPlayer_Instance.Base;
|
||||
Vec3 dir = Vec3_GetDirVector(p->Yaw * MATH_DEG2RAD, p->Pitch * MATH_DEG2RAD);
|
||||
Vec3 eyePos = Entity_GetEyePosition(p);
|
||||
float reach = LocalPlayer_Instance.ReachDistance;
|
||||
Picking_CalcPickedBlock(&eyePos, &dir, reach, pos);
|
||||
Picking_CalcPickedBlock(&eyePos, &dir, reach, t);
|
||||
}
|
||||
|
||||
#define CAMERA_SENSI_FACTOR (0.0002f / 3.0f * MATH_RAD2DEG)
|
||||
|
@ -5,7 +5,7 @@
|
||||
/* Represents a camera, may be first or third person.
|
||||
Copyright 2014-2019 ClassiCube | Licensed under BSD-3
|
||||
*/
|
||||
struct PickedPos;
|
||||
struct RayTracer;
|
||||
struct Camera;
|
||||
|
||||
/* Shared data for cameras. */
|
||||
@ -55,7 +55,7 @@ struct Camera {
|
||||
void (*LoseFocus)(void);
|
||||
|
||||
/* Calculates selected block in the world, based on camera's current state */
|
||||
void (*GetPickedBlock)(struct PickedPos* pos);
|
||||
void (*GetPickedBlock)(struct RayTracer* t);
|
||||
/* Zooms the camera in or out when scrolling mouse wheel. */
|
||||
cc_bool (*Zoom)(float amount);
|
||||
|
||||
|
@ -38,7 +38,7 @@ struct _GameData Game;
|
||||
int Game_Port;
|
||||
cc_bool Game_UseCPEBlocks;
|
||||
|
||||
struct PickedPos Game_SelectedPos;
|
||||
struct RayTracer Game_SelectedPos;
|
||||
int Game_ViewDistance, Game_MaxViewDistance, Game_UserViewDistance;
|
||||
int Game_Fov, Game_DefaultFov, Game_ZoomFov;
|
||||
|
||||
@ -545,7 +545,7 @@ static void Game_Render3D(double delta, float t) {
|
||||
|
||||
/* Need to render again over top of translucent block, as the selection outline */
|
||||
/* is drawn without writing to the depth buffer */
|
||||
if (Game_SelectedPos.Valid && !Game_HideGui && Blocks.Draw[Game_SelectedPos.Block] == DRAW_TRANSLUCENT) {
|
||||
if (Game_SelectedPos.Valid && !Game_HideGui && Blocks.Draw[Game_SelectedPos.block] == DRAW_TRANSLUCENT) {
|
||||
PickedPosRenderer_Render();
|
||||
}
|
||||
|
||||
@ -641,7 +641,7 @@ static void Game_RenderFrame(double delta) {
|
||||
if (!Gui_GetBlocksWorld() && World.Blocks) {
|
||||
Game_Render3D(delta, t);
|
||||
} else {
|
||||
PickedPos_SetAsInvalid(&Game_SelectedPos);
|
||||
RayTracer_SetInvalid(&Game_SelectedPos);
|
||||
}
|
||||
|
||||
Gui_RenderGui(delta);
|
||||
|
@ -19,7 +19,7 @@ CC_VAR extern struct _GameData {
|
||||
int ChunkUpdates;
|
||||
} Game;
|
||||
|
||||
extern struct PickedPos Game_SelectedPos;
|
||||
extern struct RayTracer Game_SelectedPos;
|
||||
extern cc_bool Game_UseCPEBlocks;
|
||||
|
||||
extern String Game_Username;
|
||||
|
@ -678,7 +678,7 @@ static void DoDeleteBlock(void) {
|
||||
/* always play delete animations, even if we aren't deleting a block */
|
||||
HeldBlockRenderer_ClickAnim(true);
|
||||
|
||||
pos = Game_SelectedPos.BlockPos;
|
||||
pos = Game_SelectedPos.pos;
|
||||
if (!Game_SelectedPos.Valid || !World_Contains(pos.X, pos.Y, pos.Z)) return;
|
||||
|
||||
old = World_GetBlock(pos.X, pos.Y, pos.Z);
|
||||
@ -710,7 +710,7 @@ static void DoPlaceBlock(void) {
|
||||
static void DoPickBlock(void) {
|
||||
IVec3 pos;
|
||||
BlockID cur;
|
||||
pos = Game_SelectedPos.BlockPos;
|
||||
pos = Game_SelectedPos.pos;
|
||||
if (!World_Contains(pos.X, pos.Y, pos.Z)) return;
|
||||
|
||||
cur = World_GetBlock(pos.X, pos.Y, pos.Z);
|
||||
|
@ -42,7 +42,7 @@ x,3,0, x,2,0, x,2,3, x,3,3,
|
||||
0,0,z, 0,1,z, 3,1,z, 3,0,z,\
|
||||
0,3,z, 0,2,z, 3,2,z, 3,3,z,
|
||||
|
||||
void PickedPosRenderer_Update(struct PickedPos* selected) {
|
||||
void PickedPosRenderer_Update(struct RayTracer* selected) {
|
||||
static const cc_uint8 indices[288] = {
|
||||
PickedPos_Y(0) PickedPos_Y(3) /* YMin, YMax */
|
||||
PickedPos_X(0) PickedPos_X(3) /* XMin, XMax */
|
||||
|
@ -4,10 +4,10 @@
|
||||
/* Renders an outline around the block the player is looking at.
|
||||
Copyright 2014-2019 ClassiCube | Licensed under BSD-3
|
||||
*/
|
||||
struct PickedPos;
|
||||
struct RayTracer;
|
||||
struct IGameComponent;
|
||||
extern struct IGameComponent PickedPosRenderer_Component;
|
||||
|
||||
void PickedPosRenderer_Render(void);
|
||||
void PickedPosRenderer_Update(struct PickedPos* selected);
|
||||
void PickedPosRenderer_Update(struct RayTracer* selected);
|
||||
#endif
|
||||
|
154
src/Picking.c
154
src/Picking.c
@ -10,51 +10,44 @@
|
||||
#include "Camera.h"
|
||||
|
||||
static float pickedPos_dist;
|
||||
static void PickedPos_TestAxis(struct PickedPos* pos, float dAxis, Face fAxis) {
|
||||
static void TestAxis(struct RayTracer* t, float dAxis, Face fAxis) {
|
||||
dAxis = Math_AbsF(dAxis);
|
||||
if (dAxis >= pickedPos_dist) return;
|
||||
|
||||
pickedPos_dist = dAxis;
|
||||
pos->Closest = fAxis;
|
||||
t->Closest = fAxis;
|
||||
}
|
||||
|
||||
void PickedPos_SetAsValid(struct PickedPos* pos, struct RayTracer* t, const Vec3* intersect) {
|
||||
pos->BlockPos.X = t->X;
|
||||
pos->BlockPos.Y = t->Y;
|
||||
pos->BlockPos.Z = t->Z;
|
||||
pos->TranslatedPos = pos->BlockPos;
|
||||
|
||||
pos->Valid = true;
|
||||
pos->Block = t->Block;
|
||||
pos->Intersect = *intersect;
|
||||
pos->Min = t->Min; pos->Max = t->Max;
|
||||
static void SetAsValid(struct RayTracer* t) {
|
||||
t->TranslatedPos = t->pos;
|
||||
t->Valid = true;
|
||||
|
||||
pickedPos_dist = MATH_LARGENUM;
|
||||
PickedPos_TestAxis(pos, intersect->X - t->Min.X, FACE_XMIN);
|
||||
PickedPos_TestAxis(pos, intersect->X - t->Max.X, FACE_XMAX);
|
||||
PickedPos_TestAxis(pos, intersect->Y - t->Min.Y, FACE_YMIN);
|
||||
PickedPos_TestAxis(pos, intersect->Y - t->Max.Y, FACE_YMAX);
|
||||
PickedPos_TestAxis(pos, intersect->Z - t->Min.Z, FACE_ZMIN);
|
||||
PickedPos_TestAxis(pos, intersect->Z - t->Max.Z, FACE_ZMAX);
|
||||
TestAxis(t, t->Intersect.X - t->Min.X, FACE_XMIN);
|
||||
TestAxis(t, t->Intersect.X - t->Max.X, FACE_XMAX);
|
||||
TestAxis(t, t->Intersect.Y - t->Min.Y, FACE_YMIN);
|
||||
TestAxis(t, t->Intersect.Y - t->Max.Y, FACE_YMAX);
|
||||
TestAxis(t, t->Intersect.Z - t->Min.Z, FACE_ZMIN);
|
||||
TestAxis(t, t->Intersect.Z - t->Max.Z, FACE_ZMAX);
|
||||
|
||||
switch (pos->Closest) {
|
||||
case FACE_XMIN: pos->TranslatedPos.X--; break;
|
||||
case FACE_XMAX: pos->TranslatedPos.X++; break;
|
||||
case FACE_ZMIN: pos->TranslatedPos.Z--; break;
|
||||
case FACE_ZMAX: pos->TranslatedPos.Z++; break;
|
||||
case FACE_YMIN: pos->TranslatedPos.Y--; break;
|
||||
case FACE_YMAX: pos->TranslatedPos.Y++; break;
|
||||
switch (t->Closest) {
|
||||
case FACE_XMIN: t->TranslatedPos.X--; break;
|
||||
case FACE_XMAX: t->TranslatedPos.X++; break;
|
||||
case FACE_ZMIN: t->TranslatedPos.Z--; break;
|
||||
case FACE_ZMAX: t->TranslatedPos.Z++; break;
|
||||
case FACE_YMIN: t->TranslatedPos.Y--; break;
|
||||
case FACE_YMAX: t->TranslatedPos.Y++; break;
|
||||
}
|
||||
}
|
||||
|
||||
void PickedPos_SetAsInvalid(struct PickedPos* pos) {
|
||||
static const IVec3 blockPos = { -1, -1, -1 };
|
||||
pos->BlockPos = blockPos;
|
||||
pos->TranslatedPos = blockPos;
|
||||
void RayTracer_SetInvalid(struct RayTracer* t) {
|
||||
static const IVec3 pos = { -1, -1, -1 };
|
||||
t->pos = pos;
|
||||
t->TranslatedPos = pos;
|
||||
|
||||
pos->Valid = false;
|
||||
pos->Block = BLOCK_AIR;
|
||||
pos->Closest = FACE_COUNT;
|
||||
t->Valid = false;
|
||||
t->block = BLOCK_AIR;
|
||||
t->Closest = FACE_COUNT;
|
||||
}
|
||||
|
||||
static float RayTracer_Div(float a, float b) {
|
||||
@ -63,22 +56,21 @@ static float RayTracer_Div(float a, float b) {
|
||||
}
|
||||
|
||||
void RayTracer_Init(struct RayTracer* t, const Vec3* origin, const Vec3* dir) {
|
||||
IVec3 start, cellBoundary;
|
||||
t->Origin = *origin; t->Dir = *dir;
|
||||
IVec3 cellBoundary;
|
||||
t->origin = *origin; t->dir = *dir;
|
||||
|
||||
/* Rounds the position's X, Y and Z down to the nearest integer values. */
|
||||
IVec3_Floor(&start, origin);
|
||||
/* The cell in which the ray starts. */
|
||||
t->X = start.X; t->Y = start.Y; t->Z = start.Z;
|
||||
/* Determine which way we go.*/
|
||||
IVec3_Floor(&t->pos, origin);
|
||||
/* Determine which way we go. */
|
||||
t->step.X = Math_Sign(dir->X); t->step.Y = Math_Sign(dir->Y); t->step.Z = Math_Sign(dir->Z);
|
||||
|
||||
/* Calculate cell boundaries. When the step (i.e. direction sign) is positive,
|
||||
the next boundary is AFTER our current position, meaning that we have to add 1.
|
||||
Otherwise, it is BEFORE our current position, in which case we add nothing. */
|
||||
cellBoundary.X = start.X + (t->step.X > 0 ? 1 : 0);
|
||||
cellBoundary.Y = start.Y + (t->step.Y > 0 ? 1 : 0);
|
||||
cellBoundary.Z = start.Z + (t->step.Z > 0 ? 1 : 0);
|
||||
cellBoundary.X = t->pos.X + (t->step.X > 0 ? 1 : 0);
|
||||
cellBoundary.Y = t->pos.Y + (t->step.Y > 0 ? 1 : 0);
|
||||
cellBoundary.Z = t->pos.Z + (t->step.Z > 0 ? 1 : 0);
|
||||
|
||||
/* NOTE: we want it so if dir.x = 0, tmax.x = positive infinity
|
||||
Determine how far we can travel along the ray before we hit a voxel boundary. */
|
||||
@ -97,22 +89,21 @@ void RayTracer_Step(struct RayTracer* t) {
|
||||
(i.e. which voxel boundary is nearest) and walk that way. */
|
||||
if (t->tMax.X < t->tMax.Y && t->tMax.X < t->tMax.Z) {
|
||||
/* tMax.X is the lowest, an YZ cell boundary plane is nearest. */
|
||||
t->X += t->step.X;
|
||||
t->pos.X += t->step.X;
|
||||
t->tMax.X += t->tDelta.X;
|
||||
} else if (t->tMax.Y < t->tMax.Z) {
|
||||
/* tMax.Y is the lowest, an XZ cell boundary plane is nearest. */
|
||||
t->Y += t->step.Y;
|
||||
t->pos.Y += t->step.Y;
|
||||
t->tMax.Y += t->tDelta.Y;
|
||||
} else {
|
||||
/* tMax.Z is the lowest, an XY cell boundary plane is nearest. */
|
||||
t->Z += t->step.Z;
|
||||
t->pos.Z += t->step.Z;
|
||||
t->tMax.Z += t->tDelta.Z;
|
||||
}
|
||||
}
|
||||
|
||||
static struct RayTracer tracer;
|
||||
#define PICKING_BORDER BLOCK_BEDROCK
|
||||
typedef cc_bool (*IntersectTest)(struct PickedPos* pos);
|
||||
typedef cc_bool (*IntersectTest)(struct RayTracer* t);
|
||||
|
||||
static BlockID Picking_GetInside(int x, int y, int z) {
|
||||
cc_bool sides;
|
||||
@ -150,7 +141,7 @@ static BlockID Picking_GetOutside(int x, int y, int z, IVec3 origin) {
|
||||
return BLOCK_AIR;
|
||||
}
|
||||
|
||||
static cc_bool RayTrace(const Vec3* origin, const Vec3* dir, float reach, struct PickedPos* pos, IntersectTest intersect) {
|
||||
static cc_bool RayTrace(struct RayTracer* t, const Vec3* origin, const Vec3* dir, float reach, IntersectTest intersect) {
|
||||
IVec3 pOrigin;
|
||||
cc_bool insideMap;
|
||||
float reachSq;
|
||||
@ -161,89 +152,88 @@ static cc_bool RayTrace(const Vec3* origin, const Vec3* dir, float reach, struct
|
||||
float dzMin, dzMax, dz;
|
||||
int i, x, y, z;
|
||||
|
||||
RayTracer_Init(&tracer, origin, dir);
|
||||
RayTracer_Init(t, origin, dir);
|
||||
IVec3_Floor(&pOrigin, origin);
|
||||
insideMap = World_Contains(pOrigin.X, pOrigin.Y, pOrigin.Z);
|
||||
reachSq = reach * reach;
|
||||
|
||||
for (i = 0; i < 25000; i++) {
|
||||
x = tracer.X; y = tracer.Y; z = tracer.Z;
|
||||
x = t->pos.X; y = t->pos.Y; z = t->pos.Z;
|
||||
v.X = (float)x; v.Y = (float)y; v.Z = (float)z;
|
||||
|
||||
tracer.Block = insideMap ? Picking_GetInside(x, y, z) : Picking_GetOutside(x, y, z, pOrigin);
|
||||
Vec3_Add(&minBB, &v, &Blocks.RenderMinBB[tracer.Block]);
|
||||
Vec3_Add(&maxBB, &v, &Blocks.RenderMaxBB[tracer.Block]);
|
||||
t->block = insideMap ? Picking_GetInside(x, y, z) : Picking_GetOutside(x, y, z, pOrigin);
|
||||
Vec3_Add(&t->Min, &v, &Blocks.RenderMinBB[t->block]);
|
||||
Vec3_Add(&t->Max, &v, &Blocks.RenderMaxBB[t->block]);
|
||||
|
||||
dxMin = Math_AbsF(origin->X - minBB.X); dxMax = Math_AbsF(origin->X - maxBB.X);
|
||||
dyMin = Math_AbsF(origin->Y - minBB.Y); dyMax = Math_AbsF(origin->Y - maxBB.Y);
|
||||
dzMin = Math_AbsF(origin->Z - minBB.Z); dzMax = Math_AbsF(origin->Z - maxBB.Z);
|
||||
dxMin = Math_AbsF(origin->X - t->Min.X); dxMax = Math_AbsF(origin->X - t->Max.X);
|
||||
dyMin = Math_AbsF(origin->Y - t->Min.Y); dyMax = Math_AbsF(origin->Y - t->Max.Y);
|
||||
dzMin = Math_AbsF(origin->Z - t->Min.Z); dzMax = Math_AbsF(origin->Z - t->Max.Z);
|
||||
dx = min(dxMin, dxMax); dy = min(dyMin, dyMax); dz = min(dzMin, dzMax);
|
||||
if (dx * dx + dy * dy + dz * dz > reachSq) return false;
|
||||
|
||||
tracer.Min = minBB; tracer.Max = maxBB;
|
||||
if (intersect(pos)) return true;
|
||||
RayTracer_Step(&tracer);
|
||||
if (intersect(t)) return true;
|
||||
RayTracer_Step(t);
|
||||
}
|
||||
|
||||
Logger_Abort("Something went wrong, did over 25,000 iterations in Picking_RayTrace()");
|
||||
return false;
|
||||
}
|
||||
|
||||
static cc_bool ClipBlock(struct PickedPos* pos) {
|
||||
Vec3 scaledDir, intersect;
|
||||
static cc_bool ClipBlock(struct RayTracer* t) {
|
||||
Vec3 scaledDir;
|
||||
float lenSq, reach;
|
||||
float t0, t1;
|
||||
|
||||
if (!Game_CanPick(tracer.Block)) return false;
|
||||
if (!Game_CanPick(t->block)) return false;
|
||||
/* This cell falls on the path of the ray. Now perform an additional AABB test,
|
||||
since some blocks do not occupy a whole cell. */
|
||||
if (!Intersection_RayIntersectsBox(tracer.Origin, tracer.Dir, tracer.Min, tracer.Max, &t0, &t1)) return false;
|
||||
if (!Intersection_RayIntersectsBox(t->origin, t->dir, t->Min, t->Max, &t0, &t1)) return false;
|
||||
|
||||
Vec3_Mul1(&scaledDir, &tracer.Dir, t0); /* scaledDir = dir * t0 */
|
||||
Vec3_Add(&intersect, &tracer.Origin, &scaledDir); /* intersect = origin + scaledDir */
|
||||
Vec3_Mul1(&scaledDir, &t->dir, t0); /* scaledDir = dir * t0 */
|
||||
Vec3_Add(&t->Intersect, &t->origin, &scaledDir); /* intersect = origin + scaledDir */
|
||||
|
||||
/* Only pick the block if the block is precisely within reach distance. */
|
||||
lenSq = Vec3_LengthSquared(&scaledDir);
|
||||
reach = LocalPlayer_Instance.ReachDistance;
|
||||
|
||||
if (lenSq <= reach * reach) {
|
||||
PickedPos_SetAsValid(pos, &tracer, &intersect);
|
||||
SetAsValid(t);
|
||||
} else {
|
||||
PickedPos_SetAsInvalid(pos);
|
||||
RayTracer_SetInvalid(t);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const static Vec3 picking_adjust = { 0.1f, 0.1f, 0.1f };
|
||||
static cc_bool ClipCamera(struct PickedPos* pos) {
|
||||
static cc_bool ClipCamera(struct RayTracer* t) {
|
||||
Vec3 intersect;
|
||||
float t0, t1;
|
||||
|
||||
if (Blocks.Draw[tracer.Block] == DRAW_GAS || Blocks.Collide[tracer.Block] != COLLIDE_SOLID) return false;
|
||||
if (!Intersection_RayIntersectsBox(tracer.Origin, tracer.Dir, tracer.Min, tracer.Max, &t0, &t1)) return false;
|
||||
if (Blocks.Draw[t->block] == DRAW_GAS || Blocks.Collide[t->block] != COLLIDE_SOLID) return false;
|
||||
if (!Intersection_RayIntersectsBox(t->origin, t->dir, t->Min, t->Max, &t0, &t1)) return false;
|
||||
|
||||
/* Need to collide with slightly outside block, to avoid camera clipping issues */
|
||||
Vec3_Sub(&tracer.Min, &tracer.Min, &picking_adjust);
|
||||
Vec3_Add(&tracer.Max, &tracer.Max, &picking_adjust);
|
||||
Intersection_RayIntersectsBox(tracer.Origin, tracer.Dir, tracer.Min, tracer.Max, &t0, &t1);
|
||||
Vec3_Sub(&t->Min, &t->Min, &picking_adjust);
|
||||
Vec3_Add(&t->Max, &t->Max, &picking_adjust);
|
||||
Intersection_RayIntersectsBox(t->origin, t->dir, t->Min, t->Max, &t0, &t1);
|
||||
|
||||
Vec3_Mul1(&intersect, &tracer.Dir, t0); /* intersect = dir * t0 */
|
||||
Vec3_Add(&intersect, &tracer.Origin, &intersect); /* intersect = origin + dir * t0 */
|
||||
PickedPos_SetAsValid(pos, &tracer, &intersect);
|
||||
Vec3_Mul1(&intersect, &t->dir, t0); /* intersect = dir * t0 */
|
||||
Vec3_Add(&t->Intersect, &t->origin, &intersect); /* intersect = origin + dir * t0 */
|
||||
SetAsValid(t);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Picking_CalcPickedBlock(const Vec3* origin, const Vec3* dir, float reach, struct PickedPos* pos) {
|
||||
if (!RayTrace(origin, dir, reach, pos, ClipBlock)) {
|
||||
PickedPos_SetAsInvalid(pos);
|
||||
void Picking_CalcPickedBlock(const Vec3* origin, const Vec3* dir, float reach, struct RayTracer* t) {
|
||||
if (!RayTrace(t, origin, dir, reach, ClipBlock)) {
|
||||
RayTracer_SetInvalid(t);
|
||||
}
|
||||
}
|
||||
|
||||
void Picking_ClipCameraPos(const Vec3* origin, const Vec3* dir, float reach, struct PickedPos* pos) {
|
||||
void Picking_ClipCameraPos(const Vec3* origin, const Vec3* dir, float reach, struct RayTracer* t) {
|
||||
cc_bool noClip = !Camera.Clipping || LocalPlayer_Instance.Hacks.Noclip;
|
||||
if (noClip || !RayTrace(origin, dir, reach, pos, ClipCamera)) {
|
||||
PickedPos_SetAsInvalid(pos);
|
||||
Vec3_Mul1(&pos->Intersect, dir, reach); /* intersect = dir * reach */
|
||||
Vec3_Add(&pos->Intersect, origin, &pos->Intersect); /* intersect = origin + dir * reach */
|
||||
if (noClip || !RayTrace(t, origin, dir, reach, ClipCamera)) {
|
||||
RayTracer_SetInvalid(t);
|
||||
Vec3_Mul1(&t->Intersect, dir, reach); /* intersect = dir * reach */
|
||||
Vec3_Add(&t->Intersect, origin, &t->Intersect); /* intersect = origin + dir * reach */
|
||||
}
|
||||
}
|
||||
|
@ -6,18 +6,6 @@
|
||||
Copyright 2014-2019 ClassiCube | Licensed under BSD-3
|
||||
*/
|
||||
|
||||
/* Describes the picked/selected block by the user and its position. */
|
||||
struct PickedPos {
|
||||
Vec3 Min; /* Minimum coords of the block's bounding box.*/
|
||||
Vec3 Max; /* Maximum coords of the block's bounding box. */
|
||||
Vec3 Intersect; /* Coords at which the ray intersected this block. */
|
||||
IVec3 BlockPos; /* Coords of the block */
|
||||
IVec3 TranslatedPos; /* Coords of the neighbouring block that is closest to the player */
|
||||
cc_bool Valid; /* Whether this instance actually has a selected block currently */
|
||||
Face Closest; /* Face of the picked block that is closet to the player */
|
||||
BlockID Block; /* Block ID of the picked block */
|
||||
};
|
||||
|
||||
/* Implements a voxel ray tracer
|
||||
http://www.xnawiki.com/index.php/Voxel_traversal
|
||||
https://web.archive.org/web/20120113051728/http://www.xnawiki.com/index.php?title=Voxel_traversal
|
||||
@ -28,22 +16,26 @@ http://www.cse.yorku.ca/~amana/research/grid.pdf
|
||||
http://www.devmaster.net/articles/raytracing_series/A%20faster%20voxel%20traversal%20algorithm%20for%20ray%20tracing.pdf
|
||||
*/
|
||||
struct RayTracer {
|
||||
int X, Y, Z;
|
||||
Vec3 Origin, Dir;
|
||||
Vec3 Min, Max; /* Block data */
|
||||
BlockID Block; /* Block data */
|
||||
IVec3 pos; /* Coordinates of block within world */
|
||||
Vec3 origin, dir;
|
||||
Vec3 Min, Max; /* Min/max coords of block's bounding box. */
|
||||
BlockID block;
|
||||
IVec3 step;
|
||||
Vec3 tMax, tDelta;
|
||||
/* Result only data */
|
||||
Vec3 Intersect; /* Coords at which the ray exactly intersected this block. */
|
||||
IVec3 TranslatedPos; /* Coords of the neighbouring block that is closest to the player */
|
||||
cc_bool Valid; /* Whether the ray tracer actually intersected with a block */
|
||||
Face Closest; /* Face of the intersected block that is closet to the player */
|
||||
};
|
||||
|
||||
void PickedPos_SetAsValid(struct PickedPos* pos, struct RayTracer* t, const Vec3* intersect);
|
||||
void PickedPos_SetAsInvalid(struct PickedPos* pos);
|
||||
void RayTracer_SetInvalid(struct RayTracer* t);
|
||||
void RayTracer_Init(struct RayTracer* t, const Vec3* origin, const Vec3* dir);
|
||||
void RayTracer_Step(struct RayTracer* t);
|
||||
|
||||
/* Determines the picked block based on the given origin and direction vector.
|
||||
Marks pickedPos as invalid if a block could not be found due to going outside map boundaries
|
||||
or not being able to find a suitable candiate within the given reach distance.*/
|
||||
void Picking_CalcPickedBlock(const Vec3* origin, const Vec3* dir, float reach, struct PickedPos* pos);
|
||||
void Picking_ClipCameraPos(const Vec3* origin, const Vec3* dir, float reach, struct PickedPos* pos);
|
||||
void Picking_CalcPickedBlock(const Vec3* origin, const Vec3* dir, float reach, struct RayTracer* t);
|
||||
void Picking_ClipCameraPos(const Vec3* origin, const Vec3* dir, float reach, struct RayTracer* t);
|
||||
#endif
|
||||
|
@ -738,7 +738,7 @@ static const char* cpe_clientExtensions[34] = {
|
||||
static void CPE_SetMapEnvUrl(cc_uint8* data);
|
||||
|
||||
#define Ext_Deg2Packed(x) ((int)((x) * 65536.0f / 360.0f))
|
||||
void CPE_SendPlayerClick(int button, cc_bool pressed, cc_uint8 targetId, struct PickedPos* pos) {
|
||||
void CPE_SendPlayerClick(int button, cc_bool pressed, cc_uint8 targetId, struct RayTracer* t) {
|
||||
struct Entity* p = &LocalPlayer_Instance.Base;
|
||||
cc_uint8 data[15];
|
||||
|
||||
@ -750,13 +750,13 @@ void CPE_SendPlayerClick(int button, cc_bool pressed, cc_uint8 targetId, struct
|
||||
Stream_SetU16_BE(&data[5], Ext_Deg2Packed(p->Pitch));
|
||||
|
||||
data[7] = targetId;
|
||||
Stream_SetU16_BE(&data[8], pos->BlockPos.X);
|
||||
Stream_SetU16_BE(&data[10], pos->BlockPos.Y);
|
||||
Stream_SetU16_BE(&data[12], pos->BlockPos.Z);
|
||||
Stream_SetU16_BE(&data[8], t->pos.X);
|
||||
Stream_SetU16_BE(&data[10], t->pos.Y);
|
||||
Stream_SetU16_BE(&data[12], t->pos.Z);
|
||||
|
||||
data[14] = 255;
|
||||
/* Our own face values differ from CPE block face */
|
||||
switch (pos->Closest) {
|
||||
switch (t->Closest) {
|
||||
case FACE_XMAX: data[14] = 0; break;
|
||||
case FACE_XMIN: data[14] = 1; break;
|
||||
case FACE_YMAX: data[14] = 2; break;
|
||||
|
@ -46,7 +46,7 @@ extern cc_uint16 Net_PacketSizes[OPCODE_COUNT];
|
||||
extern Net_Handler Net_Handlers[OPCODE_COUNT];
|
||||
#define Net_Set(opcode, handler, size) Net_Handlers[opcode] = handler; Net_PacketSizes[opcode] = size;
|
||||
|
||||
struct PickedPos;
|
||||
struct RayTracer;
|
||||
void Protocol_RemoveEntity(EntityID id);
|
||||
void Protocol_Reset(void);
|
||||
void Protocol_Tick(void);
|
||||
@ -56,5 +56,5 @@ void Classic_SendChat(const String* text, cc_bool partial);
|
||||
void Classic_WritePosition(Vec3 pos, float yaw, float pitch);
|
||||
void Classic_WriteSetBlock(int x, int y, int z, cc_bool place, BlockID block);
|
||||
void Classic_SendLogin(const String* username, const String* verKey);
|
||||
void CPE_SendPlayerClick(int button, cc_bool pressed, cc_uint8 targetId, struct PickedPos* pos);
|
||||
void CPE_SendPlayerClick(int button, cc_bool pressed, cc_uint8 targetId, struct RayTracer* t);
|
||||
#endif
|
||||
|
@ -6,7 +6,7 @@
|
||||
Copyright 2014-2019 ClassiCube | Licensed under BSD-3
|
||||
*/
|
||||
|
||||
struct PickedPos;
|
||||
struct RayTracer;
|
||||
struct Stream;
|
||||
struct IGameComponent;
|
||||
struct ScheduledTask;
|
||||
|
Loading…
x
Reference in New Issue
Block a user