mirror of
https://git.coom.tech/drummyfish/small3dlib.git
synced 2024-11-20 20:29:58 +01:00
Add screen projection function
This commit is contained in:
parent
a89f3c192f
commit
4ed5e5fd84
3 changed files with 82 additions and 11 deletions
|
@ -29,6 +29,8 @@
|
|||
S3L_Model3D models[3];
|
||||
S3L_Scene scene;
|
||||
|
||||
S3L_Vec4 teleportPoint;
|
||||
|
||||
uint32_t pixels[S3L_RESOLUTION_X * S3L_RESOLUTION_Y];
|
||||
|
||||
uint32_t frame = 0;
|
||||
|
@ -80,6 +82,20 @@ void sampleTxture(S3L_Unit u, S3L_Unit v, uint8_t *r, uint8_t *g, uint8_t *b)
|
|||
*b = texture[index];
|
||||
}
|
||||
|
||||
void drawTeleport(int16_t x, int16_t y, S3L_ScreenCoord size)
|
||||
{
|
||||
int16_t halfSize = size / 2;
|
||||
|
||||
S3L_ScreenCoord x0 = S3L_max(0,x - halfSize);
|
||||
S3L_ScreenCoord x1 = S3L_min(S3L_RESOLUTION_X - 1,x + halfSize);
|
||||
S3L_ScreenCoord y0 = S3L_max(0,y - halfSize);
|
||||
S3L_ScreenCoord y1 = S3L_min(S3L_RESOLUTION_Y - 1,y + halfSize);
|
||||
|
||||
for (S3L_ScreenCoord j = y0; j < y1; ++j)
|
||||
for (S3L_ScreenCoord i = x0; i < x1; ++i)
|
||||
setPixel(i,j,255,0,0);
|
||||
}
|
||||
|
||||
void drawPixel(S3L_PixelInfo *p)
|
||||
{
|
||||
if (p->triangleID != previousTriangle)
|
||||
|
@ -142,6 +158,13 @@ void draw()
|
|||
|
||||
S3L_drawScene(scene);
|
||||
|
||||
S3L_Vec4 screenPoint;
|
||||
|
||||
project3DPointToScreen(teleportPoint,scene.camera,&screenPoint);
|
||||
|
||||
if (screenPoint.z < S3L_zBufferRead(screenPoint.x,screenPoint.y))
|
||||
drawTeleport(screenPoint.x,screenPoint.y,screenPoint.w);
|
||||
|
||||
clock_t nowT = clock();
|
||||
|
||||
double timeDiff = ((double) (nowT - nextT)) / CLOCKS_PER_SEC;
|
||||
|
@ -167,6 +190,11 @@ int main()
|
|||
SDL_Surface *screenSurface = SDL_GetWindowSurface(window);
|
||||
SDL_Event event;
|
||||
|
||||
teleportPoint.x = 6 * S3L_FRACTIONS_PER_UNIT;
|
||||
teleportPoint.y = -3 * S3L_FRACTIONS_PER_UNIT;
|
||||
teleportPoint.z = 2 * S3L_FRACTIONS_PER_UNIT;
|
||||
teleportPoint.w = S3L_FRACTIONS_PER_UNIT;
|
||||
|
||||
nextT = clock();
|
||||
|
||||
S3L_initCamera(&scene.camera);
|
||||
|
|
63
small3dlib.h
63
small3dlib.h
|
@ -512,6 +512,15 @@ static inline S3L_Unit S3L_cos(S3L_Unit x);
|
|||
S3L_Unit S3L_vec3Length(S3L_Vec4 v);
|
||||
S3L_Unit S3L_sqrt(S3L_Unit value);
|
||||
|
||||
/** Projects a single point from 3D space to the screen space (pixels), which
|
||||
can be useful e.g. for drawing sprites. The w component of input and result
|
||||
holds the point size. If this size is 0 in the result, the sprite is outside
|
||||
the view. */
|
||||
void project3DPointToScreen(
|
||||
S3L_Vec4 point,
|
||||
S3L_Camera camera,
|
||||
S3L_Vec4 *result);
|
||||
|
||||
/** Computes a normalized normal of given triangle. */
|
||||
void S3L_triangleNormal(S3L_Vec4 t0, S3L_Vec4 t1, S3L_Vec4 t2,
|
||||
S3L_Vec4 *n);
|
||||
|
@ -1419,6 +1428,50 @@ void S3L_initTransoform3D(S3L_Transform3D *t)
|
|||
t->scale.w = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Performs perspecive division (z-divide). Does NOT check for division by zero.
|
||||
*/
|
||||
static inline void S3L_perspectiveDivide(S3L_Vec4 *vector,
|
||||
S3L_Unit focalLength)
|
||||
{
|
||||
vector->x = (vector->x * focalLength) / vector->z;
|
||||
vector->y = (vector->y * focalLength) / vector->z;
|
||||
}
|
||||
|
||||
void project3DPointToScreen(
|
||||
S3L_Vec4 point,
|
||||
S3L_Camera camera,
|
||||
S3L_Vec4 *result)
|
||||
{
|
||||
S3L_Mat4 m;
|
||||
S3L_makeCameraMatrix(camera.transform,&m);
|
||||
|
||||
S3L_Unit s = point.w;
|
||||
|
||||
point.w = S3L_FRACTIONS_PER_UNIT;
|
||||
|
||||
S3L_vec3Xmat4(&point,&m);
|
||||
|
||||
point.z = S3L_nonZero(point.z);
|
||||
|
||||
S3L_perspectiveDivide(&point,camera.focalLength);
|
||||
|
||||
S3L_ScreenCoord x, y;
|
||||
|
||||
S3L_mapProjectionPlaneToScreen(point,&x,&y);
|
||||
|
||||
result->x = x;
|
||||
result->y = y;
|
||||
result->z = point.z;
|
||||
|
||||
result->w =
|
||||
(point.z < 0) ? 0 :
|
||||
(
|
||||
(s * camera.focalLength * S3L_RESOLUTION_X) /
|
||||
(point.z * S3L_FRACTIONS_PER_UNIT)
|
||||
);
|
||||
}
|
||||
|
||||
void S3L_lookAt(S3L_Vec4 pointTo, S3L_Transform3D *t)
|
||||
{
|
||||
S3L_Vec4 v;
|
||||
|
@ -2296,16 +2349,6 @@ void S3L_makeCameraMatrix(S3L_Transform3D cameraTransform, S3L_Mat4 *m)
|
|||
S3L_mat4Xmat4(m,&r);
|
||||
}
|
||||
|
||||
/**
|
||||
Performs perspecive division (z-divide). Does NOT check for division by zero.
|
||||
*/
|
||||
static inline void S3L_perspectiveDivide(S3L_Vec4 *vector,
|
||||
S3L_Unit focalLength)
|
||||
{
|
||||
vector->x = (vector->x * focalLength) / vector->z;
|
||||
vector->y = (vector->y * focalLength) / vector->z;
|
||||
}
|
||||
|
||||
int8_t S3L_triangleWinding(
|
||||
S3L_ScreenCoord x0,
|
||||
S3L_ScreenCoord y0,
|
||||
|
|
2
todo.txt
2
todo.txt
|
@ -16,7 +16,7 @@ features:
|
|||
- function to set/clear stencil buffer -- can be useful
|
||||
|
||||
- function to map one point in 3D space to screen, along with size (for mapping
|
||||
billboards/sprites etc.)
|
||||
billboards/sprites etc.) DONE
|
||||
|
||||
- Optimize persp. correction!
|
||||
|
||||
|
|
Loading…
Reference in a new issue