1
0
Fork 0
mirror of https://git.coom.tech/drummyfish/small3dlib.git synced 2024-12-22 01:26:17 +01:00

Replace drawModel with drawScene

This commit is contained in:
Miloslav Číž 2019-05-21 21:28:16 +02:00
parent ae985635fd
commit c11cc70238
2 changed files with 158 additions and 81 deletions

168
s3l.h
View file

@ -125,6 +125,38 @@
on. */
#endif
#ifndef S3L_RENDER_STRATEGY
#define S3L_RENDER_STRATEGY S3L_STRATEGY_Z_BUFFER /**< Strategy used for
visibility
determination -- see
S3L_STRATEGY_*
consts. */
#endif
#define S3L_STRATEGY_NONE 0 /**< No strategy -- can be sufficient in
some cases. */
#define S3L_STRATEGY_Z_BUFFER 1 /**< Use z-buffer (depth buffer).
Accurate and fast, but requires a lot
of memory. */
#define S3L_STRATEGY_BACK_TO_FRONT 2 /**< Sort and draw triangles from back to
front (painter's algorithm). Requires
less memory, but can be slower than
Z-buffer and can't handle
intersecting triangles. */
#define S3L_STRATEGY_FRONT_TO_BACK 3 /**< Sort and draw triangles from front to
back (reverse painter's algorithm).
Requires a bit more memory than back
to front, but can also be faster
(doesn't draw over already drawn
pixels). */
#ifndef S3L_MAX_TRIANGES_DRAWN
#define S3L_MAX_TRIANGES_DRAWN 128 /**< Maximum number of triangles that can
be drawn in sorted modes. This
affects the size of a cache used for
triangle sorting. */
#endif
#ifndef S3L_PERSPECTIVE_CORRECTION
#define S3L_PERSPECTIVE_CORRECTION 0 /**< Specifies what type of perspective
correction (PC) to use. Remember
@ -198,6 +230,8 @@ typedef uint16_t S3L_Index;
/* 7 back, top, left */\
-S3L_FRACTIONS_PER_UNIT/2,S3L_FRACTIONS_PER_UNIT/2,S3L_FRACTIONS_PER_UNIT/2
#define S3L_CUBE_VERTEX_COUNT 8
/** Predefined triangle indices of a cube, to be used with S3L_CUBE_VERTICES
and S3L_CUBE_TEXCOORDS. */
#define S3L_CUBE_TRIANGLES\
@ -214,6 +248,8 @@ typedef uint16_t S3L_Index;
4, 1, 0, /* bottom */\
4, 5, 1
#define S3L_CUBE_TRIANGLE_COUNT 12
/** Predefined texture coordinates of a cube, corresponding to triangles (NOT
vertices), to be used with S3L_CUBE_VERTICES and S3L_CUBE_TRIANGLES. */
#define S3L_CUBE_TEXCOORDS(m)\
@ -332,12 +368,37 @@ void S3L_mat4Xmat4(S3L_Mat4 *m1, S3L_Mat4 *m2);
typedef struct
{
S3L_Unit focalLength; ///< Defines the field of view (FOV).
S3L_Unit focalLength; ///< Defines the field of view (FOV).
S3L_Transform3D transform;
} S3L_Camera;
static inline void S3L_initCamera(S3L_Camera *c);
typedef struct
{
uint8_t backfaceCulling;
uint8_t mode;
} S3L_DrawConfig;
void S3L_initDrawConfig(S3L_DrawConfig *config);
typedef struct
{
S3L_Unit *vertices;
S3L_Index vertexCount;
S3L_Index *triangles;
S3L_Index triangleCount;
S3L_Transform3D transform;
S3L_DrawConfig config;
} S3L_Model3D; ///< Represents a 3D model.
typedef struct
{
S3L_Model3D *models;
S3L_Index modelCount;
S3L_Camera camera;
} S3L_Scene; ///< Represent the 3D scene to be rendered.
typedef struct
{
S3L_ScreenCoord x; ///< Screen X coordinate.
@ -351,7 +412,8 @@ typedef struct
S3L_FRACTIONS_PER_UNIT. */
S3L_Unit barycentric1; ///< Baryc. coord 1 (corresponds to 2nd vertex).
S3L_Unit barycentric2; ///< Baryc. coord 2 (corresponds to 3rd vertex).
S3L_Index triangleID;
S3L_Index triangleID; ///< Triangle index.
S3L_Index modelID;
S3L_Unit depth; ///< Depth (only if depth is turned on).
} S3L_PixelInfo; /**< Used to pass the info about a rasterized pixel
(fragment) to the user-defined drawing func. */
@ -366,14 +428,6 @@ static inline void S3L_initPixelInfo(S3L_PixelInfo *p);
#define S3L_MODE_LINES 1
#define S3L_MODE_POINTS 2
typedef struct
{
uint8_t backfaceCulling;
uint8_t mode;
} S3L_DrawConfig;
void S3L_initDrawConfig(S3L_DrawConfig *config);
// general helper functions
static inline S3L_Unit S3L_abs(S3L_Unit value);
static inline S3L_Unit S3L_min(S3L_Unit v1, S3L_Unit v2);
@ -1653,57 +1707,61 @@ static inline void S3L_perspectiveDivide(S3L_Vec4 *vector,
vector->y = (vector->y * focalLength) / divisor;
}
void S3L_drawModelIndexed(
const S3L_Unit coords[],
const S3L_Index triangleVertexIndices[],
uint16_t triangleCount,
S3L_Transform3D modelTransform,
const S3L_Camera *camera,
const S3L_DrawConfig *config)
void S3L_drawScene(S3L_Scene scene)
{
S3L_Index triangleIndex = 0;
S3L_Index coordIndex = 0;
S3L_Vec4 pointModel, transformed0, transformed1, transformed2;
S3L_Unit indexIndex = 0;
pointModel.w = S3L_FRACTIONS_PER_UNIT; // has to be "1.0" for translation
S3L_Mat4 mat1, mat2;
S3L_makeWorldMatrix(modelTransform,&mat1);
S3L_makeCameraMatrix(camera->transform,&mat2);
S3L_mat4Xmat4(&mat1,&mat2);
while (triangleIndex < triangleCount)
for (S3L_Index modelIndex; modelIndex < scene.modelCount; ++modelIndex)
{
#define project(n)\
indexIndex = triangleVertexIndices[coordIndex] * 3;\
pointModel.x = coords[indexIndex];\
++indexIndex; /* TODO: put into square brackets? */\
pointModel.y = coords[indexIndex];\
++indexIndex;\
pointModel.z = coords[indexIndex];\
++coordIndex;\
S3L_vec3Xmat4(&pointModel,&mat1);\
transformed##n.x = pointModel.x;\
transformed##n.y = pointModel.y;\
transformed##n.z = pointModel.z;\
transformed##n.w = S3L_FRACTIONS_PER_UNIT;\
S3L_perspectiveDivide(&transformed##n,camera->focalLength);
S3L_Unit *vertices = scene.models[modelIndex].vertices;
S3L_Index *triangles = scene.models[modelIndex].triangles;
S3L_Index triangleIndex = 0;
S3L_Index coordIndex = 0;
/* TODO: maybe create an option that would use a cache here to not
transform the same point twice? */
S3L_Vec4 pointModel, transformed0, transformed1, transformed2;
S3L_Unit indexIndex = 0;
project(0)
project(1)
project(2)
pointModel.w = S3L_FRACTIONS_PER_UNIT; // has to be "1.0" for translation
S3L_drawTriangle(transformed0,transformed1,transformed2,config,camera,
triangleIndex);
S3L_Mat4 mat1, mat2;
++triangleIndex;
S3L_makeWorldMatrix(scene.models[modelIndex].transform,&mat1);
S3L_makeCameraMatrix(scene.camera.transform,&mat2);
S3L_mat4Xmat4(&mat1,&mat2);
S3L_Index triangleCount = scene.models[modelIndex].triangleCount;
while (triangleIndex < triangleCount)
{
#define project(n)\
indexIndex = triangles[coordIndex] * 3;\
pointModel.x = vertices[indexIndex];\
++indexIndex; /* TODO: put into square brackets? */\
pointModel.y = vertices[indexIndex];\
++indexIndex;\
pointModel.z = vertices[indexIndex];\
++coordIndex;\
S3L_vec3Xmat4(&pointModel,&mat1);\
transformed##n.x = pointModel.x;\
transformed##n.y = pointModel.y;\
transformed##n.z = pointModel.z;\
transformed##n.w = S3L_FRACTIONS_PER_UNIT;\
S3L_perspectiveDivide(&transformed##n,scene.camera.focalLength);
/* TODO: maybe create an option that would use a cache here to not
transform the same point twice? */
project(0)
project(1)
project(2)
#undef project
S3L_drawTriangle(transformed0,transformed1,transformed2,
&(scene.models[modelIndex].config),&(scene.camera),triangleIndex);
++triangleIndex;
}
}
}

View file

@ -35,6 +35,9 @@ const S3L_Unit ver[] = { S3L_CUBE_VERTICES };
const S3L_Index tri[] = { S3L_CUBE_TRIANGLES };
const S3L_Unit tex_coords[] = { S3L_CUBE_TEXCOORDS(16) };
S3L_Model3D models[2];
S3L_Scene scene;
int8_t keys[256];
const uint8_t testTexture[] =
@ -126,7 +129,6 @@ setPixel(p->x,p->y,sss,sss,sss);
// setPixel(p->x,p->y,p->barycentric0 / ((float) S3L_FRACTIONS_PER_UNIT) * 255,p->barycentric1 / ((float) S3L_FRACTIONS_PER_UNIT) * 255,p->barycentric2 / ((float) S3L_FRACTIONS_PER_UNIT) * 255);
}
S3L_Camera camera;
S3L_Transform3D modelTransform;
S3L_DrawConfig conf;
@ -136,11 +138,11 @@ void draw()
if (frame % 128 == 0)
{
printf("frame: %d\n",frame);
printf("camera:\n");
printf("scene.camera:\n");
printf(" translation: ");
S3L_writeVec4(camera.transform.translation);
S3L_writeVec4(scene.camera.transform.translation);
printf(" rotation: ");
S3L_writeVec4(camera.transform.rotation);
S3L_writeVec4(scene.camera.transform.rotation);
}
*/
@ -150,22 +152,26 @@ void draw()
uint32_t f = frame;
modelTransform.rotation.z = f * 0.1;
modelTransform.rotation.x = f * 0.3;
scene.models[0].transform.rotation.z = f * 0.1;
scene.models[0].transform.rotation.x = f * 0.3;
// modelTransform.translation.x = sin(f >> 7) * 700;
// modelTransform.translation.y = sin(f >> 8) * 600;
S3L_drawModelIndexed(ver,tri,12,modelTransform,&camera,&conf);
/*
S3L_drawModelIndexed(ver,tri,12,modelTransform,&scene.camera,&conf);
modelTransform.translation.x += 2 * S3L_FRACTIONS_PER_UNIT;
S3L_drawModelIndexed(ver,tri,12,modelTransform,&camera,&conf);
S3L_drawModelIndexed(ver,tri,12,modelTransform,&scene.camera,&conf);
modelTransform.translation.x -= 2 * S3L_FRACTIONS_PER_UNIT;
*/
S3L_drawScene(scene);
if (offScreenPixels > 0)
printf("offscreen pixels: %d\n",offScreenPixels);
// S3L_drawModelIndexed(ver,tri,1,modelTransform,&camera,&conf);
// S3L_drawModelIndexed(ver,tri,1,modelTransform,&scene.camera,&conf);
/*
conf.backfaceCulling = S3L_BACKFACE_CULLING_NONE;
@ -216,12 +222,25 @@ int main()
SDL_Surface *screenSurface = SDL_GetWindowSurface(window);
SDL_Event event;
S3L_initCamera(&camera);
S3L_initCamera(&scene.camera);
camera.transform.translation.z = -S3L_FRACTIONS_PER_UNIT * 2;
scene.camera.transform.translation.z = -S3L_FRACTIONS_PER_UNIT * 2;
scene.modelCount = 2;
scene.models = &models;
// camera.transform.translation.x = S3L_FRACTIONS_PER_UNIT;
// camera.transform.translation.y = S3L_FRACTIONS_PER_UNIT;
scene.models[0].vertices = ver;
scene.models[0].vertexCount = S3L_CUBE_VERTEX_COUNT;
scene.models[0].triangles = tri;
scene.models[0].triangleCount = S3L_CUBE_TRIANGLE_COUNT;
S3L_initTransoform3D(&(scene.models[0].transform));
S3L_initDrawConfig(&(scene.models[0].config));
scene.models[0].transform.translation.x = S3L_FRACTIONS_PER_UNIT;
scene.models[1] = scene.models[0];
scene.models[1].transform.translation.x = -1 * S3L_FRACTIONS_PER_UNIT;
// scene.camera.transform.translation.x = S3L_FRACTIONS_PER_UNIT;
// scene.camera.transform.translation.y = S3L_FRACTIONS_PER_UNIT;
S3L_initTransoform3D(&modelTransform);
S3L_initDrawConfig(&conf);
@ -261,47 +280,47 @@ int main()
int step = 10;
S3L_rotationToDirections(
camera.transform.rotation,
scene.camera.transform.rotation,
step,
&camF,
&camR,
&camU);
if (keys['w'])
S3L_vec3Add(&camera.transform.translation,camF);
S3L_vec3Add(&scene.camera.transform.translation,camF);
if (keys['s'])
S3L_vec3Sub(&camera.transform.translation,camF);
S3L_vec3Sub(&scene.camera.transform.translation,camF);
if (keys['d'])
S3L_vec3Add(&camera.transform.translation,camR);
S3L_vec3Add(&scene.camera.transform.translation,camR);
if (keys['a'])
S3L_vec3Sub(&camera.transform.translation,camR);
S3L_vec3Sub(&scene.camera.transform.translation,camR);
if (keys['c'])
S3L_vec3Add(&camera.transform.translation,camU);
S3L_vec3Add(&scene.camera.transform.translation,camU);
if (keys['x'])
S3L_vec3Sub(&camera.transform.translation,camU);
S3L_vec3Sub(&scene.camera.transform.translation,camU);
if (keys['q'])
camera.transform.rotation.y -= 1;
scene.camera.transform.rotation.y -= 1;
if (keys['e'])
camera.transform.rotation.y += 1;
scene.camera.transform.rotation.y += 1;
if (keys['r'])
camera.transform.rotation.x -= 1;
scene.camera.transform.rotation.x -= 1;
if (keys['t'])
camera.transform.rotation.x += 1;
scene.camera.transform.rotation.x += 1;
if (keys['f'])
camera.transform.rotation.z -= 1;
scene.camera.transform.rotation.z -= 1;
if (keys['g'])
camera.transform.rotation.z += 1;
scene.camera.transform.rotation.z += 1;
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer,texture,NULL,NULL);