1
0
Fork 0
mirror of https://git.coom.tech/drummyfish/small3dlib.git synced 2024-11-21 20:39:57 +01:00

Fix near culling

This commit is contained in:
Miloslav Číž 2019-06-02 13:13:33 +02:00
parent 8c00c5d7fd
commit 246cb2a8cc
2 changed files with 21 additions and 15 deletions

View file

@ -260,7 +260,13 @@ typedef uint16_t S3L_Index;
#ifndef S3L_NEAR #ifndef S3L_NEAR
#define S3L_NEAR (S3L_FRACTIONS_PER_UNIT / 4) /**< Distance of the near #define S3L_NEAR (S3L_FRACTIONS_PER_UNIT / 4) /**< Distance of the near
clipping plane. */ clipping plane. Points in front or EXATLY ON
this plane are considered outside the
frustum. This must be >= 0. */
#endif
#if S3L_NEAR <= 0
#define S3L_NEAR 1 // Can't be <= 0.
#endif #endif
#ifndef S3L_FAST_LERP_QUALITY #ifndef S3L_FAST_LERP_QUALITY
@ -1722,20 +1728,14 @@ void S3L_makeCameraMatrix(S3L_Transform3D cameraTransform, S3L_Mat4 *m)
S3L_mat4Xmat4(m,&r); S3L_mat4Xmat4(m,&r);
} }
/**
Performs perspecive division (z-divide). Does NOT check for division by zero.
*/
static inline void S3L_perspectiveDivide(S3L_Vec4 *vector, static inline void S3L_perspectiveDivide(S3L_Vec4 *vector,
S3L_Unit focalLength) S3L_Unit focalLength)
{ {
S3L_Unit divisor = vector->z > 0 ? vector->z : (-1 * (vector->z - 1)); vector->x = (vector->x * focalLength) / vector->z;
/* ^ This has two purposes: vector->y = (vector->y * focalLength) / vector->z;
1. Prevent division by zero.
2. Prevent a "rapid flip" of the vertex, e.g.: having a vertex
[100,0,0.1] z-divides it to [1000,0], but when it shift a short
distance to [100,0,-0.1], it z-divides to [-1000,0], rapidly flipping
from right to the left. */
vector->x = (vector->x * focalLength) / divisor;
vector->y = (vector->y * focalLength) / divisor;
} }
/** /**
@ -1756,7 +1756,7 @@ static inline int8_t S3L_triangleIsVisible(
if ( // outside frustum? if ( // outside frustum?
#if S3L_STRICT_NEAR_CULLING #if S3L_STRICT_NEAR_CULLING
p0.z < S3L_NEAR || p1.z < S3L_NEAR || p2.z < S3L_NEAR || p0.z <= S3L_NEAR || p1.z <= S3L_NEAR || p2.z <= S3L_NEAR ||
// ^ partially in front of NEAR? // ^ partially in front of NEAR?
#else #else
clipTest(z,<=,S3L_NEAR) || // completely in front of NEAR? clipTest(z,<=,S3L_NEAR) || // completely in front of NEAR?
@ -1812,6 +1812,12 @@ void _S3L_projectVertex(
S3L_vec3Xmat4(result,projectionMatrix); S3L_vec3Xmat4(result,projectionMatrix);
result->z = result->z >= S3L_NEAR ? result->z : S3L_NEAR;
/* ^ This firstly prevents zero division in the follwoing z-divide and
secondly "pushes" vertices that are in front of near a little bit forward,
which makes the behave a bit better. If all three vertices end up exactly
on NEAR, the triangle will be culled. */
S3L_perspectiveDivide(result,focalLength); S3L_perspectiveDivide(result,focalLength);
} }

View file

@ -11,7 +11,7 @@
//#define S3L_PRESET_HIGHEST_QUALITY //#define S3L_PRESET_HIGHEST_QUALITY
#define S3L_FLAT 0 #define S3L_FLAT 0
#define S3L_STRICT_NEAR_CULLING 1 #define S3L_STRICT_NEAR_CULLING 0
#define S3L_PERSPECTIVE_CORRECTION 1 #define S3L_PERSPECTIVE_CORRECTION 1
#define S3L_SORT 0 #define S3L_SORT 0
#define S3L_Z_BUFFER 1 #define S3L_Z_BUFFER 1