Add a few more mesh types
This commit is contained in:
@@ -11,6 +11,10 @@
|
||||
#include "display/spritebatch/spritebatch.h"
|
||||
#include "display/mesh/quad.h"
|
||||
#include "display/mesh/cube.h"
|
||||
#include "display/mesh/sphere.h"
|
||||
#include "display/mesh/plane.h"
|
||||
#include "display/mesh/capsule.h"
|
||||
#include "display/mesh/triprism.h"
|
||||
#include "display/screen/screen.h"
|
||||
#include "ui/ui.h"
|
||||
#include "display/text/text.h"
|
||||
@@ -35,8 +39,15 @@ errorret_t displayInit(void) {
|
||||
&TEXTURE_WHITE, 4, 4,
|
||||
TEXTURE_FORMAT_RGBA, (texturedata_t){ .rgbaColors = TEXTURE_WHITE_PIXELS }
|
||||
));
|
||||
|
||||
// Standard meshes
|
||||
errorChain(quadInit());
|
||||
errorChain(cubeInit());
|
||||
errorChain(sphereInit());
|
||||
errorChain(planeInit());
|
||||
errorChain(capsuleInit());
|
||||
errorChain(triPrismInit());
|
||||
|
||||
errorChain(frameBufferInitBackBuffer());
|
||||
errorChain(spriteBatchInit());
|
||||
errorChain(textInit());
|
||||
|
||||
@@ -9,4 +9,8 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
mesh.c
|
||||
quad.c
|
||||
cube.c
|
||||
sphere.c
|
||||
plane.c
|
||||
capsule.c
|
||||
triprism.c
|
||||
)
|
||||
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "capsule.h"
|
||||
#include "assert/assert.h"
|
||||
|
||||
mesh_t CAPSULE_MESH_SIMPLE;
|
||||
meshvertex_t CAPSULE_MESH_SIMPLE_VERTICES[CAPSULE_VERTEX_COUNT];
|
||||
|
||||
errorret_t capsuleInit() {
|
||||
vec3 center = { 0.0f, 0.0f, 0.0f };
|
||||
capsuleBuffer(
|
||||
CAPSULE_MESH_SIMPLE_VERTICES,
|
||||
center,
|
||||
0.5f,
|
||||
0.5f,
|
||||
CAPSULE_CAP_RINGS,
|
||||
CAPSULE_SECTORS
|
||||
#if MESH_ENABLE_COLOR
|
||||
, COLOR_WHITE_4B
|
||||
#endif
|
||||
);
|
||||
errorChain(meshInit(
|
||||
&CAPSULE_MESH_SIMPLE,
|
||||
CAPSULE_PRIMITIVE_TYPE,
|
||||
CAPSULE_VERTEX_COUNT,
|
||||
CAPSULE_MESH_SIMPLE_VERTICES
|
||||
));
|
||||
errorOk();
|
||||
}
|
||||
|
||||
void capsuleBuffer(
|
||||
meshvertex_t *vertices,
|
||||
const vec3 center,
|
||||
const float_t radius,
|
||||
const float_t halfHeight,
|
||||
const int32_t capRings,
|
||||
const int32_t sectors
|
||||
#if MESH_ENABLE_COLOR
|
||||
, const color_t color
|
||||
#endif
|
||||
) {
|
||||
assertNotNull(vertices, "Vertices cannot be NULL");
|
||||
assertNotNull(center, "Center vector cannot be NULL");
|
||||
|
||||
const float_t cx = center[0];
|
||||
const float_t cy = center[1];
|
||||
const float_t cz = center[2];
|
||||
const float_t sectorStep = 2.0f * (float_t)GLM_PI / (float_t)sectors;
|
||||
int32_t vi = 0;
|
||||
|
||||
/* Helper macro: write one vertex. */
|
||||
#if MESH_ENABLE_COLOR
|
||||
#define CAP_VERT(px, py, pz, u, v) \
|
||||
vertices[vi].color = color; \
|
||||
vertices[vi].pos[0] = (px); \
|
||||
vertices[vi].pos[1] = (py); \
|
||||
vertices[vi].pos[2] = (pz); \
|
||||
vertices[vi].uv[0] = (u); \
|
||||
vertices[vi].uv[1] = (v); \
|
||||
vi++;
|
||||
#else
|
||||
#define CAP_VERT(px, py, pz, u, v) \
|
||||
vertices[vi].pos[0] = (px); \
|
||||
vertices[vi].pos[1] = (py); \
|
||||
vertices[vi].pos[2] = (pz); \
|
||||
vertices[vi].uv[0] = (u); \
|
||||
vertices[vi].uv[1] = (v); \
|
||||
vi++;
|
||||
#endif
|
||||
|
||||
/* ---- Top hemisphere ---- */
|
||||
/* phi ranges from PI/2 (top pole) down to 0 (equator). */
|
||||
const float_t capStep = (float_t)GLM_PI_2 / (float_t)capRings;
|
||||
for(int32_t i = 0; i < capRings; i++) {
|
||||
const float_t phi1 = (float_t)GLM_PI_2 - (float_t)i * capStep;
|
||||
const float_t phi2 = (float_t)GLM_PI_2 - (float_t)(i + 1) * capStep;
|
||||
|
||||
const float_t ly1 = radius * sinf(phi1);
|
||||
const float_t ly2 = radius * sinf(phi2);
|
||||
const float_t lxz1 = radius * cosf(phi1);
|
||||
const float_t lxz2 = radius * cosf(phi2);
|
||||
|
||||
/* UV: top cap occupies v in [0.5 + halfHeightFrac .. 1.0] — we use a
|
||||
* simple per-band normalisation against the full height. */
|
||||
const float_t v1 = 1.0f - (float_t)i / (float_t)(2 * capRings + 1);
|
||||
const float_t v2 = 1.0f - (float_t)(i + 1) / (float_t)(2 * capRings + 1);
|
||||
|
||||
for(int32_t j = 0; j < sectors; j++) {
|
||||
const float_t t1 = (float_t)j * sectorStep;
|
||||
const float_t t2 = (float_t)(j + 1) * sectorStep;
|
||||
|
||||
const float_t u1 = (float_t)j / (float_t)sectors;
|
||||
const float_t u2 = (float_t)(j + 1) / (float_t)sectors;
|
||||
|
||||
const float_t x11 = lxz1 * cosf(t1), z11 = lxz1 * sinf(t1);
|
||||
const float_t x12 = lxz1 * cosf(t2), z12 = lxz1 * sinf(t2);
|
||||
const float_t x21 = lxz2 * cosf(t1), z21 = lxz2 * sinf(t1);
|
||||
const float_t x22 = lxz2 * cosf(t2), z22 = lxz2 * sinf(t2);
|
||||
|
||||
const float_t y1off = cy + halfHeight + ly1;
|
||||
const float_t y2off = cy + halfHeight + ly2;
|
||||
|
||||
CAP_VERT(cx+x11, y1off, cz+z11, u1, v1)
|
||||
CAP_VERT(cx+x21, y2off, cz+z21, u1, v2)
|
||||
CAP_VERT(cx+x12, y1off, cz+z12, u2, v1)
|
||||
|
||||
CAP_VERT(cx+x12, y1off, cz+z12, u2, v1)
|
||||
CAP_VERT(cx+x21, y2off, cz+z21, u1, v2)
|
||||
CAP_VERT(cx+x22, y2off, cz+z22, u2, v2)
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- Cylindrical body ---- */
|
||||
{
|
||||
const float_t yTop = cy + halfHeight;
|
||||
const float_t yBot = cy - halfHeight;
|
||||
const float_t vTop = 1.0f - (float_t)capRings / (float_t)(2 * capRings + 1);
|
||||
const float_t vBot = 1.0f - (float_t)(capRings + 1) / (float_t)(2 * capRings + 1);
|
||||
|
||||
for(int32_t j = 0; j < sectors; j++) {
|
||||
const float_t t1 = (float_t)j * sectorStep;
|
||||
const float_t t2 = (float_t)(j + 1) * sectorStep;
|
||||
|
||||
const float_t u1 = (float_t)j / (float_t)sectors;
|
||||
const float_t u2 = (float_t)(j + 1) / (float_t)sectors;
|
||||
|
||||
const float_t x1 = radius * cosf(t1), z1 = radius * sinf(t1);
|
||||
const float_t x2 = radius * cosf(t2), z2 = radius * sinf(t2);
|
||||
|
||||
CAP_VERT(cx+x1, yTop, cz+z1, u1, vTop)
|
||||
CAP_VERT(cx+x1, yBot, cz+z1, u1, vBot)
|
||||
CAP_VERT(cx+x2, yTop, cz+z2, u2, vTop)
|
||||
|
||||
CAP_VERT(cx+x2, yTop, cz+z2, u2, vTop)
|
||||
CAP_VERT(cx+x1, yBot, cz+z1, u1, vBot)
|
||||
CAP_VERT(cx+x2, yBot, cz+z2, u2, vBot)
|
||||
}
|
||||
}
|
||||
|
||||
// Bottom hemisphere
|
||||
for(int32_t i = 0; i < capRings; i++) {
|
||||
const float_t phi1 = -(float_t)i * capStep;
|
||||
const float_t phi2 = -(float_t)(i + 1) * capStep;
|
||||
|
||||
const float_t ly1 = radius * sinf(phi1);
|
||||
const float_t ly2 = radius * sinf(phi2);
|
||||
const float_t lxz1 = radius * cosf(phi1);
|
||||
const float_t lxz2 = radius * cosf(phi2);
|
||||
|
||||
const float_t v1 = 1.0f - (float_t)(capRings + 1 + i) / (float_t)(2 * capRings + 1);
|
||||
const float_t v2 = 1.0f - (float_t)(capRings + 1 + i + 1) / (float_t)(2 * capRings + 1);
|
||||
|
||||
for(int32_t j = 0; j < sectors; j++) {
|
||||
const float_t t1 = (float_t)j * sectorStep;
|
||||
const float_t t2 = (float_t)(j + 1) * sectorStep;
|
||||
|
||||
const float_t u1 = (float_t)j / (float_t)sectors;
|
||||
const float_t u2 = (float_t)(j + 1) / (float_t)sectors;
|
||||
|
||||
const float_t x11 = lxz1 * cosf(t1), z11 = lxz1 * sinf(t1);
|
||||
const float_t x12 = lxz1 * cosf(t2), z12 = lxz1 * sinf(t2);
|
||||
const float_t x21 = lxz2 * cosf(t1), z21 = lxz2 * sinf(t1);
|
||||
const float_t x22 = lxz2 * cosf(t2), z22 = lxz2 * sinf(t2);
|
||||
|
||||
const float_t y1off = cy - halfHeight + ly1;
|
||||
const float_t y2off = cy - halfHeight + ly2;
|
||||
|
||||
CAP_VERT(cx+x11, y1off, cz+z11, u1, v1)
|
||||
CAP_VERT(cx+x21, y2off, cz+z21, u1, v2)
|
||||
CAP_VERT(cx+x12, y1off, cz+z12, u2, v1)
|
||||
|
||||
CAP_VERT(cx+x12, y1off, cz+z12, u2, v1)
|
||||
CAP_VERT(cx+x21, y2off, cz+z21, u1, v2)
|
||||
CAP_VERT(cx+x22, y2off, cz+z22, u2, v2)
|
||||
}
|
||||
}
|
||||
|
||||
#undef CAP_VERT
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "display/mesh/mesh.h"
|
||||
#include "display/color.h"
|
||||
|
||||
#define CAPSULE_CAP_RINGS 4
|
||||
#define CAPSULE_SECTORS 16
|
||||
#define CAPSULE_VERTEX_COUNT ((2 * CAPSULE_CAP_RINGS + 1) * CAPSULE_SECTORS * 6)
|
||||
#define CAPSULE_PRIMITIVE_TYPE MESH_PRIMITIVE_TYPE_TRIANGLES
|
||||
|
||||
extern mesh_t CAPSULE_MESH_SIMPLE;
|
||||
extern meshvertex_t CAPSULE_MESH_SIMPLE_VERTICES[CAPSULE_VERTEX_COUNT];
|
||||
|
||||
/**
|
||||
* Initializes the simple unit capsule mesh centered at (0,0,0) with radius 0.5
|
||||
* and a cylindrical half-height of 0.5 (total height 2.0).
|
||||
*
|
||||
* @return Error for initialization of the capsule mesh.
|
||||
*/
|
||||
errorret_t capsuleInit();
|
||||
|
||||
/**
|
||||
* Buffers a capsule (cylinder + two hemisphere caps) into the provided vertex
|
||||
* array. The capsule's long axis is Y. Total vertex count is
|
||||
* (2*capRings + 1) * sectors * 6.
|
||||
*
|
||||
* @param vertices Vertex array to write into.
|
||||
* @param center Center position of the capsule.
|
||||
* @param radius Radius of the cylinder and hemisphere caps.
|
||||
* @param halfHeight Half the height of the cylindrical section only (caps
|
||||
* extend an additional radius above/below).
|
||||
* @param capRings Number of latitude rings per hemisphere cap.
|
||||
* @param sectors Number of longitude segments around the circumference.
|
||||
* @param color Color applied to all vertices.
|
||||
*/
|
||||
void capsuleBuffer(
|
||||
meshvertex_t *vertices,
|
||||
const vec3 center,
|
||||
const float_t radius,
|
||||
const float_t halfHeight,
|
||||
const int32_t capRings,
|
||||
const int32_t sectors
|
||||
#if MESH_ENABLE_COLOR
|
||||
, const color_t color
|
||||
#endif
|
||||
);
|
||||
@@ -14,7 +14,12 @@ meshvertex_t CUBE_MESH_SIMPLE_VERTICES[CUBE_VERTEX_COUNT];
|
||||
errorret_t cubeInit() {
|
||||
vec3 min = { 0.0f, 0.0f, 0.0f };
|
||||
vec3 max = { 1.0f, 1.0f, 1.0f };
|
||||
cubeBuffer(CUBE_MESH_SIMPLE_VERTICES, min, max, COLOR_WHITE_4B);
|
||||
cubeBuffer(
|
||||
CUBE_MESH_SIMPLE_VERTICES, min, max
|
||||
#if MESH_ENABLE_COLOR
|
||||
, COLOR_WHITE_4B
|
||||
#endif
|
||||
);
|
||||
errorChain(meshInit(
|
||||
&CUBE_MESH_SIMPLE,
|
||||
CUBE_PRIMITIVE_TYPE,
|
||||
@@ -45,8 +50,10 @@ errorret_t cubeInit() {
|
||||
void cubeBuffer(
|
||||
meshvertex_t *vertices,
|
||||
const vec3 min,
|
||||
const vec3 max,
|
||||
const color_t color
|
||||
const vec3 max
|
||||
#if MESH_ENABLE_COLOR
|
||||
, const color_t color
|
||||
#endif
|
||||
) {
|
||||
assertNotNull(vertices, "Vertices cannot be NULL");
|
||||
assertNotNull(min, "Min vector cannot be NULL");
|
||||
|
||||
@@ -36,6 +36,8 @@ errorret_t cubeInit();
|
||||
void cubeBuffer(
|
||||
meshvertex_t *vertices,
|
||||
const vec3 min,
|
||||
const vec3 max,
|
||||
const color_t color
|
||||
const vec3 max
|
||||
#if MESH_ENABLE_COLOR
|
||||
, const color_t color
|
||||
#endif
|
||||
);
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "plane.h"
|
||||
#include "assert/assert.h"
|
||||
|
||||
mesh_t PLANE_MESH_SIMPLE;
|
||||
meshvertex_t PLANE_MESH_SIMPLE_VERTICES[PLANE_VERTEX_COUNT];
|
||||
|
||||
errorret_t planeInit() {
|
||||
vec3 min = { 0.0f, 0.0f, 0.0f };
|
||||
vec3 max = { 1.0f, 0.0f, 1.0f };
|
||||
vec2 uvMin = { 0.0f, 0.0f };
|
||||
vec2 uvMax = { 1.0f, 1.0f };
|
||||
planeBuffer(
|
||||
PLANE_MESH_SIMPLE_VERTICES,
|
||||
PLANE_AXIS_XZ,
|
||||
min,
|
||||
max
|
||||
#if MESH_ENABLE_COLOR
|
||||
, COLOR_WHITE_4B
|
||||
#endif
|
||||
, uvMin,
|
||||
uvMax
|
||||
);
|
||||
errorChain(meshInit(
|
||||
&PLANE_MESH_SIMPLE,
|
||||
PLANE_PRIMITIVE_TYPE,
|
||||
PLANE_VERTEX_COUNT,
|
||||
PLANE_MESH_SIMPLE_VERTICES
|
||||
));
|
||||
errorOk();
|
||||
}
|
||||
|
||||
/* Helper macro to write one vertex. */
|
||||
#if MESH_ENABLE_COLOR
|
||||
#define PLANE_VERT(i, px, py, pz, u, v) \
|
||||
vertices[i].color = color; \
|
||||
vertices[i].pos[0] = (px); \
|
||||
vertices[i].pos[1] = (py); \
|
||||
vertices[i].pos[2] = (pz); \
|
||||
vertices[i].uv[0] = (u); \
|
||||
vertices[i].uv[1] = (v);
|
||||
#else
|
||||
#define PLANE_VERT(i, px, py, pz, u, v) \
|
||||
vertices[i].pos[0] = (px); \
|
||||
vertices[i].pos[1] = (py); \
|
||||
vertices[i].pos[2] = (pz); \
|
||||
vertices[i].uv[0] = (u); \
|
||||
vertices[i].uv[1] = (v);
|
||||
#endif
|
||||
|
||||
void planeBuffer(
|
||||
meshvertex_t *vertices,
|
||||
const planeaxis_t axis,
|
||||
const vec3 min,
|
||||
const vec3 max
|
||||
#if MESH_ENABLE_COLOR
|
||||
, const color_t color
|
||||
#endif
|
||||
, const vec2 uvMin,
|
||||
const vec2 uvMax
|
||||
) {
|
||||
assertNotNull(vertices, "Vertices cannot be NULL");
|
||||
assertNotNull(min, "Min vector cannot be NULL");
|
||||
assertNotNull(max, "Max vector cannot be NULL");
|
||||
assertNotNull(uvMin, "uvMin cannot be NULL");
|
||||
assertNotNull(uvMax, "uvMax cannot be NULL");
|
||||
|
||||
const float_t u0 = uvMin[0], u1 = uvMax[0];
|
||||
const float_t v0 = uvMin[1], v1 = uvMax[1];
|
||||
|
||||
switch (axis) {
|
||||
case PLANE_AXIS_XY: {
|
||||
/* Flat in XY at z = min[2]; spans X and Y. */
|
||||
const float_t z = min[2];
|
||||
PLANE_VERT(0, min[0], min[1], z, u0, v0)
|
||||
PLANE_VERT(1, max[0], min[1], z, u1, v0)
|
||||
PLANE_VERT(2, max[0], max[1], z, u1, v1)
|
||||
PLANE_VERT(3, min[0], min[1], z, u0, v0)
|
||||
PLANE_VERT(4, max[0], max[1], z, u1, v1)
|
||||
PLANE_VERT(5, min[0], max[1], z, u0, v1)
|
||||
break;
|
||||
}
|
||||
|
||||
case PLANE_AXIS_XZ: {
|
||||
/* Flat in XZ at y = min[1]; spans X and Z. */
|
||||
const float_t y = min[1];
|
||||
PLANE_VERT(0, min[0], y, min[2], u0, v0)
|
||||
PLANE_VERT(1, max[0], y, min[2], u1, v0)
|
||||
PLANE_VERT(2, max[0], y, max[2], u1, v1)
|
||||
PLANE_VERT(3, min[0], y, min[2], u0, v0)
|
||||
PLANE_VERT(4, max[0], y, max[2], u1, v1)
|
||||
PLANE_VERT(5, min[0], y, max[2], u0, v1)
|
||||
break;
|
||||
}
|
||||
|
||||
case PLANE_AXIS_YZ: {
|
||||
/* Flat in YZ at x = min[0]; spans Y and Z. */
|
||||
const float_t x = min[0];
|
||||
PLANE_VERT(0, x, min[1], min[2], u0, v0)
|
||||
PLANE_VERT(1, x, max[1], min[2], u1, v0)
|
||||
PLANE_VERT(2, x, max[1], max[2], u1, v1)
|
||||
PLANE_VERT(3, x, min[1], min[2], u0, v0)
|
||||
PLANE_VERT(4, x, max[1], max[2], u1, v1)
|
||||
PLANE_VERT(5, x, min[1], max[2], u0, v1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#undef PLANE_VERT
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "display/mesh/mesh.h"
|
||||
#include "display/color.h"
|
||||
|
||||
#define PLANE_VERTEX_COUNT 6
|
||||
#define PLANE_PRIMITIVE_TYPE MESH_PRIMITIVE_TYPE_TRIANGLES
|
||||
|
||||
/** Which axis the plane's normal points along. */
|
||||
typedef enum {
|
||||
PLANE_AXIS_XY = 0, /**< Flat in XY, normal along +Z (billboard/wall face). */
|
||||
PLANE_AXIS_XZ = 1, /**< Flat in XZ, normal along +Y (ground/floor plane). */
|
||||
PLANE_AXIS_YZ = 2, /**< Flat in YZ, normal along +X (side wall). */
|
||||
} planeaxis_t;
|
||||
|
||||
extern mesh_t PLANE_MESH_SIMPLE;
|
||||
extern meshvertex_t PLANE_MESH_SIMPLE_VERTICES[PLANE_VERTEX_COUNT];
|
||||
|
||||
/**
|
||||
* Initializes the simple unit XZ plane mesh (ground plane) from (0,0,0) to
|
||||
* (1,0,1).
|
||||
*
|
||||
* @return Error for initialization of the plane mesh.
|
||||
*/
|
||||
errorret_t planeInit();
|
||||
|
||||
/**
|
||||
* Buffers an axis-aligned plane into the provided vertex array.
|
||||
* Writes PLANE_VERTEX_COUNT (6) vertices (two triangles, CCW winding).
|
||||
*
|
||||
* The min/max corners fully describe the plane in 3D space. The axis enum
|
||||
* controls which dimension is treated as the "depth" (normal) axis:
|
||||
* PLANE_AXIS_XY — spans X and Y, depth from min[2]/max[2] (uses min[2])
|
||||
* PLANE_AXIS_XZ — spans X and Z, depth from min[1]/max[1] (uses min[1])
|
||||
* PLANE_AXIS_YZ — spans Y and Z, depth from min[0]/max[0] (uses min[0])
|
||||
*
|
||||
* @param vertices Vertex array to write into (must hold PLANE_VERTEX_COUNT).
|
||||
* @param axis Which axis the plane's normal points along.
|
||||
* @param min Minimum XYZ corner.
|
||||
* @param max Maximum XYZ corner.
|
||||
* @param color Color applied to all vertices.
|
||||
* @param uvMin Minimum UV coordinates.
|
||||
* @param uvMax Maximum UV coordinates.
|
||||
*/
|
||||
void planeBuffer(
|
||||
meshvertex_t *vertices,
|
||||
const planeaxis_t axis,
|
||||
const vec3 min,
|
||||
const vec3 max
|
||||
#if MESH_ENABLE_COLOR
|
||||
, const color_t color
|
||||
#endif
|
||||
, const vec2 uvMin,
|
||||
const vec2 uvMax
|
||||
);
|
||||
@@ -77,13 +77,13 @@ void quadBuffer(
|
||||
const float_t minY,
|
||||
const float_t maxX,
|
||||
const float_t maxY,
|
||||
#if MESH_ENABLE_COLOR
|
||||
const color_t color,
|
||||
#endif
|
||||
const float_t u0,
|
||||
const float_t v0,
|
||||
const float_t u1,
|
||||
const float_t v1
|
||||
#if MESH_ENABLE_COLOR
|
||||
, const color_t color
|
||||
#endif
|
||||
) {
|
||||
const float_t z = 0.0f; // Z coordinate for 2D rendering
|
||||
assertNotNull(vertices, "Vertices cannot be NULL");
|
||||
@@ -149,11 +149,11 @@ void quadBuffer3D(
|
||||
meshvertex_t *vertices,
|
||||
const vec3 min,
|
||||
const vec3 max,
|
||||
#if MESH_ENABLE_COLOR
|
||||
const color_t color,
|
||||
#endif
|
||||
const vec2 uvMin,
|
||||
const vec2 uvMax
|
||||
#if MESH_ENABLE_COLOR
|
||||
, const color_t color
|
||||
#endif
|
||||
) {
|
||||
assertNotNull(vertices, "Vertices cannot be NULL");
|
||||
assertNotNull(min, "Min vector cannot be NULL");
|
||||
|
||||
@@ -42,13 +42,13 @@ void quadBuffer(
|
||||
const float_t minY,
|
||||
const float_t maxX,
|
||||
const float_t maxY,
|
||||
#if MESH_ENABLE_COLOR
|
||||
const color_t color,
|
||||
#endif
|
||||
const float_t u0,
|
||||
const float_t v0,
|
||||
const float_t u1,
|
||||
const float_t v1
|
||||
#if MESH_ENABLE_COLOR
|
||||
, const color_t color
|
||||
#endif
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -65,9 +65,9 @@ void quadBuffer3D(
|
||||
meshvertex_t *vertices,
|
||||
const vec3 min,
|
||||
const vec3 max,
|
||||
#if MESH_ENABLE_COLOR
|
||||
const color_t color,
|
||||
#endif
|
||||
const vec2 uvMin,
|
||||
const vec2 uvMax
|
||||
#if MESH_ENABLE_COLOR
|
||||
, const color_t color
|
||||
#endif
|
||||
);
|
||||
@@ -0,0 +1,145 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "sphere.h"
|
||||
#include "assert/assert.h"
|
||||
|
||||
mesh_t SPHERE_MESH_SIMPLE;
|
||||
meshvertex_t SPHERE_MESH_SIMPLE_VERTICES[SPHERE_VERTEX_COUNT];
|
||||
|
||||
errorret_t sphereInit() {
|
||||
vec3 center = { 0.0f, 0.0f, 0.0f };
|
||||
sphereBuffer(
|
||||
SPHERE_MESH_SIMPLE_VERTICES,
|
||||
center,
|
||||
0.5f,
|
||||
SPHERE_STACKS,
|
||||
SPHERE_SECTORS
|
||||
#if MESH_ENABLE_COLOR
|
||||
, COLOR_WHITE_4B
|
||||
#endif
|
||||
);
|
||||
errorChain(meshInit(
|
||||
&SPHERE_MESH_SIMPLE,
|
||||
SPHERE_PRIMITIVE_TYPE,
|
||||
SPHERE_VERTEX_COUNT,
|
||||
SPHERE_MESH_SIMPLE_VERTICES
|
||||
));
|
||||
errorOk();
|
||||
}
|
||||
|
||||
void sphereBuffer(
|
||||
meshvertex_t *vertices,
|
||||
const vec3 center,
|
||||
const float_t radius,
|
||||
const int32_t stacks,
|
||||
const int32_t sectors
|
||||
#if MESH_ENABLE_COLOR
|
||||
, const color_t color
|
||||
#endif
|
||||
) {
|
||||
assertNotNull(vertices, "Vertices cannot be NULL");
|
||||
assertNotNull(center, "Center vector cannot be NULL");
|
||||
|
||||
const float_t stackStep = (float_t)GLM_PI / (float_t)stacks;
|
||||
const float_t sectorStep = 2.0f * (float_t)GLM_PI / (float_t)sectors;
|
||||
int32_t vi = 0;
|
||||
|
||||
for(int32_t i = 0; i < stacks; i++) {
|
||||
/* Latitude angles: top of band -> bottom of band */
|
||||
const float_t phi1 = (float_t)GLM_PI_2 - (float_t)i * stackStep;
|
||||
const float_t phi2 = (float_t)GLM_PI_2 - (float_t)(i + 1) * stackStep;
|
||||
|
||||
const float_t y1 = radius * sinf(phi1);
|
||||
const float_t y2 = radius * sinf(phi2);
|
||||
const float_t xz1 = radius * cosf(phi1);
|
||||
const float_t xz2 = radius * cosf(phi2);
|
||||
|
||||
const float_t v1 = 1.0f - (float_t)i / (float_t)stacks;
|
||||
const float_t v2 = 1.0f - (float_t)(i + 1) / (float_t)stacks;
|
||||
|
||||
for(int32_t j = 0; j < sectors; j++) {
|
||||
const float_t theta1 = (float_t)j * sectorStep;
|
||||
const float_t theta2 = (float_t)(j + 1) * sectorStep;
|
||||
|
||||
const float_t x11 = xz1 * cosf(theta1);
|
||||
const float_t z11 = xz1 * sinf(theta1);
|
||||
const float_t x12 = xz1 * cosf(theta2);
|
||||
const float_t z12 = xz1 * sinf(theta2);
|
||||
|
||||
const float_t x21 = xz2 * cosf(theta1);
|
||||
const float_t z21 = xz2 * sinf(theta1);
|
||||
const float_t x22 = xz2 * cosf(theta2);
|
||||
const float_t z22 = xz2 * sinf(theta2);
|
||||
|
||||
const float_t u1 = (float_t)j / (float_t)sectors;
|
||||
const float_t u2 = (float_t)(j + 1) / (float_t)sectors;
|
||||
|
||||
/* Triangle 1: top-left, bottom-left, top-right */
|
||||
#if MESH_ENABLE_COLOR
|
||||
vertices[vi].color = color;
|
||||
#endif
|
||||
vertices[vi].pos[0] = center[0] + x11;
|
||||
vertices[vi].pos[1] = center[1] + y1;
|
||||
vertices[vi].pos[2] = center[2] + z11;
|
||||
vertices[vi].uv[0] = u1;
|
||||
vertices[vi].uv[1] = v1;
|
||||
vi++;
|
||||
|
||||
#if MESH_ENABLE_COLOR
|
||||
vertices[vi].color = color;
|
||||
#endif
|
||||
vertices[vi].pos[0] = center[0] + x21;
|
||||
vertices[vi].pos[1] = center[1] + y2;
|
||||
vertices[vi].pos[2] = center[2] + z21;
|
||||
vertices[vi].uv[0] = u1;
|
||||
vertices[vi].uv[1] = v2;
|
||||
vi++;
|
||||
|
||||
#if MESH_ENABLE_COLOR
|
||||
vertices[vi].color = color;
|
||||
#endif
|
||||
vertices[vi].pos[0] = center[0] + x12;
|
||||
vertices[vi].pos[1] = center[1] + y1;
|
||||
vertices[vi].pos[2] = center[2] + z12;
|
||||
vertices[vi].uv[0] = u2;
|
||||
vertices[vi].uv[1] = v1;
|
||||
vi++;
|
||||
|
||||
/* Triangle 2: top-right, bottom-left, bottom-right */
|
||||
#if MESH_ENABLE_COLOR
|
||||
vertices[vi].color = color;
|
||||
#endif
|
||||
vertices[vi].pos[0] = center[0] + x12;
|
||||
vertices[vi].pos[1] = center[1] + y1;
|
||||
vertices[vi].pos[2] = center[2] + z12;
|
||||
vertices[vi].uv[0] = u2;
|
||||
vertices[vi].uv[1] = v1;
|
||||
vi++;
|
||||
|
||||
#if MESH_ENABLE_COLOR
|
||||
vertices[vi].color = color;
|
||||
#endif
|
||||
vertices[vi].pos[0] = center[0] + x21;
|
||||
vertices[vi].pos[1] = center[1] + y2;
|
||||
vertices[vi].pos[2] = center[2] + z21;
|
||||
vertices[vi].uv[0] = u1;
|
||||
vertices[vi].uv[1] = v2;
|
||||
vi++;
|
||||
|
||||
#if MESH_ENABLE_COLOR
|
||||
vertices[vi].color = color;
|
||||
#endif
|
||||
vertices[vi].pos[0] = center[0] + x22;
|
||||
vertices[vi].pos[1] = center[1] + y2;
|
||||
vertices[vi].pos[2] = center[2] + z22;
|
||||
vertices[vi].uv[0] = u2;
|
||||
vertices[vi].uv[1] = v2;
|
||||
vi++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "display/mesh/mesh.h"
|
||||
#include "display/color.h"
|
||||
|
||||
#define SPHERE_STACKS 8
|
||||
#define SPHERE_SECTORS 16
|
||||
#define SPHERE_VERTEX_COUNT (SPHERE_STACKS * SPHERE_SECTORS * 6)
|
||||
#define SPHERE_PRIMITIVE_TYPE MESH_PRIMITIVE_TYPE_TRIANGLES
|
||||
|
||||
extern mesh_t SPHERE_MESH_SIMPLE;
|
||||
extern meshvertex_t SPHERE_MESH_SIMPLE_VERTICES[SPHERE_VERTEX_COUNT];
|
||||
|
||||
/**
|
||||
* Initializes the simple unit sphere mesh centered at (0,0,0) with radius 0.5.
|
||||
*
|
||||
* @return Error for initialization of the sphere mesh.
|
||||
*/
|
||||
errorret_t sphereInit();
|
||||
|
||||
/**
|
||||
* Buffers a UV sphere into the provided vertex array.
|
||||
* Writes stacks * sectors * 6 vertices (CCW winding).
|
||||
*
|
||||
* @param vertices Vertex array to write into (must hold stacks*sectors*6).
|
||||
* @param center Center position of the sphere.
|
||||
* @param radius Radius of the sphere.
|
||||
* @param stacks Number of horizontal rings (latitude bands).
|
||||
* @param sectors Number of vertical segments (longitude slices).
|
||||
* @param color Color applied to all vertices.
|
||||
*/
|
||||
void sphereBuffer(
|
||||
meshvertex_t *vertices,
|
||||
const vec3 center,
|
||||
const float_t radius,
|
||||
const int32_t stacks,
|
||||
const int32_t sectors
|
||||
#if MESH_ENABLE_COLOR
|
||||
, const color_t color
|
||||
#endif
|
||||
);
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "triprism.h"
|
||||
#include "assert/assert.h"
|
||||
|
||||
mesh_t TRIPRISM_MESH_SIMPLE;
|
||||
meshvertex_t TRIPRISM_MESH_SIMPLE_VERTICES[TRIPRISM_VERTEX_COUNT];
|
||||
|
||||
errorret_t triPrismInit() {
|
||||
triPrismBuffer(
|
||||
TRIPRISM_MESH_SIMPLE_VERTICES,
|
||||
0.0f, 0.0f, /* p0: bottom-left */
|
||||
1.0f, 0.0f, /* p1: bottom-right */
|
||||
0.5f, 1.0f, /* p2: apex */
|
||||
0.0f, 1.0f /* minZ, maxZ */
|
||||
#if MESH_ENABLE_COLOR
|
||||
, COLOR_WHITE_4B
|
||||
#endif
|
||||
);
|
||||
errorChain(meshInit(
|
||||
&TRIPRISM_MESH_SIMPLE,
|
||||
TRIPRISM_PRIMITIVE_TYPE,
|
||||
TRIPRISM_VERTEX_COUNT,
|
||||
TRIPRISM_MESH_SIMPLE_VERTICES
|
||||
));
|
||||
errorOk();
|
||||
}
|
||||
|
||||
void triPrismBuffer(
|
||||
meshvertex_t *vertices,
|
||||
const float_t x0, const float_t y0,
|
||||
const float_t x1, const float_t y1,
|
||||
const float_t x2, const float_t y2,
|
||||
const float_t minZ,
|
||||
const float_t maxZ
|
||||
#if MESH_ENABLE_COLOR
|
||||
, const color_t color
|
||||
#endif
|
||||
) {
|
||||
assertNotNull(vertices, "Vertices cannot be NULL");
|
||||
|
||||
/* Helper macro: write one vertex then advance index. */
|
||||
int32_t vi = 0;
|
||||
#if MESH_ENABLE_COLOR
|
||||
#define PRISM_VERT(px, py, pz, u, v) \
|
||||
vertices[vi].color = color; \
|
||||
vertices[vi].pos[0] = (px); \
|
||||
vertices[vi].pos[1] = (py); \
|
||||
vertices[vi].pos[2] = (pz); \
|
||||
vertices[vi].uv[0] = (u); \
|
||||
vertices[vi].uv[1] = (v); \
|
||||
vi++;
|
||||
#else
|
||||
#define PRISM_VERT(px, py, pz, u, v) \
|
||||
vertices[vi].pos[0] = (px); \
|
||||
vertices[vi].pos[1] = (py); \
|
||||
vertices[vi].pos[2] = (pz); \
|
||||
vertices[vi].uv[0] = (u); \
|
||||
vertices[vi].uv[1] = (v); \
|
||||
vi++;
|
||||
#endif
|
||||
|
||||
/* --- Front face (z = maxZ), CCW from +Z --- */
|
||||
PRISM_VERT(x0, y0, maxZ, 0.0f, 0.0f)
|
||||
PRISM_VERT(x1, y1, maxZ, 1.0f, 0.0f)
|
||||
PRISM_VERT(x2, y2, maxZ, 0.5f, 1.0f)
|
||||
|
||||
/* --- Back face (z = minZ), CCW from -Z (reverse winding) --- */
|
||||
PRISM_VERT(x2, y2, minZ, 0.5f, 1.0f)
|
||||
PRISM_VERT(x1, y1, minZ, 1.0f, 0.0f)
|
||||
PRISM_VERT(x0, y0, minZ, 0.0f, 0.0f)
|
||||
|
||||
/* --- Side face 0: edge p0->p1 --- */
|
||||
PRISM_VERT(x0, y0, minZ, 0.0f, 0.0f)
|
||||
PRISM_VERT(x1, y1, minZ, 1.0f, 0.0f)
|
||||
PRISM_VERT(x1, y1, maxZ, 1.0f, 1.0f)
|
||||
|
||||
PRISM_VERT(x0, y0, minZ, 0.0f, 0.0f)
|
||||
PRISM_VERT(x1, y1, maxZ, 1.0f, 1.0f)
|
||||
PRISM_VERT(x0, y0, maxZ, 0.0f, 1.0f)
|
||||
|
||||
/* --- Side face 1: edge p1->p2 --- */
|
||||
PRISM_VERT(x1, y1, minZ, 0.0f, 0.0f)
|
||||
PRISM_VERT(x2, y2, minZ, 1.0f, 0.0f)
|
||||
PRISM_VERT(x2, y2, maxZ, 1.0f, 1.0f)
|
||||
|
||||
PRISM_VERT(x1, y1, minZ, 0.0f, 0.0f)
|
||||
PRISM_VERT(x2, y2, maxZ, 1.0f, 1.0f)
|
||||
PRISM_VERT(x1, y1, maxZ, 0.0f, 1.0f)
|
||||
|
||||
/* --- Side face 2: edge p2->p0 --- */
|
||||
PRISM_VERT(x2, y2, minZ, 0.0f, 0.0f)
|
||||
PRISM_VERT(x0, y0, minZ, 1.0f, 0.0f)
|
||||
PRISM_VERT(x0, y0, maxZ, 1.0f, 1.0f)
|
||||
|
||||
PRISM_VERT(x2, y2, minZ, 0.0f, 0.0f)
|
||||
PRISM_VERT(x0, y0, maxZ, 1.0f, 1.0f)
|
||||
PRISM_VERT(x2, y2, maxZ, 0.0f, 1.0f)
|
||||
|
||||
#undef PRISM_VERT
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "display/mesh/mesh.h"
|
||||
#include "display/color.h"
|
||||
|
||||
/**
|
||||
* Vertex layout:
|
||||
* 2 triangular end-caps (3 verts each) = 6
|
||||
* 3 rectangular side faces (6 verts each) = 18
|
||||
* Total = 24
|
||||
*/
|
||||
#define TRIPRISM_VERTEX_COUNT 24
|
||||
#define TRIPRISM_PRIMITIVE_TYPE MESH_PRIMITIVE_TYPE_TRIANGLES
|
||||
|
||||
extern mesh_t TRIPRISM_MESH_SIMPLE;
|
||||
extern meshvertex_t TRIPRISM_MESH_SIMPLE_VERTICES[TRIPRISM_VERTEX_COUNT];
|
||||
|
||||
/**
|
||||
* Initializes the simple unit triangular prism. The cross-section triangle has
|
||||
* vertices (0,0), (1,0), (0.5,1) in XY, extruded from z=0 to z=1.
|
||||
*
|
||||
* @return Error for initialization of the triangular prism mesh.
|
||||
*/
|
||||
errorret_t triPrismInit();
|
||||
|
||||
/**
|
||||
* Buffers a triangular prism into the provided vertex array.
|
||||
* The triangular cross-section is defined by three 2D points in the XY plane;
|
||||
* the prism is extruded along the Z axis between minZ and maxZ.
|
||||
* Writes TRIPRISM_VERTEX_COUNT (24) vertices (CCW winding).
|
||||
*
|
||||
* @param vertices Vertex array to write into (must hold TRIPRISM_VERTEX_COUNT).
|
||||
* @param x0,y0 First triangle vertex (XY).
|
||||
* @param x1,y1 Second triangle vertex (XY).
|
||||
* @param x2,y2 Third triangle vertex (XY).
|
||||
* @param minZ Near Z extent of the prism.
|
||||
* @param maxZ Far Z extent of the prism.
|
||||
* @param color Color applied to all vertices.
|
||||
*/
|
||||
void triPrismBuffer(
|
||||
meshvertex_t *vertices,
|
||||
const float_t x0, const float_t y0,
|
||||
const float_t x1, const float_t y1,
|
||||
const float_t x2, const float_t y2,
|
||||
const float_t minZ,
|
||||
const float_t maxZ
|
||||
#if MESH_ENABLE_COLOR
|
||||
, const color_t color
|
||||
#endif
|
||||
);
|
||||
@@ -26,11 +26,11 @@ errorret_t screenInit() {
|
||||
SCREEN.frameBufferMeshVertices,
|
||||
0.0f, 0.0f,
|
||||
1.0f, 1.0f,
|
||||
#if MESH_ENABLE_COLOR
|
||||
COLOR_WHITE,
|
||||
#endif
|
||||
0.0f, 0.0f,
|
||||
1.0f, 1.0f
|
||||
#if MESH_ENABLE_COLOR
|
||||
, COLOR_WHITE
|
||||
#endif
|
||||
);
|
||||
errorChain(meshInit(
|
||||
&SCREEN.frameBufferMesh,
|
||||
@@ -363,11 +363,11 @@ errorret_t screenRender() {
|
||||
SCREEN.frameBufferMeshVertices,
|
||||
centerX - fbWidth * 0.5f, centerY + fbHeight * 0.5f, // top-left
|
||||
centerX + fbWidth * 0.5f, centerY - fbHeight * 0.5f, // bottom-right
|
||||
#if MESH_ENABLE_COLOR
|
||||
COLOR_WHITE,
|
||||
#endif
|
||||
0.0f, 0.0f,
|
||||
1.0f, 1.0f
|
||||
#if MESH_ENABLE_COLOR
|
||||
, COLOR_WHITE
|
||||
#endif
|
||||
);
|
||||
|
||||
frameBufferClear(
|
||||
|
||||
@@ -69,10 +69,10 @@ errorret_t spriteBatchPush3D(
|
||||
quadBuffer3D(
|
||||
&SPRITEBATCH_VERTICES[vertexOffset],
|
||||
min, max,
|
||||
#if MESH_ENABLE_COLOR
|
||||
color,
|
||||
#endif
|
||||
uv0, uv1
|
||||
#if MESH_ENABLE_COLOR
|
||||
, color
|
||||
#endif
|
||||
);
|
||||
SPRITEBATCH.spriteCount++;
|
||||
errorOk();
|
||||
|
||||
@@ -18,8 +18,9 @@
|
||||
#include "assert/assert.h"
|
||||
#include "entity/entitymanager.h"
|
||||
#include "game/game.h"
|
||||
#include "display/mesh/quad.h"
|
||||
|
||||
#include "display/mesh/quad.h"
|
||||
#include "display/mesh/capsule.h"
|
||||
#include "asset/loader/display/assetmeshloader.h"
|
||||
|
||||
engine_t ENGINE;
|
||||
|
||||
Reference in New Issue
Block a user