Created
July 19, 2026 08:59
-
-
Save jweinst1/218cf1692f14ac849419f100ce252654 to your computer and use it in GitHub Desktop.
rotate 3 way pyramid with indices in C++
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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