Better car movement, optimizations and clipping
This commit is contained in:
parent
e1e4f77685
commit
040c4ae81c
|
@ -19,11 +19,17 @@ struct Color {
|
|||
#ifdef PRIZM
|
||||
unsigned short color;
|
||||
char textColor;
|
||||
bool operator != (Color o){
|
||||
return color != o.color;
|
||||
}
|
||||
#endif
|
||||
#ifdef SDL
|
||||
int r;
|
||||
int g;
|
||||
int b;
|
||||
bool operator != (Color o){
|
||||
return r != o.r || g != o.g || b != o.b;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
#include "vector.h"
|
||||
#include "display.h"
|
||||
|
||||
#define NEAR_PLANE 0.5
|
||||
#define NEAR_PLANE 0.1
|
||||
#define FAR_PLANE 100
|
||||
|
||||
#define PIXEL_SIZE 2
|
||||
#define PIXEL_SIZE 4
|
||||
#define RENDER_WIDTH (DISPLAY_WIDTH/PIXEL_SIZE)
|
||||
#define RENDER_HEIGHT (DISPLAY_HEIGHT/PIXEL_SIZE)
|
||||
|
||||
|
@ -35,6 +35,7 @@ struct Model {
|
|||
};
|
||||
|
||||
namespace Rasterizer {
|
||||
void init();
|
||||
void reset();
|
||||
extern fp *depthBuffer;
|
||||
|
||||
|
|
|
@ -16,3 +16,6 @@ fp _fp_sin(fp x);
|
|||
fp fp_sin(fp x);
|
||||
fp fp_cos(fp x);
|
||||
fp fp_atan2(fp y, fp x);
|
||||
|
||||
float isqrt(float x);
|
||||
fp fp_isqrt(fp x);
|
||||
|
|
|
@ -29,10 +29,36 @@ struct vec3d {
|
|||
vec3d operator / (fp o){
|
||||
return {x / o, y / o, z / o};
|
||||
}
|
||||
|
||||
bool operator == (vec3d o){
|
||||
return x == o.x && y == o.y && z == o.z;
|
||||
}
|
||||
};
|
||||
|
||||
struct vec3f {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
vec3f operator + (vec3f o){
|
||||
return {x + o.x, y + o.y, z + o.z};
|
||||
}
|
||||
vec3f operator - (vec3f o){
|
||||
return {x - o.x, y - o.y, z - o.z};
|
||||
}
|
||||
vec3f operator * (vec3f o){
|
||||
return {x * o.x, y * o.y, z * o.z};
|
||||
}
|
||||
vec3f operator / (vec3f o){
|
||||
return {x / o.x, y / o.y, z / o.z};
|
||||
}
|
||||
vec3f operator * (float o){
|
||||
return {x * o, y * o, z * o};
|
||||
}
|
||||
vec3f operator / (float o){
|
||||
return {x / o, y / o, z / o};
|
||||
}
|
||||
|
||||
bool operator == (vec3f o){
|
||||
return x == o.x && y == o.y && z == o.z;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -12,8 +12,10 @@ Color newColor(int r, int g, int b){
|
|||
|
||||
namespace Display {
|
||||
int textHeight = 10;
|
||||
unsigned short *VRAMAddress;
|
||||
|
||||
void init(){
|
||||
VRAMAddress = (unsigned short*)GetVRAMAddress();
|
||||
}
|
||||
|
||||
void clear(Color color){
|
||||
|
@ -27,7 +29,7 @@ namespace Display {
|
|||
}
|
||||
void destroy(){}
|
||||
void fillRect(int x, int y, int w, int h, Color color){
|
||||
unsigned short*s=(unsigned short*)GetVRAMAddress();
|
||||
unsigned short*s=VRAMAddress;
|
||||
s+=(y*384)+x;
|
||||
while(h--){
|
||||
unsigned w2=w;
|
||||
|
@ -37,7 +39,8 @@ namespace Display {
|
|||
}
|
||||
}
|
||||
void drawPoint(int x, int y, Color color){
|
||||
Bdisp_SetPoint_VRAM(x, y, color.color);
|
||||
// Bdisp_SetPoint_VRAM(x, y, color.color);
|
||||
*(VRAMAddress + x + y * DISPLAY_WIDTH) = color.color;
|
||||
}
|
||||
int textWidth(const char *text){
|
||||
return strlen(text)*6;
|
||||
|
|
207
src/main.cpp
207
src/main.cpp
|
@ -7,15 +7,14 @@
|
|||
#include "rmath.h"
|
||||
#include "math.h"
|
||||
|
||||
#define NUM_CUBES 20
|
||||
|
||||
mat4 view;
|
||||
vec3d carPos = {0, 0, 0};
|
||||
vec3d carSpeed = {0, 0, 0};
|
||||
fp carDirection = 0;
|
||||
fp carAngle = 0;
|
||||
fp cameraAngle = 0;
|
||||
fp wheelSpeed = 0;
|
||||
vec3f carPos = {0, 0, 0};
|
||||
vec3f cameraPos = {0, 0, 0};
|
||||
vec3f carSpeed = {0, 0, 0};
|
||||
float carDirection = 0;
|
||||
float carAngle = 0;
|
||||
float cameraAngle = 0;
|
||||
float wheelSpeed = 0;
|
||||
|
||||
vec3d vertexShader(vec3d i, void *uniforms){
|
||||
if(uniforms == nullptr)
|
||||
|
@ -724,35 +723,122 @@ int main(){
|
|||
|
||||
srand(0);
|
||||
|
||||
Triangle trackTriangles[100*2];
|
||||
// Triangle treeTriangles[10*10];
|
||||
// for(int x = 0; x < 10; x++){
|
||||
// for(int y = 0; y < 10; y++){
|
||||
// // int treeX = (x-50)*10;
|
||||
// // int treeY = (y-50)*10;
|
||||
// int treeX = ((rand()%100) - 50)*10;
|
||||
// int treeY = ((rand()%100) - 50)*10;
|
||||
// treeTriangles[x+y*10] = {
|
||||
// {treeX-1, 0, treeY},
|
||||
// {treeX, -1, treeY},
|
||||
// {treeX+1, 0, treeY},
|
||||
// newColor(0, 255, 0)
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// Mesh treeMesh = {
|
||||
// 10*10,
|
||||
// treeTriangles
|
||||
// };
|
||||
|
||||
for(int i = 0; i < 100; i++){
|
||||
fp angle = fp(i) * fp(2*PI) / fp(100);
|
||||
fp nextAngle = fp(i+1) * fp(2*PI) / fp(100);
|
||||
printf("%.3f\n", (float)fp_sin(angle));
|
||||
trackTriangles[i] = {
|
||||
{fp_cos(angle)*fp(4), 0, fp_sin(angle)*fp(4)},
|
||||
{fp_cos(angle)*fp(5), 0, fp_sin(angle)*fp(5)},
|
||||
{fp_cos(nextAngle)*fp(4), 0, fp_sin(nextAngle)*fp(4)},
|
||||
newColor(0, 0, 0)
|
||||
};
|
||||
trackTriangles[i].p0 = trackTriangles[i].p0 * fp(10);
|
||||
trackTriangles[i].p1 = trackTriangles[i].p1 * fp(10);
|
||||
trackTriangles[i].p2 = trackTriangles[i].p2 * fp(10);
|
||||
trackTriangles[i+100] = {
|
||||
{fp_cos(angle)*fp(5), 0, fp_sin(angle)*fp(5)},
|
||||
{fp_cos(nextAngle)*fp(4), 0, fp_sin(nextAngle)*fp(4)},
|
||||
{fp_cos(nextAngle)*fp(5), 0, fp_sin(nextAngle)*fp(5)},
|
||||
newColor(255, 255, 255)
|
||||
};
|
||||
trackTriangles[i+100].p0 = trackTriangles[i+100].p0 * fp(10);
|
||||
trackTriangles[i+100].p1 = trackTriangles[i+100].p1 * fp(10);
|
||||
trackTriangles[i+100].p2 = trackTriangles[i+100].p2 * fp(10);
|
||||
#define TRACK_SEGMENTS 25
|
||||
#define TRACK_WIDTH 10
|
||||
vec3d trackPoints[TRACK_SEGMENTS+1] = {
|
||||
{0, 0, 0},
|
||||
{2, 0, 0},
|
||||
{4, 0, 0},
|
||||
{6, 0, 0},
|
||||
{8, 0, 0},
|
||||
{10, 0, 0},
|
||||
{12, 0, 1},
|
||||
{13, 0, 3},
|
||||
{13, 0, 5},
|
||||
{12, 0, 7},
|
||||
{10, 0, 9},
|
||||
{8, 0, 10},
|
||||
{6, 0, 10},
|
||||
{4, 0, 10},
|
||||
{2, 0, 10},
|
||||
{0, 0, 10},
|
||||
{-2, 0, 10},
|
||||
{-4, 0, 10},
|
||||
{-6, 0, 10},
|
||||
{-8, 0, 10},
|
||||
{-10, 0, 10},
|
||||
{-12, 0, 10},
|
||||
{-14, 0, 10},
|
||||
{-16, 0, 10},
|
||||
{-18, 0, 10},
|
||||
{-20, 0, 10},
|
||||
};
|
||||
|
||||
for(int i = 0; i < TRACK_SEGMENTS+1; i++){
|
||||
trackPoints[i] = trackPoints[i] * 0.5;
|
||||
}
|
||||
|
||||
Triangle trackTriangles[TRACK_SEGMENTS*2];
|
||||
|
||||
for(int i = 0; i < TRACK_SEGMENTS; i++){
|
||||
vec3d pos = trackPoints[i] * fp(10);
|
||||
vec3d nextPos = trackPoints[i+1] * fp(10);
|
||||
|
||||
vec3d direction = nextPos - pos;
|
||||
vec3d perpendicular = {direction.z, 0, fp(0)-direction.x};
|
||||
direction = direction * TRACK_WIDTH;
|
||||
|
||||
perpendicular = perpendicular * fp_isqrt(perpendicular.x*perpendicular.x + perpendicular.y*perpendicular.y + perpendicular.z*perpendicular.z);
|
||||
perpendicular = perpendicular * fp(TRACK_WIDTH);
|
||||
|
||||
trackTriangles[i] = {
|
||||
pos - perpendicular,
|
||||
nextPos - perpendicular,
|
||||
nextPos + perpendicular,
|
||||
newColor(50, 50, 50)
|
||||
};
|
||||
trackTriangles[TRACK_SEGMENTS+i] = {
|
||||
pos + perpendicular,
|
||||
nextPos + perpendicular,
|
||||
pos - perpendicular,
|
||||
newColor(50, 50, 50)
|
||||
};
|
||||
}
|
||||
|
||||
// for(int i = 0; i < TRACK_SEGMENTS; i++){
|
||||
// fp angle = fp(i) * fp(2*PI) / fp(TRACK_SEGMENTS);
|
||||
// fp nextAngle = fp(i+1) * fp(2*PI) / fp(TRACK_SEGMENTS);
|
||||
// trackTriangles[i] = {
|
||||
// {fp_cos(angle)*fp(4), 0, fp_sin(angle)*fp(4)},
|
||||
// {fp_cos(angle)*fp(5), 0, fp_sin(angle)*fp(5)},
|
||||
// {fp_cos(nextAngle)*fp(4), 0, fp_sin(nextAngle)*fp(4)},
|
||||
// newColor(0, 0, 0)
|
||||
// };
|
||||
// trackTriangles[i].p0 = trackTriangles[i].p0 * fp(10);
|
||||
// trackTriangles[i].p1 = trackTriangles[i].p1 * fp(10);
|
||||
// trackTriangles[i].p2 = trackTriangles[i].p2 * fp(10);
|
||||
// trackTriangles[i+TRACK_SEGMENTS] = {
|
||||
// {fp_cos(angle)*fp(5), 0, fp_sin(angle)*fp(5)},
|
||||
// {fp_cos(nextAngle)*fp(4), 0, fp_sin(nextAngle)*fp(4)},
|
||||
// {fp_cos(nextAngle)*fp(5), 0, fp_sin(nextAngle)*fp(5)},
|
||||
// newColor(255, 255, 255)
|
||||
// };
|
||||
// trackTriangles[i+TRACK_SEGMENTS].p0 = trackTriangles[i+TRACK_SEGMENTS].p0 * fp(10);
|
||||
// trackTriangles[i+TRACK_SEGMENTS].p1 = trackTriangles[i+TRACK_SEGMENTS].p1 * fp(10);
|
||||
// trackTriangles[i+TRACK_SEGMENTS].p2 = trackTriangles[i+TRACK_SEGMENTS].p2 * fp(10);
|
||||
// }
|
||||
|
||||
// Model trees = {
|
||||
// .mesh = treeMesh,
|
||||
// .shader = {
|
||||
// .vertexShader = vertexShader,
|
||||
// .fragmentShader = fragmentShader,
|
||||
// .uniforms = nullptr
|
||||
// }
|
||||
// };
|
||||
Model track = {
|
||||
.mesh = {
|
||||
100 * 2,
|
||||
TRACK_SEGMENTS*2,
|
||||
trackTriangles
|
||||
},
|
||||
.shader = {
|
||||
|
@ -773,6 +859,7 @@ int main(){
|
|||
}
|
||||
};
|
||||
|
||||
Rasterizer::init();
|
||||
while(true){
|
||||
Rasterizer::reset();
|
||||
|
||||
|
@ -783,31 +870,39 @@ int main(){
|
|||
return 0;
|
||||
}
|
||||
|
||||
const fp speed = 0.02 * Time::delta;
|
||||
const fp acceleration = fp(1);
|
||||
if(Input::keyDown(KEY_RIGHT)){
|
||||
carAngle = carAngle + speed;
|
||||
if(Input::keyDown(KEY_RIGHT) || Input::keyDown(KEY_6)){
|
||||
carDirection = carDirection + Time::delta / 40.0f;
|
||||
}
|
||||
if(Input::keyDown(KEY_LEFT)){
|
||||
carAngle = carAngle - speed;
|
||||
if(Input::keyDown(KEY_LEFT) || Input::keyDown(KEY_4)){
|
||||
carDirection = carDirection - Time::delta / 40.0f;
|
||||
}
|
||||
wheelSpeed = 0;
|
||||
if(Input::keyDown(KEY_UP)){
|
||||
wheelSpeed = wheelSpeed + fp(2);
|
||||
|
||||
if(Input::keyDown(KEY_UP) || Input::keyDown(KEY_8)){
|
||||
wheelSpeed = wheelSpeed + Time::delta / 200.0f;
|
||||
}
|
||||
if(Input::keyDown(KEY_DOWN)){
|
||||
wheelSpeed = wheelSpeed - fp(2);
|
||||
if(Input::keyDown(KEY_DOWN) || Input::keyDown(KEY_5)){
|
||||
wheelSpeed = wheelSpeed - Time::delta / 200.0f;
|
||||
}
|
||||
// wheelSpeed = wheelSpeed / (fp(1000) * fp(Time::delta));
|
||||
// if(wheelSpeed < 0)
|
||||
// wheelSpeed = 0;
|
||||
// wheelSpeed = wheelSpeed * fp(0.7);
|
||||
carSpeed.x = carSpeed.x + wheelSpeed * fp(Time::delta) * fp_cos(carAngle) / fp(500);
|
||||
carSpeed.z = carSpeed.z + wheelSpeed * fp(Time::delta) * fp_sin(fp(0)-(carAngle)) / fp(500);
|
||||
// cameraAngle = fp(0) - fp_atan2(carSpeed.z, carSpeed.x);
|
||||
cameraAngle = carAngle;
|
||||
carPos.x = carPos.x + carSpeed.x * fp(Time::delta);
|
||||
carPos.z = carPos.z + carSpeed.z * fp(Time::delta);
|
||||
|
||||
wheelSpeed = wheelSpeed - (wheelSpeed * 0.001f) * Time::delta;
|
||||
if(wheelSpeed > 1)
|
||||
wheelSpeed = 1;
|
||||
if(wheelSpeed < 0)
|
||||
wheelSpeed = 0;
|
||||
|
||||
carSpeed.x = carSpeed.x + wheelSpeed * float(fp_cos(fp(carAngle))) * Time::delta / 150.0f;
|
||||
carSpeed.z = carSpeed.z + wheelSpeed * float(fp_sin(fp(0)-fp(carAngle))) * Time::delta / 150.0f;
|
||||
carSpeed.x = carSpeed.x - (carSpeed.x * 0.01f) * Time::delta;
|
||||
carSpeed.z = carSpeed.z - (carSpeed.z * 0.01f) * Time::delta;
|
||||
|
||||
cameraAngle = cameraAngle + (-cameraAngle * 0.02 + 0.02 * carDirection) * Time::delta;
|
||||
carAngle = carAngle + (-carAngle * 0.05 + 0.05 * carDirection) * Time::delta;
|
||||
// carAngle = carDirection;
|
||||
carPos.x = carPos.x + carSpeed.x * Time::delta;
|
||||
carPos.z = carPos.z + carSpeed.z * Time::delta;
|
||||
// vec3f zero = {0,0,0};
|
||||
// cameraPos = cameraPos + (zero - cameraPos * 0.2f + carPos * 0.2f) * Time::delta;
|
||||
cameraPos = carPos;
|
||||
|
||||
Display::clear(newColor(70, 180, 220));
|
||||
|
||||
|
@ -818,9 +913,11 @@ int main(){
|
|||
view = mat4();
|
||||
view = mat4::rotateX(view, HALF_PI*0.1);
|
||||
view = mat4::translate(view, 0, 2, 6);
|
||||
view = mat4::rotateY(view, fp(0) - cameraAngle - fp(HALF_PI));
|
||||
view = mat4::translate(view, fp(0)-carPos.x, 0, fp(0)-carPos.z);
|
||||
view = mat4::rotateY(view, -cameraAngle - HALF_PI);
|
||||
view = mat4::translate(view, -cameraPos.x, 0, -cameraPos.z);
|
||||
|
||||
// Rasterizer::drawModel(trees, false);
|
||||
// Rasterizer::drawTriangle(trees.mesh.triangles[51+51*100], trees.shader, false);
|
||||
Rasterizer::drawModel(track, false);
|
||||
Rasterizer::drawModel(car, true);
|
||||
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
#include "rasterizer.h"
|
||||
#include "display.h"
|
||||
#include "rmath.h"
|
||||
#include "time.h"
|
||||
|
||||
struct Plane {
|
||||
vec3d n;
|
||||
fp d;
|
||||
};
|
||||
|
||||
int min(int a, int b){
|
||||
if(a < b)
|
||||
|
@ -24,8 +30,8 @@ float abs(float v){
|
|||
}
|
||||
#endif
|
||||
|
||||
float dot(vec3f a, vec3f b){
|
||||
return a.x*b.x + a.y*b.y;
|
||||
fp dot3(vec3d a, vec3d b){
|
||||
return a.x*b.x + a.y*b.y + a.z*b.z;
|
||||
}
|
||||
|
||||
fp cross(vec3d a, vec3d b){
|
||||
|
@ -33,8 +39,20 @@ fp cross(vec3d a, vec3d b){
|
|||
}
|
||||
|
||||
namespace Rasterizer {
|
||||
Plane clippingPlanes[5];
|
||||
|
||||
fp *depthBuffer;
|
||||
|
||||
void init(){
|
||||
#define I_SQRT_2 0.707106
|
||||
clippingPlanes[0] = {{0, 0, 1}, fp(0)-fp(NEAR_PLANE)}; // near
|
||||
// clippingPlanes[1] = {{0, 0, 1}, fp(0)-fp(FAR_PLANE)}; // far
|
||||
clippingPlanes[1] = {{fp(I_SQRT_2), 0, fp(I_SQRT_2)}, 0}; // left
|
||||
clippingPlanes[2] = {{fp(-I_SQRT_2), 0, fp(I_SQRT_2)}, 0}; // right
|
||||
clippingPlanes[3] = {{0, fp(I_SQRT_2), fp(I_SQRT_2)}, 0}; // bottom
|
||||
clippingPlanes[4] = {{0, fp(-I_SQRT_2), fp(I_SQRT_2)}, 0}; // top
|
||||
}
|
||||
|
||||
int edge(vec3i p, vec3i e1, vec3i e2){
|
||||
return (p.x - e2.x) * (e1.y - e2.y) - (p.y - e2.y) * (e1.x - e2.x);
|
||||
}
|
||||
|
@ -46,8 +64,6 @@ namespace Rasterizer {
|
|||
}
|
||||
|
||||
vec3d toDevice(vec3d p){
|
||||
if(p.z == 0)
|
||||
p.z = -0.1;
|
||||
return {
|
||||
p.x / p.z,
|
||||
p.y / p.z,
|
||||
|
@ -63,31 +79,11 @@ namespace Rasterizer {
|
|||
};
|
||||
}
|
||||
|
||||
void drawTriangle(Triangle triangle, Shader shader, bool useDepth){
|
||||
// reset();
|
||||
// SDL_SetRenderDrawColor(renderer, triangle.c.r, triangle.c.g, triangle.c.b, 255);
|
||||
//
|
||||
|
||||
triangle.p0 = shader.vertexShader(triangle.p0, shader.uniforms);
|
||||
triangle.p1 = shader.vertexShader(triangle.p1, shader.uniforms);
|
||||
triangle.p2 = shader.vertexShader(triangle.p2, shader.uniforms);
|
||||
|
||||
if(useDepth && (triangle.p0.z == 0 || triangle.p1.z == 0 || triangle.p2.z == 0))
|
||||
return;
|
||||
|
||||
void _drawTriangle(Triangle triangle, Shader shader, bool useDepth){
|
||||
vec3d p0_d = toDevice(triangle.p0);
|
||||
vec3d p1_d = toDevice(triangle.p1);
|
||||
vec3d p2_d = toDevice(triangle.p2);
|
||||
|
||||
if((p0_d.z < NEAR_PLANE || p1_d.z < NEAR_PLANE || p2_d.z < NEAR_PLANE)
|
||||
|| (p0_d.x < -0.5 && p1_d.x < -0.5 && p2_d.x < -0.5)
|
||||
|| (p0_d.y < -0.5 && p1_d.y < -0.5 && p2_d.y < -0.5)
|
||||
|| (p0_d.x > 0.5 && p1_d.x > 0.5 && p2_d.x > 0.5)
|
||||
|| (p0_d.y > 0.5 && p1_d.y > 0.5 && p2_d.y > 0.5)
|
||||
){
|
||||
return;
|
||||
}
|
||||
|
||||
fp winding = cross({p1_d.x - p0_d.x, p1_d.y - p0_d.y, 0}, {p2_d.x - p0_d.x, p2_d.y - p0_d.y, 0});
|
||||
|
||||
vec3i p0, p1, p2;
|
||||
|
@ -106,36 +102,39 @@ namespace Rasterizer {
|
|||
int maxX = min(max(max(p0.x, p1.x), p2.x), RENDER_WIDTH);
|
||||
int minY = max(min(min(p0.y, p1.y), p2.y), 0);
|
||||
int maxY = min(max(max(p0.y, p1.y), p2.y), RENDER_HEIGHT);
|
||||
if(minX == maxX || minY == maxY)
|
||||
return;
|
||||
|
||||
int e1 = edge({minX, minY, 0}, p0, p1);
|
||||
int e2 = edge({minX, minY, 0}, p1, p2);
|
||||
int e3 = edge({minX, minY, 0}, p2, p0);
|
||||
|
||||
const vec3i bary_v0 = {(p1.x - p0.x), (p1.y - p0.y), 0};
|
||||
const vec3i bary_v1 = {(p2.x - p0.x), (p2.y - p0.y), 0};
|
||||
fp bary_denom = (bary_v0.x * bary_v1.y - bary_v1.x * bary_v0.y);
|
||||
if(bary_denom == 0)
|
||||
return;
|
||||
const fp i_bary_denom = fp(1000) / fp(bary_v0.x * bary_v1.y - bary_v1.x * bary_v0.y);
|
||||
fp bary_v, bary_w, bary_u;
|
||||
fp i_p0z, i_p1z, i_p2z;
|
||||
fp bary_v_per_x, bary_w_per_x, bary_u_per_x, bary_v_per_y, bary_w_per_y, bary_u_per_y;
|
||||
if(useDepth){
|
||||
const vec3i bary_v0 = {(p1.x - p0.x), (p1.y - p0.y), 0};
|
||||
const vec3i bary_v1 = {(p2.x - p0.x), (p2.y - p0.y), 0};
|
||||
fp bary_denom = (bary_v0.x * bary_v1.y - bary_v1.x * bary_v0.y);
|
||||
if(bary_denom == 0)
|
||||
return;
|
||||
const fp i_bary_denom = fp(1000) / fp(bary_v0.x * bary_v1.y - bary_v1.x * bary_v0.y);
|
||||
|
||||
const vec3i bary_v2 = {minX - p0.x, minY - p0.y, 0};
|
||||
const fp bary_v_per_x = fp(bary_v1.y) * fp(i_bary_denom) / fp(1000);
|
||||
const fp bary_w_per_x = fp(0) - fp(bary_v0.y) * fp(i_bary_denom) / fp(1000);
|
||||
const fp bary_u_per_x = fp(0) - bary_v_per_x - bary_w_per_x;
|
||||
const vec3i bary_v2 = {minX - p0.x, minY - p0.y, 0};
|
||||
bary_v_per_x = fp(bary_v1.y) * fp(i_bary_denom) / fp(1000);
|
||||
bary_w_per_x = fp(0) - fp(bary_v0.y) * fp(i_bary_denom) / fp(1000);
|
||||
bary_u_per_x = fp(0) - bary_v_per_x - bary_w_per_x;
|
||||
|
||||
const fp bary_v_per_y = fp(0) - fp(bary_v1.x) * fp(i_bary_denom) / fp(1000);
|
||||
const fp bary_w_per_y = fp(bary_v0.x) * fp(i_bary_denom) / fp(1000);
|
||||
const fp bary_u_per_y = fp(0) -bary_v_per_y - bary_w_per_y;
|
||||
bary_v_per_y = fp(0) - fp(bary_v1.x) * fp(i_bary_denom) / fp(1000);
|
||||
bary_w_per_y = fp(bary_v0.x) * fp(i_bary_denom) / fp(1000);
|
||||
bary_u_per_y = fp(0) -bary_v_per_y - bary_w_per_y;
|
||||
|
||||
fp bary_v = fp(bary_v2.x * bary_v1.y - bary_v1.x * bary_v2.y) / fp(1000) * fp(i_bary_denom);
|
||||
fp bary_w = fp(bary_v0.x * bary_v2.y - bary_v2.x * bary_v0.y) / fp(1000) * fp(i_bary_denom);
|
||||
fp bary_u = fp(1) - bary_v - bary_w;
|
||||
bary_v = fp(bary_v2.x * bary_v1.y - bary_v1.x * bary_v2.y) / fp(1000) * fp(i_bary_denom);
|
||||
bary_w = fp(bary_v0.x * bary_v2.y - bary_v2.x * bary_v0.y) / fp(1000) * fp(i_bary_denom);
|
||||
bary_u = fp(1) - bary_v - bary_w;
|
||||
|
||||
fp i_p0z = fp(1)/fp(p0.z);
|
||||
fp i_p1z = fp(1)/fp(p1.z);
|
||||
fp i_p2z = fp(1)/fp(p2.z);
|
||||
i_p0z = fp(1)/fp(p0.z);
|
||||
i_p1z = fp(1)/fp(p1.z);
|
||||
i_p2z = fp(1)/fp(p2.z);
|
||||
}
|
||||
|
||||
for(int y = minY; y < maxY; y++){
|
||||
bool hasEntered = false;
|
||||
|
@ -153,18 +152,28 @@ namespace Rasterizer {
|
|||
fp i_z;
|
||||
if(useDepth){
|
||||
vec3d b = {i_bary_u, i_bary_v, i_bary_w};
|
||||
// fp i_z = (b.x * i_p0z + b.y * i_p1z + b.z * i_p2z);
|
||||
i_z.i = ((b.x.i * i_p0z.i) + (b.y.i * i_p1z.i) + (b.z.i * i_p2z.i)) / FP_RIGHT;
|
||||
// i_z = (b.x * i_p0z + b.y * i_p1z + b.z * i_p2z);
|
||||
i_z.i = ((b.x.i * i_p0z.i) + (b.y.i * i_p1z.i) + (b.z.i * i_p2z.i));
|
||||
visible = visible && (i_z > depthBuffer[x+y*RENDER_WIDTH] || depthBuffer[x+y*RENDER_WIDTH] == -1);
|
||||
}
|
||||
if(visible){
|
||||
if(useDepth)
|
||||
// Color c = shader.fragmentShader(triangle.c, shader.uniforms);
|
||||
// if((ie1 >= -2 && ie1 <= 2)
|
||||
// || (ie2 >= -2 && ie2 <= 2)
|
||||
// || (ie3 >= -2 && ie3 <= 2))
|
||||
// c = {255 - c.r, 255 - c.g, 255 - c.b};
|
||||
if(useDepth){
|
||||
depthBuffer[x+y*RENDER_WIDTH] = i_z;
|
||||
Color c = shader.fragmentShader(triangle.c, shader.uniforms);
|
||||
// if(!(i_z == 0)){
|
||||
// c.r = (int)(fp(c.r) * i_z * fp(100));
|
||||
// c.g = (int)(fp(c.g) * i_z * fp(100));
|
||||
// c.b = (int)(fp(c.b) * i_z * fp(100));
|
||||
// }
|
||||
}
|
||||
#if PIXEL_SIZE == 1
|
||||
Display::drawPoint(x, y, c);
|
||||
Display::drawPoint(x, y, triangle.c);
|
||||
#else
|
||||
Display::fillRect(x*PIXEL_SIZE, y*PIXEL_SIZE, PIXEL_SIZE, PIXEL_SIZE, c);
|
||||
Display::fillRect(x*PIXEL_SIZE, y*PIXEL_SIZE, PIXEL_SIZE, PIXEL_SIZE, triangle.c);
|
||||
#endif
|
||||
}
|
||||
hasEntered = true;
|
||||
|
@ -194,6 +203,242 @@ namespace Rasterizer {
|
|||
}
|
||||
}
|
||||
|
||||
// void drawTriangle(Triangle triangle, Shader shader, bool useDepth){
|
||||
// triangle.p0 = shader.vertexShader(triangle.p0, shader.uniforms);
|
||||
// triangle.p1 = shader.vertexShader(triangle.p1, shader.uniforms);
|
||||
// triangle.p2 = shader.vertexShader(triangle.p2, shader.uniforms);
|
||||
//
|
||||
// if(triangle.p0 == triangle.p1 || triangle.p1 == triangle.p2 || triangle.p2 == triangle.p0){
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// bool clippedP0 = false;
|
||||
// bool clippedP1 = false;
|
||||
// bool clippedP2 = false;
|
||||
//
|
||||
// for(int i = 0; i < 5; i++){
|
||||
// int numClipped = 0;
|
||||
// if(dot3(clippingPlanes[i].n, triangle.p0) + clippingPlanes[i].d < 0){
|
||||
// numClipped++;
|
||||
// clippedP0 = true;
|
||||
// return;
|
||||
// }
|
||||
// if(dot3(clippingPlanes[i].n, triangle.p1) + clippingPlanes[i].d < 0){
|
||||
// numClipped++;
|
||||
// clippedP1 = true;
|
||||
// return;
|
||||
// }
|
||||
// if(dot3(clippingPlanes[i].n, triangle.p2) + clippingPlanes[i].d < 0){
|
||||
// numClipped++;
|
||||
// clippedP2 = true;
|
||||
// return;
|
||||
// }
|
||||
// if(numClipped == 0){
|
||||
// _drawTriangle(triangle, shader, useDepth);
|
||||
// } else if(numClipped == 1){
|
||||
// vec3d clipped;
|
||||
// vec3d notClipped[2];
|
||||
// if(clippedP0){
|
||||
// clipped = triangle.p0;
|
||||
// notClipped[0] = triangle.p1;
|
||||
// notClipped[1] = triangle.p2;
|
||||
// }
|
||||
//
|
||||
// if(clippedP1){
|
||||
// clipped = triangle.p1;
|
||||
// notClipped[0] = triangle.p0;
|
||||
// notClipped[1] = triangle.p2;
|
||||
// }
|
||||
//
|
||||
// if(clippedP2){
|
||||
// clipped = triangle.p2;
|
||||
// notClipped[0] = triangle.p0;
|
||||
// notClipped[1] = triangle.p1;
|
||||
// }
|
||||
//
|
||||
// fp d0 = dot3(clippingPlanes[i].n, clipped - notClipped[0]);
|
||||
// fp d1 = dot3(clippingPlanes[i].n, clipped - notClipped[1]);
|
||||
// if(d0 == 0 || d1 == 0)
|
||||
// return;
|
||||
//
|
||||
// vec3d A = notClipped[0] + (clipped - notClipped[0]) * ((fp(0) - clippingPlanes[i].d - dot3(clippingPlanes[i].n, notClipped[0]))/d0);
|
||||
// vec3d B = notClipped[1] + (clipped - notClipped[1]) * ((fp(0) - clippingPlanes[i].d - dot3(clippingPlanes[i].n, notClipped[1]))/d1);
|
||||
//
|
||||
// _drawTriangle({notClipped[0], A, notClipped[1], triangle.c}, shader, useDepth);
|
||||
// _drawTriangle({notClipped[1], A, B, triangle.c}, shader, useDepth);
|
||||
// } else if(numClipped == 2){
|
||||
// vec3d clipped[2];
|
||||
// vec3d notClipped;
|
||||
// if(!clippedP0){
|
||||
// notClipped = triangle.p0;
|
||||
// clipped[0] = triangle.p1;
|
||||
// clipped[1] = triangle.p2;
|
||||
// } else if(!clippedP1){
|
||||
// notClipped = triangle.p1;
|
||||
// clipped[0] = triangle.p0;
|
||||
// clipped[1] = triangle.p2;
|
||||
// } else {
|
||||
// notClipped = triangle.p2;
|
||||
// clipped[0] = triangle.p0;
|
||||
// clipped[1] = triangle.p1;
|
||||
// }
|
||||
//
|
||||
// fp d0 = dot3(clippingPlanes[i].n, clipped[0] - notClipped);
|
||||
// fp d1 = dot3(clippingPlanes[i].n, clipped[1] - notClipped);
|
||||
// if(d0 == 0 || d1 == 0)
|
||||
// return;
|
||||
//
|
||||
// vec3d B = notClipped + (clipped[0] - notClipped) * ((fp(0) - clippingPlanes[i].d - dot3(clippingPlanes[i].n, notClipped))/d0);
|
||||
// vec3d C = notClipped + (clipped[0] - notClipped) * ((fp(0) - clippingPlanes[i].d - dot3(clippingPlanes[i].n, notClipped))/d1);
|
||||
//
|
||||
// _drawTriangle({notClipped, B, C, triangle.c}, shader, useDepth);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
Mesh clipTriangleAgainstPlane(Triangle triangle, Plane plane){
|
||||
int numClipped = 0;
|
||||
bool clippedP0 = false;
|
||||
bool clippedP1 = false;
|
||||
bool clippedP2 = false;
|
||||
|
||||
if(dot3(plane.n, triangle.p0) + plane.d < 0){
|
||||
numClipped++;
|
||||
clippedP0 = true;
|
||||
}
|
||||
if(dot3(plane.n, triangle.p1) + plane.d < 0){
|
||||
numClipped++;
|
||||
clippedP1 = true;
|
||||
}
|
||||
if(dot3(plane.n, triangle.p2) + plane.d < 0){
|
||||
numClipped++;
|
||||
clippedP2 = true;
|
||||
}
|
||||
|
||||
if(numClipped == 0){
|
||||
Mesh m = {1, (Triangle*)malloc(sizeof(Triangle))};
|
||||
m.triangles[0] = triangle;
|
||||
return m;
|
||||
} else if(numClipped == 3){
|
||||
return {0, nullptr};
|
||||
} else if(numClipped == 2){
|
||||
vec3d clipped[2];
|
||||
vec3d notClipped;
|
||||
if(!clippedP0){
|
||||
notClipped = triangle.p0;
|
||||
clipped[0] = triangle.p1;
|
||||
clipped[1] = triangle.p2;
|
||||
} else if(!clippedP1){
|
||||
notClipped = triangle.p1;
|
||||
clipped[0] = triangle.p0;
|
||||
clipped[1] = triangle.p2;
|
||||
} else {
|
||||
notClipped = triangle.p2;
|
||||
clipped[0] = triangle.p0;
|
||||
clipped[1] = triangle.p1;
|
||||
}
|
||||
|
||||
fp d0 = dot3(plane.n, clipped[0] - notClipped);
|
||||
fp d1 = dot3(plane.n, clipped[1] - notClipped);
|
||||
if(d0 == 0 || d1 == 0)
|
||||
return {0, nullptr};
|
||||
|
||||
vec3d B = notClipped + (clipped[0] - notClipped) * ((fp(0) - plane.d - dot3(plane.n, notClipped))/d0);
|
||||
vec3d C = notClipped + (clipped[1] - notClipped) * ((fp(0) - plane.d - dot3(plane.n, notClipped))/d1);
|
||||
|
||||
Mesh m = {1, (Triangle*)malloc(sizeof(Triangle))};
|
||||
m.triangles[0] = {notClipped, B, C, triangle.c};
|
||||
return m;
|
||||
} else if(numClipped == 1){
|
||||
vec3d clipped;
|
||||
vec3d notClipped[2];
|
||||
if(clippedP0){
|
||||
clipped = triangle.p0;
|
||||
notClipped[0] = triangle.p1;
|
||||
notClipped[1] = triangle.p2;
|
||||
}
|
||||
|
||||
if(clippedP1){
|
||||
clipped = triangle.p1;
|
||||
notClipped[0] = triangle.p0;
|
||||
notClipped[1] = triangle.p2;
|
||||
}
|
||||
|
||||
if(clippedP2){
|
||||
clipped = triangle.p2;
|
||||
notClipped[0] = triangle.p0;
|
||||
notClipped[1] = triangle.p1;
|
||||
}
|
||||
|
||||
fp d0 = dot3(plane.n, clipped - notClipped[0]);
|
||||
fp d1 = dot3(plane.n, clipped - notClipped[1]);
|
||||
if(d0 == 0 || d1 == 0)
|
||||
return {0, nullptr};
|
||||
|
||||
vec3d A = notClipped[0] + (clipped - notClipped[0]) * ((fp(0) - plane.d - dot3(plane.n, notClipped[0]))/d0);
|
||||
vec3d B = notClipped[1] + (clipped - notClipped[1]) * ((fp(0) - plane.d - dot3(plane.n, notClipped[1]))/d1);
|
||||
|
||||
Mesh m = {2, (Triangle*)malloc(2*sizeof(Triangle))};
|
||||
m.triangles[0] = {notClipped[0], A, notClipped[1], triangle.c};
|
||||
m.triangles[1] = {notClipped[1], A, B, triangle.c};
|
||||
return m;
|
||||
}
|
||||
|
||||
return {0, nullptr};
|
||||
}
|
||||
|
||||
Mesh clipMeshAgainstPlane(Mesh mesh, Plane plane){
|
||||
Mesh r = {0, nullptr};
|
||||
|
||||
for(int i = 0; i < mesh.numTriangles; i++){
|
||||
Mesh m = clipTriangleAgainstPlane(mesh.triangles[i], plane);
|
||||
r.numTriangles += m.numTriangles;
|
||||
if(r.triangles == nullptr)
|
||||
r.triangles = (Triangle*) malloc(r.numTriangles*sizeof(Triangle));
|
||||
else
|
||||
r.triangles = (Triangle*) realloc(r.triangles, r.numTriangles*sizeof(Triangle));
|
||||
|
||||
for(int i = r.numTriangles - m.numTriangles; i < r.numTriangles; i++){
|
||||
r.triangles[i] = m.triangles[i - (r.numTriangles - m.numTriangles)];
|
||||
}
|
||||
|
||||
free(m.triangles);
|
||||
}
|
||||
free(mesh.triangles);
|
||||
return r;
|
||||
}
|
||||
|
||||
Mesh clipMesh(Mesh mesh){
|
||||
for(int i = 0; i < 5; i++){
|
||||
mesh = clipMeshAgainstPlane(mesh, clippingPlanes[i]);
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
|
||||
Mesh clipTriangle(Triangle triangle){
|
||||
Mesh m = {1, (Triangle*)malloc(sizeof(Triangle))};
|
||||
m.triangles[0] = triangle;
|
||||
m = clipMesh(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
void drawTriangle(Triangle triangle, Shader shader, bool useDepth){
|
||||
triangle.p0 = shader.vertexShader(triangle.p0, shader.uniforms);
|
||||
triangle.p1 = shader.vertexShader(triangle.p1, shader.uniforms);
|
||||
triangle.p2 = shader.vertexShader(triangle.p2, shader.uniforms);
|
||||
|
||||
if(triangle.p0 == triangle.p1 || triangle.p1 == triangle.p2 || triangle.p2 == triangle.p0){
|
||||
return;
|
||||
}
|
||||
|
||||
Mesh mesh = clipTriangle(triangle);
|
||||
for(int i = 0; i < mesh.numTriangles; i++){
|
||||
_drawTriangle(mesh.triangles[i], shader, useDepth);
|
||||
}
|
||||
free(mesh.triangles);
|
||||
}
|
||||
|
||||
void drawModel(Model model, bool useDepth){
|
||||
for(int i = 0; i < model.mesh.numTriangles; i++){
|
||||
drawTriangle(model.mesh.triangles[i], model.shader, useDepth);
|
||||
|
|
|
@ -117,3 +117,16 @@ fp fp_atan2(fp y, fp x){
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
float isqrt(float x){
|
||||
float xhalf = 0.5f * x;
|
||||
int i = *(int*)&x; // store floating-point bits in integer
|
||||
i = 0x5f3759df - (i >> 1); // initial guess for Newton's method
|
||||
x = *(float*)&i; // convert new bits into float
|
||||
x = x*(1.5f - xhalf*x*x); // One round of Newton's method
|
||||
return x;
|
||||
}
|
||||
|
||||
fp fp_isqrt(fp x){
|
||||
return fp(isqrt(float(x)));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue