pctm + foundation for obj models
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
#ifndef DELTA_ASSETLOADER
|
||||
#define DELTA_ASSETLOADER
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "math.hpp"
|
||||
|
||||
struct SDL_SurfaceDeleter {
|
||||
void operator()(SDL_Surface* surface) const {
|
||||
if (surface) {
|
||||
SDL_DestroySurface(surface);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class DeltaAssetLoader {
|
||||
public:
|
||||
~DeltaAssetLoader() {
|
||||
for (auto& [id, surface] : textures) {
|
||||
SDL_DestroySurface(surface);
|
||||
}
|
||||
}
|
||||
|
||||
void loadTexture(std::string id, const char *path);
|
||||
void loadModel(std::string id, const char *path);
|
||||
SDL_Surface* getSurface(const std::string& id);
|
||||
void getModel(std::string id, const char *path);
|
||||
private:
|
||||
std::string base_path = "assets";
|
||||
std::string img_path = "images";
|
||||
std::string model_path = "models";
|
||||
|
||||
std::unordered_map<std::string, SDL_Surface*> textures;
|
||||
std::unordered_map<std::string, DeltaModel> models;
|
||||
};
|
||||
|
||||
#endif
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
#ifndef DELTA_GLOBALS
|
||||
#define DELTA_GLOBALS
|
||||
|
||||
const int SIMULATED_WIDTH = 800;
|
||||
const int SIMULATED_HEIGHT = 600;
|
||||
const int SIMULATED_WIDTH = 1200;
|
||||
const int SIMULATED_HEIGHT = 800;
|
||||
const int FOCAL = 300;
|
||||
|
||||
#endif
|
||||
+26
-7
@@ -1,6 +1,8 @@
|
||||
#ifndef DELTA_MATH
|
||||
#define DELTA_MATH
|
||||
|
||||
#include <vector>
|
||||
|
||||
class DeltaVector2 {
|
||||
public:
|
||||
float x, y;
|
||||
@@ -35,9 +37,6 @@ class DeltaVector3 {
|
||||
float length() const;
|
||||
};
|
||||
|
||||
float getDeterminant(const DeltaVector2 &pointA, const DeltaVector2 &pointB, const DeltaVector2 &candidate);
|
||||
DeltaVector2 barycentricToScreen(const DeltaVector3 &baryPoint, const DeltaVector2 &a, const DeltaVector2 &b, const DeltaVector2 &c);
|
||||
DeltaVector3 intersect(DeltaVector3 a, DeltaVector3 b, float nearZ);
|
||||
|
||||
struct DeltaTriangle {
|
||||
DeltaVector3 a, b, c;
|
||||
@@ -47,14 +46,34 @@ struct DeltaTriangle2D {
|
||||
DeltaVector2 a, b, c;
|
||||
};
|
||||
|
||||
|
||||
struct DeltaRenderTriangle {
|
||||
DeltaVector3 a, b, c;
|
||||
DeltaVector2 uva, uvb, uvc;
|
||||
struct DeltaVertex {
|
||||
DeltaVector3 pos;
|
||||
DeltaVector2 uv;
|
||||
};
|
||||
|
||||
struct DeltaModelConnector {
|
||||
int ind1, ind2;
|
||||
};
|
||||
|
||||
struct DeltaRenderTriangle {
|
||||
DeltaVertex a, b, c;
|
||||
bool invert;
|
||||
};
|
||||
|
||||
struct DeltaModel {
|
||||
std::vector<DeltaVertex> vertexes;
|
||||
std::vector<DeltaModelConnector> lines;
|
||||
std::vector<DeltaRenderTriangle> triangles;
|
||||
};
|
||||
|
||||
|
||||
float getDeterminant(const DeltaVector2 &pointA, const DeltaVector2 &pointB, const DeltaVector2 &candidate);
|
||||
DeltaVector2 barycentricToScreen(const DeltaVector3 &baryPoint, const DeltaVector2 &a, const DeltaVector2 &b, const DeltaVector2 &c);
|
||||
DeltaVertex intersect(DeltaVertex a, DeltaVertex b, float nearZ);
|
||||
int clipTriangleAgainstNearPlane(float nearY, const DeltaRenderTriangle &in, DeltaRenderTriangle &out1, DeltaRenderTriangle &out2);
|
||||
|
||||
std::vector<DeltaTriangle2D> triangulatePolygon(std::vector<DeltaVertex>& points);
|
||||
|
||||
uint32_t SDLColorToUint32(SDL_Color color);
|
||||
|
||||
#endif
|
||||
@@ -4,9 +4,11 @@
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include "math.hpp"
|
||||
#include "assetloader.hpp"
|
||||
|
||||
void rasterizeTriangle(SDL_Renderer *renderer, const DeltaVector2 &a, const DeltaVector2 &b, const DeltaVector2 &c);
|
||||
// void rasterizeTriangle(SDL_Renderer *renderer, const DeltaVector2 &a, const DeltaVector2 &b, const DeltaVector2 &c);
|
||||
void rasterizeTriangleFast(SDL_Surface* surface, const DeltaVector2& v0, const DeltaVector2& v1, const DeltaVector2& v2, uint32_t color);
|
||||
void rasterizeTriangleSurface(SDL_Surface* surface, const DeltaVector2& v0, const DeltaVector2& v1, const DeltaVector2& v2, uint32_t color, float u0, float v0_uv, float u1, float v1_uv, float u2, float v2_uv);
|
||||
void rasterizeTriangleSurface(DeltaAssetLoader& assets, std::vector<float>& depthbuffer, SDL_Surface* surface, const DeltaVector3& v0, const DeltaVector3& v1, const DeltaVector3& v2, const std::string& textureID, float u0, float v0_uv, float u1, float v1_uv, float u2, float v2_uv);
|
||||
void setPixel(SDL_Surface* surface, int x, int y, uint32_t color);
|
||||
uint32_t getPixel(SDL_Surface* surface, int x, int y);
|
||||
#endif
|
||||
@@ -11,9 +11,9 @@ class DeltaCamera {
|
||||
DeltaCamera() {pos = DeltaVector3(); angle = DeltaVector2();};
|
||||
DeltaCamera(float x, float y, float z);
|
||||
DeltaVector3 translatePoint(const DeltaVector3 &worldPos);
|
||||
DeltaVector2 projectPointVec(const DeltaVector3 &worldPos);
|
||||
int projectTriangle(const DeltaTriangle &in, DeltaTriangle2D &out1, DeltaTriangle2D &out2);
|
||||
DeltaVector2 projectPoint(float worldX, float worldY, float worldZ);
|
||||
DeltaVector3 projectPointVec(const DeltaVector3 &worldPos);
|
||||
int projectTriangle(const DeltaRenderTriangle &in, DeltaTriangle &out1, DeltaTriangle &out2, DeltaTriangle2D &uv1, DeltaTriangle2D &uv2);
|
||||
DeltaVector3 projectPoint(float worldX, float worldY, float worldZ);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
g++ -c src/*.cpp -O3 -ffast-math -IC:\\common\include -Iinclude/
|
||||
g++ -c src/renderer/*.cpp -O3 -ffast-math -IC:\\common\include -Iinclude/
|
||||
g++ -c src/math/*.cpp -O3 -ffast-math -IC:\\common\include -Iinclude/
|
||||
g++ *.o -LC:\\common\lib -lSDL3 -mwindows -o out\release.exe
|
||||
del .\*.o
|
||||
echo release version built. available as ./out/release.exe
|
||||
@@ -1,5 +1,8 @@
|
||||
g++ -c src/*.cpp -IC:\\common\include -Iinclude/
|
||||
g++ -c src/renderer/*.cpp -IC:\\common\include -Iinclude/
|
||||
g++ -c src/math/*.cpp -IC:\\common\include -Iinclude/
|
||||
g++ *.o -LC:\\common\lib -lSDL3 -o out\debug.exe
|
||||
del .\*.o
|
||||
.\out\debug.exe
|
||||
cd .\out\
|
||||
.\debug.exe
|
||||
cd ..
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 880 B |
@@ -0,0 +1,4 @@
|
||||
newmtl FrontColor
|
||||
Ka 0.000000 0.000000 0.000000
|
||||
Kd 1.000000 1.000000 1.000000
|
||||
Ks 0.330000 0.330000 0.330000
|
||||
@@ -0,0 +1,28 @@
|
||||
#include <SDL3/SDL.h>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "assetloader.hpp"
|
||||
|
||||
void DeltaAssetLoader::loadTexture(std::string id, const char* path) {
|
||||
std::string fullPath = base_path + "\\" + img_path + "\\" + path;
|
||||
SDL_Surface* surface = SDL_LoadPNG(fullPath.c_str());
|
||||
if (!surface) {
|
||||
SDL_Log(SDL_GetError());
|
||||
}
|
||||
|
||||
if (surface) {
|
||||
SDL_Surface* optimized = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ARGB8888);
|
||||
SDL_DestroySurface(surface);
|
||||
|
||||
if (textures.count(id)) SDL_DestroySurface(textures[id]);
|
||||
textures[id] = optimized;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Surface* DeltaAssetLoader::getSurface(const std::string& id) {
|
||||
auto it = textures.find(id);
|
||||
return (it != textures.end()) ? it->second : nullptr;
|
||||
}
|
||||
+40
-23
@@ -13,6 +13,7 @@
|
||||
#include "renderer/camera.hpp"
|
||||
#include "renderer/calls.hpp"
|
||||
#include "player.hpp"
|
||||
#include "assetloader.hpp"
|
||||
|
||||
static SDL_Window *window = NULL;
|
||||
static SDL_Renderer *renderer = NULL;
|
||||
@@ -23,10 +24,13 @@ DeltaVector2 topleft, bottomright, p;
|
||||
Player player = Player(200, -200, 20);
|
||||
double prev = 0, now = 0, deltaTime;
|
||||
SDL_Surface* backbuffer = NULL;
|
||||
std::vector<float> depthbuffer;
|
||||
|
||||
std::vector<DeltaRenderTriangle> triangles;
|
||||
SDL_Texture* gpuTexture = NULL;
|
||||
|
||||
DeltaAssetLoader assets;
|
||||
|
||||
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
{
|
||||
SDL_HideCursor();
|
||||
@@ -37,7 +41,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
if (!SDL_CreateWindowAndRenderer("game", SIMULATED_WIDTH, SIMULATED_HEIGHT, 0, &window, &renderer)) {
|
||||
if (!SDL_CreateWindowAndRenderer("game", SIMULATED_WIDTH, SIMULATED_HEIGHT, SDL_WINDOW_FULLSCREEN, &window, &renderer)) {
|
||||
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
@@ -46,9 +50,27 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
|
||||
SDL_SetRenderLogicalPresentation(renderer, SIMULATED_WIDTH, SIMULATED_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX);
|
||||
|
||||
triangles.push_back({ {40, 10, 200}, {40, 210, 0}, {40, 10, 0} , {0, 0}, {1, 1}, {0, 1}});
|
||||
triangles.push_back({ {40, 210, 200}, {40, 210, 0}, {40, 10, 200}, {1, 0}, {1, 1}, {0, 0} });
|
||||
// SDL_SetHint(SDL_HINT_RENDER_DEFAULT, "0");
|
||||
|
||||
// delta shenanigans
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
triangles.push_back({ {{40 - i * 200.0f, 10, 200}, {0, 0}} , {{40 - i * 200.0f, 210, 0}, {1, 1}}, {{40 - i * 200.0f, 10, 0}, {0, 1}}});
|
||||
triangles.push_back({ {{40 - i * 200.0f, 210, 200}, {1, 0}}, {{40 - i * 200.0f, 210, 0}, {1, 1}}, {{40 - i * 200.0f, 10, 200}, {0, 0}} });
|
||||
}
|
||||
|
||||
// triangles.push_back({ {{10, 10, 200}, {0, 0}} , {{10, 410, 0}, {2, 1}}, {{10, 10, 0}, {0, 1}} , false});
|
||||
// triangles.push_back({ {{10, 410, 200}, {2, 0}}, {{10, 410, 0}, {2, 1}}, {{10, 10, 200}, {0, 0}} , false});
|
||||
// triangles.push_back({ {{410, 10, 0}, {0, 1}} , {{410, 410, 0}, {2, 1}}, {{410, 10, 200}, {0, 0}} , true});
|
||||
// triangles.push_back({ {{410, 10, 200}, {0, 0}}, {{410, 410, 0}, {2, 1}}, {{410, 410, 200}, {2, 0}} , true});
|
||||
// triangles.push_back({ {{10, 410, 200}, {0, 0}} , {{410, 410, 0}, {2, 1}}, {{10, 410, 0}, {0, 1}} , true});
|
||||
// triangles.push_back({ {{10, 410, 200}, {0, 0}}, {{410, 410, 200}, {2, 0}}, {{410, 410, 0}, {2, 1}} , true});
|
||||
// triangles.push_back({ {{10, 10, 200}, {0, 0}} , {{10, 10, 0}, {0, 1}}, {{410, 10, 0}, {2, 1}} , true});
|
||||
// triangles.push_back({ {{410, 10, 200}, {2, 0}} , {{10, 10, 200}, {0, 0}}, {{410, 10, 0}, {2, 1}} , true});
|
||||
|
||||
|
||||
backbuffer = SDL_CreateSurface(SIMULATED_WIDTH, SIMULATED_HEIGHT, SDL_PIXELFORMAT_ARGB8888);
|
||||
depthbuffer.resize(SIMULATED_WIDTH * SIMULATED_HEIGHT);
|
||||
gpuTexture = SDL_CreateTexture(
|
||||
renderer,
|
||||
SDL_PIXELFORMAT_ARGB8888,
|
||||
@@ -57,6 +79,10 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
SIMULATED_HEIGHT
|
||||
);
|
||||
|
||||
SDL_SetTextureScaleMode(gpuTexture, SDL_SCALEMODE_NEAREST);
|
||||
|
||||
assets.loadTexture("stonebricks", "stone.png");
|
||||
|
||||
SDL_SetRenderVSync(renderer, 1);
|
||||
|
||||
return SDL_APP_CONTINUE; /* carry on with the program! */
|
||||
@@ -93,17 +119,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
|
||||
|
||||
SDL_FillSurfaceRect(backbuffer, NULL, 0xFF000000);
|
||||
|
||||
// SDL_SetRenderDrawColor(renderer, 255, 0, 255, SDL_ALPHA_OPAQUE);
|
||||
// rasterizeTriangle(renderer, temp1, temp2, temp3);
|
||||
|
||||
// DeltaVector2 rendered = player.camera.projectPointVec({ 40, 10, 30 });
|
||||
// SDL_RenderPoint(renderer, rendered.x, rendered.y);
|
||||
// rendered = player.camera.projectPointVec({ 40, 210, 30 });
|
||||
// SDL_RenderPoint(renderer, rendered.x, rendered.y);
|
||||
// rendered = player.camera.projectPointVec({ 40, 10, -170 });
|
||||
// SDL_RenderPoint(renderer, rendered.x, rendered.y);
|
||||
// rendered = player.camera.projectPointVec({ 40, 210, -170 });
|
||||
// SDL_RenderPoint(renderer, rendered.x, rendered.y);
|
||||
std::fill(depthbuffer.begin(), depthbuffer.end(), 0.0f);
|
||||
|
||||
if (SDL_MUSTLOCK(backbuffer)) {
|
||||
SDL_LockSurface(backbuffer);
|
||||
@@ -112,23 +128,24 @@ SDL_AppResult SDL_AppIterate(void *appstate)
|
||||
DeltaTriangle triangle1, triangle2;
|
||||
for (auto triangle : triangles) {
|
||||
// DeltaVector2 pointA = player.camera.projectPointVec(triangle.a), pointB = player.camera.projectPointVec(triangle.b), pointC = player.camera.projectPointVec(triangle.c);
|
||||
DeltaTriangle2D out1, out2;
|
||||
DeltaTriangle out1, out2;
|
||||
DeltaTriangle2D uv1, uv2;
|
||||
|
||||
int numtriangles = player.camera.projectTriangle({ triangle.a, triangle.b, triangle.c }, out1, out2);
|
||||
int numtriangles = player.camera.projectTriangle(triangle, out1, out2, uv1, uv2);
|
||||
// SDL_Log(std::to_string(numtriangles).c_str());
|
||||
if (numtriangles == 1) {
|
||||
// rasterizeTriangleFast(backbuffer, out1.a, out1.b, out1.c, SDLColorToUint32({ 255, 0, 0, 255 }));
|
||||
// rasterizeTriangleFast(backbuffer, out1.c, out1.b, out1.a, SDLColorToUint32({ 0, 0, 255, 255 }));
|
||||
rasterizeTriangleSurface(backbuffer, out1.a, out1.b, out1.c, SDLColorToUint32({ 0, 255, 0, 255 }), triangle.uva.x, triangle.uva.y, triangle.uvb.x, triangle.uvb.y, triangle.uvc.x, triangle.uvc.y);
|
||||
// rasterizeTriangleFast(backbuffer, out1.a, out1.b, out1.c, SDLColorToUint32({ 0, 0, 255, 255 }));
|
||||
rasterizeTriangleSurface(assets, depthbuffer, backbuffer, out1.a, out1.b, out1.c, "stonebricks", uv1.a.x, uv1.a.y, uv1.b.x, uv1.b.y, uv1.c.x, uv1.c.y);
|
||||
// SDL_Log(std::to_string(triangle.a.y).c_str());
|
||||
// SDL_Log(std::to_string(triangle.b.y).c_str());
|
||||
// SDL_Log(std::to_string(triangle.c.y).c_str());
|
||||
}
|
||||
if (numtriangles == 2) {
|
||||
// rasterizeTriangleFast(backbuffer, out1.a, out1.b, out1.c, SDLColorToUint32({ 255, 0, 0, 255 }));
|
||||
rasterizeTriangleSurface(backbuffer, out1.a, out1.b, out1.c, SDLColorToUint32({ 0, 255, 0, 255 }), triangle.uva.x, triangle.uva.y, triangle.uvb.x, triangle.uvb.y, triangle.uvc.x, triangle.uvc.y);
|
||||
rasterizeTriangleSurface(assets, depthbuffer, backbuffer, out1.a, out1.b, out1.c, "stonebricks", uv1.a.x, uv1.a.y, uv1.b.x, uv1.b.y, uv1.c.x, uv1.c.y);
|
||||
// rasterizeTriangleFast(backbuffer, out1.c, out1.b, out1.a, SDLColorToUint32({ 0, 255, 0, 255 }));
|
||||
rasterizeTriangleSurface(backbuffer, out2.a, out2.b, out2.c, SDLColorToUint32({ 0, 255, 0, 255 }), triangle.uva.x, triangle.uva.y, triangle.uvb.x, triangle.uvb.y, triangle.uvc.x, triangle.uvc.y);
|
||||
rasterizeTriangleSurface(assets, depthbuffer, backbuffer, out2.a, out2.b, out2.c, "stonebricks", uv2.a.x, uv2.a.y, uv2.b.x, uv2.b.y, uv2.c.x, uv2.c.y);
|
||||
}
|
||||
|
||||
// int intersected = clipTriangleAgainstNearPlane(0.1, { triangle.a, triangle.b, triangle.c }, triangle1, triangle2);
|
||||
@@ -139,7 +156,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
|
||||
// rasterizeTriangleFast(backbuffer, pointA, pointB, pointC, SDLColorToUint32({ 255, 0, 0, 255 }));
|
||||
// SDL_Log("===");
|
||||
}
|
||||
SDL_Log("=====");
|
||||
// SDL_Log("=====");
|
||||
|
||||
if (SDL_MUSTLOCK(backbuffer)) {
|
||||
SDL_UnlockSurface(backbuffer);
|
||||
@@ -153,7 +170,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
|
||||
|
||||
SDL_UpdateTexture(gpuTexture, NULL, backbuffer->pixels, backbuffer->pitch);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
|
||||
SDL_SetRenderDrawColor(renderer, 64, 64, 64, 255);
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_RenderTexture(renderer, gpuTexture, NULL, NULL);
|
||||
|
||||
@@ -166,6 +183,6 @@ SDL_AppResult SDL_AppIterate(void *appstate)
|
||||
|
||||
void SDL_AppQuit(void *appstate, SDL_AppResult result)
|
||||
{
|
||||
|
||||
SDL_Log(SDL_GetError());
|
||||
}
|
||||
|
||||
|
||||
+25
-44
@@ -122,61 +122,41 @@ uint32_t SDLColorToUint32(SDL_Color color) {
|
||||
return (uint32_t)((color.a << 24) | (color.r << 16) | (color.g << 8) | (color.b << 0));
|
||||
}
|
||||
|
||||
DeltaVector3 intersect(DeltaVector3 a, DeltaVector3 b, float nearZ) {
|
||||
if (std::abs(b.y - a.y) < 0.0001f) {
|
||||
SDL_Log("IMAGINEEEE");
|
||||
DeltaVertex intersect(DeltaVertex a, DeltaVertex b, float nearZ) {
|
||||
if (std::abs(b.pos.y - a.pos.y) < 0.0001f) {
|
||||
return a;
|
||||
}
|
||||
|
||||
float t = (nearZ - a.y) / (b.y - a.y);
|
||||
return DeltaVector3(
|
||||
a.x + t * (b.x - a.x),
|
||||
float t = (nearZ - a.pos.y) / (b.pos.y - a.pos.y);
|
||||
|
||||
return {
|
||||
{a.pos.x + t * (b.pos.x - a.pos.x),
|
||||
nearZ,
|
||||
a.z + t * (b.z - a.z)
|
||||
);
|
||||
a.pos.z + t * (b.pos.z - a.pos.z)},
|
||||
{a.uv.x + t * (b.uv.x - a.uv.x),
|
||||
a.uv.y + t * (b.uv.y - a.uv.y)}
|
||||
};
|
||||
}
|
||||
|
||||
DeltaVector2 intersectUV(DeltaVector3 a, DeltaVector3 b, DeltaVector2 uv1, DeltaVector2 uv2, float nearZ) {
|
||||
if (std::abs(b.y - a.y) < 0.0001f) {
|
||||
return uv1;
|
||||
}
|
||||
|
||||
float t = (nearZ - a.y) / (b.y - a.y);
|
||||
return {
|
||||
uv1.x + t * (uv2.x - uv1.x),
|
||||
uv1.y + t * (uv2.y - uv1.y)
|
||||
};
|
||||
}
|
||||
|
||||
int clipTriangleAgainstNearPlane(float nearY, const DeltaRenderTriangle &in, DeltaRenderTriangle &out1, DeltaRenderTriangle &out2) {
|
||||
// DeltaVector3 inside[3], outside[3];
|
||||
// DeltaVector3 cur;
|
||||
// int nIn = 0, nOut = 0;
|
||||
|
||||
// for (int i = 0; i < 3; i++) {
|
||||
// if (i == 0) cur = in.a;
|
||||
// else if (i == 1) cur = in.b;
|
||||
// else cur = in.c;
|
||||
// if (cur.y > 0.1f) inside[nIn++] = cur;
|
||||
// else outside[nOut++] = cur;
|
||||
// }
|
||||
|
||||
// if (nIn == 0) return 0;
|
||||
// if (nIn == 3) { out1 = in; return 1; }
|
||||
|
||||
// if (nIn == 1) {
|
||||
// out1.c = inside[0];
|
||||
// out1.b = intersect(inside[0], outside[0], nearZ);
|
||||
// out1.a = intersect(inside[0], outside[1], nearZ);
|
||||
// return 1;
|
||||
// }
|
||||
|
||||
// if (nIn == 2) {
|
||||
// out1.a = inside[0];
|
||||
// out1.b = inside[1];
|
||||
// out1.c = intersect(inside[1], outside[0], nearZ);
|
||||
|
||||
// out2.a = inside[0];
|
||||
// out2.b = out1.a;
|
||||
// out2.c = intersect(outside[0], inside[0], nearZ);
|
||||
|
||||
// return 2;
|
||||
// }
|
||||
|
||||
const DeltaVector3* v[3] = { &in.a, &in.b, &in.c };
|
||||
const DeltaVertex* v[3] = { &in.a, &in.b, &in.c };
|
||||
bool inside[3];
|
||||
int insideCount = 0;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
inside[i] = (v[i]->y >= nearY);
|
||||
inside[i] = (v[i]->pos.y >= nearY);
|
||||
if (inside[i]) insideCount++;
|
||||
}
|
||||
|
||||
@@ -192,6 +172,7 @@ int clipTriangleAgainstNearPlane(float nearY, const DeltaRenderTriangle &in, Del
|
||||
out1.a = *v[i0];
|
||||
out1.b = intersect(*v[i0], *v[i1], nearY);
|
||||
out1.c = intersect(*v[i0], *v[i2], nearY);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <SDL3/SDL.h>
|
||||
#include <cmath>
|
||||
#include <float.h>
|
||||
|
||||
#include "math.hpp"
|
||||
|
||||
// std::vector<DeltaTriangle2D> triangulatePolygon(std::vector<DeltaVertex>& points) {
|
||||
// DeltaVertex v0 = points
|
||||
// }
|
||||
+57
-86
@@ -1,9 +1,11 @@
|
||||
#include <SDL3/SDL.h>
|
||||
#include <algorithm>
|
||||
#include <smmintrin.h>
|
||||
#include <string>
|
||||
|
||||
#include "globals.hpp"
|
||||
#include "renderer/calls.hpp"
|
||||
#include "assetloader.hpp"
|
||||
|
||||
void setPixel(SDL_Surface* surface, int x, int y, uint32_t color) {
|
||||
// 1. Boundary check to prevent memory corruption (Crashes)
|
||||
@@ -15,12 +17,25 @@ void setPixel(SDL_Surface* surface, int x, int y, uint32_t color) {
|
||||
*(uint32_t*)pixel_ptr = color;
|
||||
}
|
||||
|
||||
void rasterizeTriangleSurface(SDL_Surface* surface, const DeltaVector2& v0, const DeltaVector2& v1, const DeltaVector2& v2, uint32_t color, float u0, float v0_uv, float u1, float v1_uv, float u2, float v2_uv) {
|
||||
uint32_t getPixel(SDL_Surface* surface, int x, int y) {
|
||||
// Check bounds! (Important for 3D clipping)
|
||||
if (x < 0 || x >= surface->w || y < 0 || y >= surface->h) return 0;
|
||||
|
||||
// Pitch is in bytes, so we divide by 4 to get 'pitch in uint32_ts'
|
||||
uint32_t* pixels = (uint32_t*)surface->pixels;
|
||||
int pitchInWords = surface->pitch / 4;
|
||||
|
||||
return pixels[y * pitchInWords + x];
|
||||
}
|
||||
|
||||
void rasterizeTriangleSurface(DeltaAssetLoader& assets, std::vector<float>& depthbuffer, SDL_Surface* surface, const DeltaVector3& v0, const DeltaVector3& v1, const DeltaVector3& v2, const std::string& textureID, float u0, float v0_uv, float u1, float v1_uv, float u2, float v2_uv) {
|
||||
int minX = std::max(0, (int)std::min({v0.x, v1.x, v2.x}));
|
||||
int maxX = std::min((int)surface->w - 1, (int)std::max({v0.x, v1.x, v2.x}));
|
||||
int minY = std::max(0, (int)std::min({v0.y, v1.y, v2.y}));
|
||||
int maxY = std::min((int)surface->h - 1, (int)std::max({v0.y, v1.y, v2.y}));
|
||||
|
||||
SDL_Surface* textureOrigin = assets.getSurface(textureID);
|
||||
|
||||
// precompute edge coefficients
|
||||
// edge function: E(x, y) = (v_i.y - v_j.y)x + (v_j.x - v_i.x)y + (v_i.x * v_j.y - v_j.x * v_i.y)
|
||||
float a0 = v1.y - v2.y, b0 = v2.x - v1.x, c0 = v1.x * v2.y - v2.x * v1.y;
|
||||
@@ -37,7 +52,19 @@ void rasterizeTriangleSurface(SDL_Surface* surface, const DeltaVector2& v0, cons
|
||||
float invArea = 1.0f / area;
|
||||
|
||||
uint32_t* pixels = (uint32_t*)surface->pixels;
|
||||
uint32_t* texpixels = (uint32_t*)textureOrigin->pixels;
|
||||
int pitch = surface->pitch / sizeof(uint32_t);
|
||||
int pitchInWords = textureOrigin->pitch / 4;
|
||||
|
||||
float iw0 = 1.0f / v0.z;
|
||||
float iw1 = 1.0f / v1.z;
|
||||
float iw2 = 1.0f / v2.z;
|
||||
|
||||
float pu0 = u0 * iw0, pv0 = v0_uv * iw0;
|
||||
float pu1 = u1 * iw1, pv1 = v1_uv * iw1;
|
||||
float pu2 = u2 * iw2, pv2 = v2_uv * iw2;
|
||||
|
||||
int texW = textureOrigin->w, texH = textureOrigin->h;
|
||||
|
||||
// main raster loop
|
||||
for (int y = minY; y <= maxY; y++) {
|
||||
@@ -54,14 +81,37 @@ void rasterizeTriangleSurface(SDL_Surface* surface, const DeltaVector2& v0, cons
|
||||
float w1 = e1 * invArea;
|
||||
float w2 = e2 * invArea;
|
||||
|
||||
float u = w0 * u0 + w1 * u1 + w2 * u2;
|
||||
float v = w0 * v0_uv + w1 * v1_uv + w2 * v2_uv;
|
||||
// 2. interpolate the 1/w and the u/w, v/w
|
||||
float interW = w0 * iw0 + w1 * iw1 + w2 * iw2;
|
||||
float interU = w0 * pu0 + w1 * pu1 + w2 * pu2;
|
||||
float interV = w0 * pv0 + w1 * pv1 + w2 * pv2;
|
||||
|
||||
uint8_t r = (uint8_t)(u * 255.0f);
|
||||
uint8_t g = (uint8_t)(v * 255.0f);
|
||||
uint8_t b = 128;
|
||||
int pixelInd = y * surface->w + x;
|
||||
if (interW > depthbuffer[pixelInd]) {
|
||||
depthbuffer[pixelInd] = interW;
|
||||
|
||||
float realInvW = 1.0f / interW;
|
||||
float u = interU * realInvW;
|
||||
float v = interV * realInvW;
|
||||
|
||||
// uint8_t r = (uint8_t)(u * textureOrigin->w);
|
||||
// uint8_t g = (uint8_t)(v * textureOrigin->h);
|
||||
// uint8_t b = 128;
|
||||
|
||||
// texpixels[y * pitchInWords + x];
|
||||
|
||||
int tx = (int)(u * texW) & (texW - 1);
|
||||
int ty = (int)(v * texH) & (texH - 1);
|
||||
|
||||
// tx %= texW;
|
||||
// ty %= texH;
|
||||
|
||||
// rowPtr[x] = SDL_MapRGB(SDL_GetPixelFormatDetails(surface->format), NULL, (uint8_t)(u * 255), (uint8_t)(v * 255), 0); //getPixel(textureOrigin, (int)(u * textureOrigin->w), (int)(v * textureOrigin->h));
|
||||
// rowPtr[x] = getPixel(textureOrigin, (int)(u * textureOrigin->w) % textureOrigin->w, (int)(v * textureOrigin->h) % textureOrigin->h);
|
||||
// (int)(u * textureOrigin->w) & (textureOrigin->w - 1)
|
||||
rowPtr[x] = texpixels[ty * pitchInWords + tx];
|
||||
}
|
||||
|
||||
rowPtr[x] = (255 << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
// step horizontally: just 3 additions
|
||||
@@ -77,55 +127,6 @@ void rasterizeTriangleSurface(SDL_Surface* surface, const DeltaVector2& v0, cons
|
||||
}
|
||||
}
|
||||
|
||||
void rasterizeTriangle(SDL_Renderer *renderer, const DeltaVector2 &v0, const DeltaVector2 &v1, const DeltaVector2 &v2) {
|
||||
int minX = std::max(0, (int)std::min({v0.x, v1.x, v2.x}));
|
||||
int maxX = std::min((int)SIMULATED_WIDTH - 1, (int)std::max({v0.x, v1.x, v2.x}));
|
||||
int minY = std::max(0, (int)std::min({v0.y, v1.y, v2.y}));
|
||||
int maxY = std::min((int)SIMULATED_HEIGHT - 1, (int)std::max({v0.y, v1.y, v2.y}));
|
||||
|
||||
float a0 = v1.y - v2.y, b0 = v2.x - v1.x, c0 = v1.x * v2.y - v2.x * v1.y;
|
||||
float a1 = v2.y - v0.y, b1 = v0.x - v2.x, c1 = v2.x * v0.y - v0.x * v2.y;
|
||||
float a2 = v0.y - v1.y, b2 = v1.x - v0.x, c2 = v0.x * v1.y - v1.x * v0.y;
|
||||
|
||||
__m128 stepX = _mm_set_ps(3.0f, 2.0f, 1.0f, 0.0f);
|
||||
__m128 a0_4 = _mm_set1_ps(a0);
|
||||
__m128 a1_4 = _mm_set1_ps(a1);
|
||||
__m128 a2_4 = _mm_set1_ps(a2);
|
||||
|
||||
for (int y = minY; y <= maxY; y++) {
|
||||
float fy = (float)y;
|
||||
|
||||
__m128 e0 = _mm_add_ps(_mm_set1_ps(a0 * minX + b0 * fy + c0), _mm_mul_ps(a0_4, stepX));
|
||||
__m128 e1 = _mm_add_ps(_mm_set1_ps(a1 * minX + b1 * fy + c1), _mm_mul_ps(a1_4, stepX));
|
||||
__m128 e2 = _mm_add_ps(_mm_set1_ps(a2 * minX + b2 * fy + c2), _mm_mul_ps(a2_4, stepX));
|
||||
|
||||
__m128 e0_step = _mm_set1_ps(a0 * 4.0f);
|
||||
__m128 e1_step = _mm_set1_ps(a1 * 4.0f);
|
||||
__m128 e2_step = _mm_set1_ps(a2 * 4.0f);
|
||||
|
||||
for (int x = minX; x <= maxX; x += 4) {
|
||||
__m128 mask = _mm_and_ps(_mm_cmpge_ps(e0, _mm_setzero_ps()),
|
||||
_mm_and_ps(_mm_cmpge_ps(e1, _mm_setzero_ps()),
|
||||
_mm_cmpge_ps(e2, _mm_setzero_ps())));
|
||||
|
||||
int bitmask = _mm_movemask_ps(mask);
|
||||
|
||||
if (bitmask != 0) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((bitmask >> i) & 1) {
|
||||
if (x + i <= maxX)
|
||||
SDL_RenderPoint(renderer, (float)(x + i), fy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
e0 = _mm_add_ps(e0, e0_step);
|
||||
e1 = _mm_add_ps(e1, e1_step);
|
||||
e2 = _mm_add_ps(e2, e2_step);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rasterizeTriangleFast(SDL_Surface* surface, const DeltaVector2& v0, const DeltaVector2& v1, const DeltaVector2& v2, uint32_t color) {
|
||||
int minX = std::max(0, (int)std::min({v0.x, v1.x, v2.x}));
|
||||
int maxX = std::min((int)surface->w - 1, (int)std::max({v0.x, v1.x, v2.x}));
|
||||
@@ -178,33 +179,3 @@ void rasterizeTriangleFast(SDL_Surface* surface, const DeltaVector2& v0, const D
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// void rasterizeTriangle(SDL_Renderer *renderer, const DeltaVector2 &a, const DeltaVector2 &b, const DeltaVector2 &c) {
|
||||
// DeltaVector2 begin, end, p;
|
||||
// begin.x = std::min(a.x, std::min(b.x, c.x));
|
||||
// begin.y = std::min(a.y, std::min(b.y, c.y));
|
||||
// end.x = std::max(a.x, std::max(b.x, c.x));
|
||||
// end.y = std::max(a.y, std::max(b.y, c.y));
|
||||
|
||||
// int entrance, exit;
|
||||
|
||||
// for (int y = std::max(1.0f, begin.y); y < std::min(end.y, SIMULATED_HEIGHT + 0.0f); y++) {
|
||||
// entrance = -1;
|
||||
// exit = -1;
|
||||
// for (int x = std::max(1.0f, begin.x); x < std::min(end.x, SIMULATED_WIDTH + 0.0f); x++) {
|
||||
// p.x = x; p.y = y;
|
||||
|
||||
// if (getDeterminant(a, b, p) >= 0 && getDeterminant(b, c, p) >= 0 && getDeterminant(c, a, p) >= 0 && entrance == -1) {
|
||||
// SDL_RenderPoint(renderer, p.x, p.y);
|
||||
// // entrance = x;
|
||||
// }
|
||||
// else if (!(getDeterminant(a, b, p) >= 0 && getDeterminant(b, c, p) >= 0 && getDeterminant(c, a, p) >= 0) && entrance != -1) {
|
||||
// exit = x;
|
||||
// break;
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// // SDL_RenderLine(renderer, entrance, y, exit, y);
|
||||
// }
|
||||
// }
|
||||
+28
-15
@@ -45,7 +45,7 @@ DeltaVector3 DeltaCamera::translatePoint(const DeltaVector3 &worldPos) {
|
||||
return calculatedPos;
|
||||
}
|
||||
|
||||
DeltaVector2 DeltaCamera::projectPointVec(const DeltaVector3 &worldPos) {
|
||||
DeltaVector3 DeltaCamera::projectPointVec(const DeltaVector3 &worldPos) {
|
||||
DeltaVector3 calculatedPos; DeltaVector2 projected;
|
||||
calculatedPos = worldPos;
|
||||
|
||||
@@ -61,17 +61,22 @@ DeltaVector2 DeltaCamera::projectPointVec(const DeltaVector3 &worldPos) {
|
||||
projected.y = SIMULATED_HEIGHT - projected.y;
|
||||
|
||||
// we are done =D
|
||||
return projected;
|
||||
return {projected.x, projected.y, calculatedPos.y};
|
||||
}
|
||||
|
||||
int DeltaCamera::projectTriangle(const DeltaTriangle &in, DeltaTriangle2D &out1, DeltaTriangle2D &out2) {
|
||||
DeltaTriangle translated = { translatePoint(in.a), translatePoint(in.b), translatePoint(in.c) }, clipped1, clipped2;
|
||||
int DeltaCamera::projectTriangle(const DeltaRenderTriangle &in, DeltaTriangle &out1, DeltaTriangle &out2, DeltaTriangle2D &uv1, DeltaTriangle2D &uv2) {
|
||||
DeltaTriangle translated = { translatePoint(in.a.pos), translatePoint(in.b.pos), translatePoint(in.c.pos) };
|
||||
DeltaRenderTriangle translatedUV = {{translated.a, in.a.uv}, {translated.b, in.b.uv}, {translated.c, in.c.uv}}, clipped1, clipped2;
|
||||
|
||||
int numClipped = clipTriangleAgainstNearPlane(0.01, translated, clipped1, clipped2);
|
||||
int numClipped = clipTriangleAgainstNearPlane(0.01, translatedUV, clipped1, clipped2);
|
||||
if (numClipped == 1) {
|
||||
out1.a = projectPointVec(clipped1.a);
|
||||
out1.b = projectPointVec(clipped1.b);
|
||||
out1.c = projectPointVec(clipped1.c);
|
||||
out1.a = projectPointVec(clipped1.a.pos);
|
||||
out1.b = projectPointVec(clipped1.b.pos);
|
||||
out1.c = projectPointVec(clipped1.c.pos);
|
||||
|
||||
uv1.a = clipped1.a.uv;
|
||||
uv1.b = clipped1.b.uv;
|
||||
uv1.c = clipped1.c.uv;
|
||||
|
||||
// out1.a = projectPointVec(translated.a);
|
||||
// out1.b = projectPointVec(translated.b);
|
||||
@@ -80,18 +85,26 @@ int DeltaCamera::projectTriangle(const DeltaTriangle &in, DeltaTriangle2D &out1,
|
||||
|
||||
if (numClipped == 2) {
|
||||
|
||||
out1.a = projectPointVec(clipped1.a);
|
||||
out1.b = projectPointVec(clipped1.b);
|
||||
out1.c = projectPointVec(clipped1.c);
|
||||
out1.a = projectPointVec(clipped1.a.pos);
|
||||
out1.b = projectPointVec(clipped1.b.pos);
|
||||
out1.c = projectPointVec(clipped1.c.pos);
|
||||
|
||||
out2.a = projectPointVec(clipped2.a);
|
||||
out2.b = projectPointVec(clipped2.b);
|
||||
out2.c = projectPointVec(clipped2.c);
|
||||
out2.a = projectPointVec(clipped2.a.pos);
|
||||
out2.b = projectPointVec(clipped2.b.pos);
|
||||
out2.c = projectPointVec(clipped2.c.pos);
|
||||
|
||||
uv1.a = clipped1.a.uv;
|
||||
uv1.b = clipped1.b.uv;
|
||||
uv1.c = clipped1.c.uv;
|
||||
|
||||
uv2.a = clipped2.a.uv;
|
||||
uv2.b = clipped2.b.uv;
|
||||
uv2.c = clipped2.c.uv;
|
||||
}
|
||||
return numClipped;
|
||||
}
|
||||
|
||||
DeltaVector2 DeltaCamera::projectPoint(float worldX, float worldY, float worldZ) {
|
||||
DeltaVector3 DeltaCamera::projectPoint(float worldX, float worldY, float worldZ) {
|
||||
// simple conversion, dont iterate further
|
||||
return projectPointVec({ worldX, worldY, worldZ });
|
||||
}
|
||||
Reference in New Issue
Block a user