Skip to content

Instantly share code, notes, and snippets.

@jweinst1
Created July 19, 2026 08:59
Show Gist options
  • Select an option

  • Save jweinst1/218cf1692f14ac849419f100ce252654 to your computer and use it in GitHub Desktop.

Select an option

Save jweinst1/218cf1692f14ac849419f100ce252654 to your computer and use it in GitHub Desktop.
rotate 3 way pyramid with indices in C++
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <cmath>
struct Vec3 {
float x, y, z;
};
typedef struct {
Vec3 position;
SDL_FColor color;
} LocalVertex3D;
static constexpr LocalVertex3D BLUEPRINT[] = {
// red
{ { 0.0f, -100.0f, 0.0f }, {1.0f, 0.0f, 0.0f, 1.0f} }, // A: Top Tip
{ { -100.f, 0.0f, -100.0f }, {1.0f, 0.0f, 0.0f, 1.0f} }, // C: Bottom Left-Front
{ { 100.f, 0.0f, -100.0f }, {1.0f, 0.0f, 0.0f, 1.0f} }, // B: Bottom Right-Front
// green
{ { 0.0f, -100.0f, 0.0f }, {0.0f, 1.0f, 0.0f, 1.0f} },
{ { 100.f, 0.0f, -100.0f }, {0.0f, 1.0f, 0.0f, 1.0f} },
{ { 0.0f, 0.0f, 100.0f }, {0.0f, 1.0f, 0.0f, 1.0f} },
// blue
{ { 0.0f, -100.0f, 0.0f }, {0.0f, 0.0f, 1.0f, 1.0f} },
{ { -100.f, 0.0f, -100.0f }, {0.0f, 0.0f, 1.0f, 1.0f} },
{ { 0.0f, 0.0f, 100.0f }, {0.0f, 0.0f, 1.0f, 1.0f} }
};
static constexpr size_t vertLen = sizeof(BLUEPRINT) / sizeof(BLUEPRINT[0]);
static constexpr size_t triangleLen = vertLen / 3;
Vec3 RotatePointY(const Vec3& point, float angle_radians) {
float cosAng = cosf(angle_radians);
float sinAng = sinf(angle_radians);
Vec3 rotated;
rotated.x = (point.x * cosAng) - (point.z * sinAng);
rotated.y = point.y;
rotated.z = (point.x * sinAng) + (point.z * cosAng);
return rotated;
}
void UpdateGeometry3D(SDL_Vertex* target, const LocalVertex3D* source, int count,
float objX, float objY, float objZ,
float rotationAngle,
float screenWidth, float screenHeight, float* zScores)
{
float centerX = screenWidth / 2.0f;
float centerY = screenHeight / 2.0f;
float focalLength = screenWidth * 0.8f;
for (int i = 0; i < count; i++) {
Vec3 localPos = source[i].position;
Vec3 rotatedPos = RotatePointY(localPos, rotationAngle);
float worldX = rotatedPos.x + objX;
float worldY = rotatedPos.y + objY;
float worldZ = rotatedPos.z + objZ;
zScores[i] = worldZ;
if (worldZ < 10.0f) worldZ = 10.0f;
target[i].position.x = (worldX / worldZ) * focalLength + centerX;
target[i].position.y = (worldY / worldZ) * focalLength + centerY;
target[i].color = source[i].color;
}
}
int main(int argc, char *argv[])
{
bool quit = false;
SDL_Window *window = SDL_CreateWindow("Backface Culling Cube", 800, 600, 0);
SDL_Renderer *renderer = SDL_CreateRenderer(window, NULL);
float cubeX = 0.0f;
float cubeY = 0.0f;
float cubeZ = 500.0f;
float cubeRotation = 0.0f;
while (!quit) {
SDL_Event ev;
while (SDL_PollEvent(&ev) != 0) {
if (ev.type == SDL_EVENT_QUIT) {
quit = true;
}
}
SDL_Vertex verts[vertLen];
int indicesToUse[vertLen];
float zScores[vertLen] = {0.0f};
SDL_SetRenderDrawColor(renderer, 20, 20, 30, 255);
SDL_RenderClear(renderer);
// 1. Process all 3D coordinates into 2D screen positions
UpdateGeometry3D(verts, BLUEPRINT, vertLen, cubeX, cubeY, cubeZ, cubeRotation, 800.0f, 600.0f, zScores);
float zTotalScores[triangleLen];
zTotalScores[0] = zScores[0] + zScores[1] + zScores[2];
zTotalScores[1] = zScores[3] + zScores[4] + zScores[5];
zTotalScores[2] = zScores[6] + zScores[7] + zScores[8];
if (zTotalScores[0] > zTotalScores[1] && zTotalScores[0] > zTotalScores[2]) {
indicesToUse[0] = 0;
indicesToUse[1] = 1;
indicesToUse[2] = 2;
if (zTotalScores[1] > zTotalScores[2]) {
indicesToUse[3] = 3;
indicesToUse[4] = 4;
indicesToUse[5] = 5;
indicesToUse[6] = 6;
indicesToUse[7] = 7;
indicesToUse[8] = 8;
} else {
indicesToUse[3] = 6;
indicesToUse[4] = 7;
indicesToUse[5] = 8;
indicesToUse[6] = 3;
indicesToUse[7] = 4;
indicesToUse[8] = 5;
}
} else if (zTotalScores[1] > zTotalScores[0] && zTotalScores[1] > zTotalScores[2]) {
indicesToUse[0] = 3;
indicesToUse[1] = 4;
indicesToUse[2] = 5;
if (zTotalScores[0] > zTotalScores[2]) {
indicesToUse[3] = 0;
indicesToUse[4] = 1;
indicesToUse[5] = 2;
indicesToUse[6] = 6;
indicesToUse[7] = 7;
indicesToUse[8] = 8;
} else {
indicesToUse[3] = 6;
indicesToUse[4] = 7;
indicesToUse[5] = 8;
indicesToUse[6] = 0;
indicesToUse[7] = 1;
indicesToUse[8] = 2;
}
} else {
indicesToUse[0] = 6;
indicesToUse[1] = 7;
indicesToUse[2] = 8;
if (zTotalScores[0] > zTotalScores[1]) {
indicesToUse[3] = 0;
indicesToUse[4] = 1;
indicesToUse[5] = 2;
indicesToUse[6] = 3;
indicesToUse[7] = 4;
indicesToUse[8] = 5;
} else {
indicesToUse[3] = 3;
indicesToUse[4] = 4;
indicesToUse[5] = 5;
indicesToUse[6] = 0;
indicesToUse[7] = 1;
indicesToUse[8] = 2;
}
}
SDL_RenderGeometry(renderer, NULL, verts, vertLen, indicesToUse, vertLen);
cubeRotation += 0.02f;
SDL_RenderPresent(renderer);
SDL_Delay(16);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment