169
src/LunarWM.c
169
src/LunarWM.c
@@ -2139,56 +2139,101 @@ static void DrawBillboardNoShear(
|
||||
DrawBillboardPro(cam, tex, src, pos, cam.up, size, origin, 0.0f, tint);
|
||||
}
|
||||
|
||||
// pass yFlip from tl->attribs.invert_y
|
||||
static void DrawTexture3D(
|
||||
Texture2D tex, Vector3 position, Vector3 target, float scale, bool y_flip)
|
||||
void DrawTextureCyl(
|
||||
Texture2D tex, Vector3 center, float radius, float scale, bool y_flip)
|
||||
{
|
||||
if (!tex.id)
|
||||
if (!tex.id || scale <= 0.0f || radius == 0.0f)
|
||||
return;
|
||||
|
||||
Vector3 fwd = Vector3Normalize(Vector3Subtract(target, position));
|
||||
Vector3 up_ref = (fabsf(fwd.y) > 0.99f) ? (Vector3) { 0, 0, 1 }
|
||||
: (Vector3) { 0, 1, 0 };
|
||||
Vector3 right = Vector3Normalize(Vector3CrossProduct(fwd, up_ref));
|
||||
Vector3 up = Vector3CrossProduct(right, fwd);
|
||||
|
||||
float half_w = 0.5f * (float)tex.width * scale;
|
||||
float r = fabsf(radius);
|
||||
float arc_len = (float)tex.width * scale; // arc length in world units
|
||||
float theta = arc_len / r; // radians across the panel
|
||||
float half_t = 0.5f * theta;
|
||||
float half_h = 0.5f * (float)tex.height * scale;
|
||||
|
||||
Vector3 tl
|
||||
= Vector3Add(Vector3Subtract(position, Vector3Scale(right, half_w)),
|
||||
Vector3Scale(up, half_h));
|
||||
Vector3 tr = Vector3Add(Vector3Add(position, Vector3Scale(right, half_w)),
|
||||
Vector3Scale(up, half_h));
|
||||
Vector3 br
|
||||
= Vector3Subtract(Vector3Add(position, Vector3Scale(right, half_w)),
|
||||
Vector3Scale(up, half_h));
|
||||
Vector3 bl = Vector3Subtract(
|
||||
Vector3Subtract(position, Vector3Scale(right, half_w)),
|
||||
Vector3Scale(up, half_h));
|
||||
// mid-angle around Y so the segment's middle sits at 'center'
|
||||
float a0 = atan2f(center.x, center.z);
|
||||
|
||||
// shift so the cylinder surface midpoint matches 'center'
|
||||
Vector3 mid_ref = (Vector3) { sinf(a0) * r, center.y, cosf(a0) * r };
|
||||
Vector3 delta = Vector3Subtract(center, mid_ref);
|
||||
|
||||
// tessellation: about 3° per slice (min 8)
|
||||
int slices = (int)ceilf(fmaxf(theta * (180.0f / PI) / 3.0f, 8.0f));
|
||||
if (slices > 1024)
|
||||
slices = 1024;
|
||||
|
||||
float vt = y_flip ? 1.0f : 0.0f;
|
||||
float vb = y_flip ? 0.0f : 1.0f;
|
||||
|
||||
rlDisableBackfaceCulling(); // ensure visible regardless of winding
|
||||
rlDrawRenderBatchActive(); // flush any prior state
|
||||
rlSetTexture(tex.id);
|
||||
rlDisableBackfaceCulling();
|
||||
rlColor4ub(255, 255, 255, 255);
|
||||
rlBegin(RL_QUADS);
|
||||
rlNormal3f(fwd.x, fwd.y, fwd.z);
|
||||
|
||||
// TL, TR, BR, BL with canonical UVs
|
||||
rlTexCoord2f(1.0f, vt);
|
||||
rlVertex3f(tl.x, tl.y, tl.z);
|
||||
rlTexCoord2f(0.0f, vt);
|
||||
rlVertex3f(tr.x, tr.y, tr.z);
|
||||
rlTexCoord2f(0.0f, vb);
|
||||
rlVertex3f(br.x, br.y, br.z);
|
||||
rlTexCoord2f(1.0f, vb);
|
||||
rlVertex3f(bl.x, bl.y, bl.z);
|
||||
for (int i = 0; i < slices; ++i) {
|
||||
float u0 = (float)i / (float)slices;
|
||||
float u1 = (float)(i + 1) / (float)slices;
|
||||
|
||||
float aL = a0 - half_t + theta * u0;
|
||||
float aR = a0 - half_t + theta * u1;
|
||||
|
||||
Vector3 nL = (Vector3) { sinf(aL), 0.0f, cosf(aL) };
|
||||
Vector3 nR = (Vector3) { sinf(aR), 0.0f, cosf(aR) };
|
||||
if (radius < 0.0f) {
|
||||
nL = Vector3Negate(nL);
|
||||
nR = Vector3Negate(nR);
|
||||
}
|
||||
|
||||
Vector3 pLT = Vector3Add(
|
||||
(Vector3) { nL.x * r, center.y + half_h, nL.z * r }, delta);
|
||||
Vector3 pLB = Vector3Add(
|
||||
(Vector3) { nL.x * r, center.y - half_h, nL.z * r }, delta);
|
||||
Vector3 pRT = Vector3Add(
|
||||
(Vector3) { nR.x * r, center.y + half_h, nR.z * r }, delta);
|
||||
Vector3 pRB = Vector3Add(
|
||||
(Vector3) { nR.x * r, center.y - half_h, nR.z * r }, delta);
|
||||
|
||||
// match your flat-quad U flip (so WL textures look correct)
|
||||
float U0 = 1.0f - u0;
|
||||
float U1 = 1.0f - u1;
|
||||
|
||||
// one normal per-vertex (simple cylindrical)
|
||||
rlNormal3f(nL.x, nL.y, nL.z);
|
||||
rlTexCoord2f(U0, vt);
|
||||
rlVertex3f(pLT.x, pLT.y, pLT.z);
|
||||
rlNormal3f(nR.x, nR.y, nR.z);
|
||||
rlTexCoord2f(U1, vt);
|
||||
rlVertex3f(pRT.x, pRT.y, pRT.z);
|
||||
rlNormal3f(nR.x, nR.y, nR.z);
|
||||
rlTexCoord2f(U1, vb);
|
||||
rlVertex3f(pRB.x, pRB.y, pRB.z);
|
||||
rlNormal3f(nL.x, nL.y, nL.z);
|
||||
rlTexCoord2f(U0, vb);
|
||||
rlVertex3f(pLB.x, pLB.y, pLB.z);
|
||||
}
|
||||
|
||||
rlEnd();
|
||||
rlSetTexture(0);
|
||||
rlEnableBackfaceCulling();
|
||||
}
|
||||
|
||||
static inline Vector3 RecenterPoint(LunarWM *wm, Vector3 p)
|
||||
{
|
||||
if (!wm->xr.recenter_active)
|
||||
return p;
|
||||
return Vector3Add(Vector3RotateByQuaternion(p, wm->xr.recenter_rot),
|
||||
wm->xr.recenter_trans);
|
||||
}
|
||||
|
||||
static inline Quaternion RecenterOrient(LunarWM *wm, Quaternion q)
|
||||
{
|
||||
if (!wm->xr.recenter_active)
|
||||
return q;
|
||||
return QuaternionMultiply(wm->xr.recenter_rot, q);
|
||||
}
|
||||
|
||||
void render_hud(LunarWM *this, float /*dt*/, int hud_size)
|
||||
{
|
||||
ClearBackground((Color) { 0, 0, 0, 0 });
|
||||
@@ -2220,33 +2265,30 @@ void render_hud(LunarWM *this, float /*dt*/, int hud_size)
|
||||
|
||||
void render_3d(LunarWM *this, float /*dt*/)
|
||||
{
|
||||
Skybox_draw(this->renderer.skybox, Vector3Zero());
|
||||
Skybox_draw(this->renderer.skybox, this->renderer.camera.position);
|
||||
|
||||
// rlDisableBackfaceCulling();
|
||||
for (size_t i = 0; i < vector_size(this->wayland.v_toplevels); i++) {
|
||||
auto *tl = this->wayland.v_toplevels[i];
|
||||
|
||||
if (!tl || !tl->surface)
|
||||
continue;
|
||||
|
||||
// if (!LunarWM_Toplevel_update(tl))
|
||||
// continue;
|
||||
auto const rad = this->cman->cfg.space.radius - 0.01 * (float)i;
|
||||
|
||||
DrawTexture3D(tl->rl_texture,
|
||||
(Vector3) { 0, 0, this->cman->cfg.space.radius - 0.01 * (float)i },
|
||||
Vector3Zero(), this->cman->cfg.space.window_scale, false);
|
||||
DrawTextureCyl(tl->rl_texture, (Vector3) { 0, 0, rad }, rad,
|
||||
this->cman->cfg.space.window_scale, false);
|
||||
}
|
||||
// rlEnableBackfaceCulling();
|
||||
|
||||
for (int h = 0; h < 2; ++h) {
|
||||
auto *hand_info = &this->xr.hands[h];
|
||||
for (size_t k = 0; k < XR_HAND_JOINT_COUNT_EXT; ++k) {
|
||||
auto const *jl = &hand_info->joint_locations[k];
|
||||
Vector3 const pos = {
|
||||
Vector3 pos = {
|
||||
jl->pose.position.x,
|
||||
jl->pose.position.y,
|
||||
jl->pose.position.z,
|
||||
};
|
||||
pos = RecenterPoint(this, pos);
|
||||
DrawSphere(pos, jl->radius, (Color) { 255, 0, 0, 255 });
|
||||
}
|
||||
}
|
||||
@@ -2274,21 +2316,6 @@ void render_3d(LunarWM *this, float /*dt*/)
|
||||
}
|
||||
}
|
||||
|
||||
static inline Vector3 RecenterPoint(LunarWM *wm, Vector3 p)
|
||||
{
|
||||
if (!wm->xr.recenter_active)
|
||||
return p;
|
||||
return Vector3Add(Vector3RotateByQuaternion(p, wm->xr.recenter_rot),
|
||||
wm->xr.recenter_trans);
|
||||
}
|
||||
|
||||
static inline Quaternion RecenterOrient(LunarWM *wm, Quaternion q)
|
||||
{
|
||||
if (!wm->xr.recenter_active)
|
||||
return q;
|
||||
return QuaternionMultiply(wm->xr.recenter_rot, q);
|
||||
}
|
||||
|
||||
static bool render_layer(LunarWM *this, LunarWM_RenderLayerInfo *info, float dt)
|
||||
{
|
||||
auto const view_count = (uint32_t)this->xr.view_configuration_views_count;
|
||||
@@ -2448,6 +2475,7 @@ static bool render_layer(LunarWM *this, LunarWM_RenderLayerInfo *info, float dt)
|
||||
|
||||
BeginMode3D(this->renderer.camera);
|
||||
{
|
||||
ClearBackground(RED);
|
||||
render_3d(this, dt);
|
||||
}
|
||||
EndMode3D();
|
||||
@@ -2641,33 +2669,6 @@ void LunarWM_run(LunarWM *this)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (int h = 0; h < 2; h++) {
|
||||
auto *hand_info = &this->xr.hands[h];
|
||||
for (size_t k = 0; k < XR_HAND_JOINT_COUNT_EXT; ++k) {
|
||||
auto *jl = &hand_info->joint_locations[k];
|
||||
|
||||
Vector3 pos = { jl->pose.position.x, jl->pose.position.y,
|
||||
jl->pose.position.z };
|
||||
pos = RecenterPoint(this, pos);
|
||||
|
||||
Quaternion q
|
||||
= { jl->pose.orientation.x, jl->pose.orientation.y,
|
||||
jl->pose.orientation.z, jl->pose.orientation.w };
|
||||
q = RecenterOrient(this, q);
|
||||
|
||||
jl->pose.position.x = pos.x;
|
||||
jl->pose.position.y = pos.y;
|
||||
jl->pose.position.z = pos.z;
|
||||
|
||||
jl->pose.orientation.x = q.x;
|
||||
jl->pose.orientation.y = q.y;
|
||||
jl->pose.orientation.z = q.z;
|
||||
jl->pose.orientation.w = q.w;
|
||||
|
||||
DrawSphere(pos, jl->radius, (Color) { 255, 0, 0, 255 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LunarWM_RenderLayerInfo render_layer_info = {
|
||||
|
||||
@@ -95,16 +95,14 @@ void Skybox_draw(Skybox const skybox, Vector3 position)
|
||||
if (!skybox.ok)
|
||||
return;
|
||||
|
||||
// Render behind everything without writing depth; cull disabled so we see
|
||||
// inside faces
|
||||
rlDisableBackfaceCulling();
|
||||
rlDisableDepthMask();
|
||||
rlDisableDepthTest();
|
||||
rlDisableColorBlend();
|
||||
|
||||
DrawModel(skybox.cube, position, 500.0f, (Color) { 255, 255, 255, 255 });
|
||||
DrawModel(skybox.cube, position, 5.0f, (Color) { 255, 255, 255, 255 });
|
||||
rlDrawRenderBatchActive();
|
||||
|
||||
rlEnableColorBlend();
|
||||
rlEnableDepthMask();
|
||||
rlEnableDepthTest();
|
||||
rlEnableBackfaceCulling();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user