fix: now rotating just fine

This commit is contained in:
violette 2025-10-04 18:40:15 -04:00
parent f2bb638c0b
commit a1cd49180b

View file

@ -67,13 +67,6 @@ flipBuffers()
} }
} }
void
putPx(uint16_t x, uint16_t y, uint8_t c)
{
uint16_t pos = (GBA_SCREEN_W * y + x);
buffer[pos] = c;
}
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
#include <math.h> #include <math.h>
@ -82,8 +75,6 @@ putPx(uint16_t x, uint16_t y, uint8_t c)
#include <fcntl.h> #include <fcntl.h>
#include <float.h> #include <float.h>
#define VWIDTH 25
#define VHEIGHT 25
#define CUBE_WIDTH 10 #define CUBE_WIDTH 10
#define CUBE_WIDTH_FP ((1 << FP) * CUBE_WIDTH) #define CUBE_WIDTH_FP ((1 << FP) * CUBE_WIDTH)
@ -103,21 +94,16 @@ enum faces {
#define ACTION_STEP 0.1 #define ACTION_STEP 0.1
#define ACTION_STEP_FP ((1 << FP) * ACTION_STEP) #define ACTION_STEP_FP ((1 << FP) * ACTION_STEP)
#define SCALE 3 // how much is our initial render scaled #define SCALE 5 // how much is our initial render scaled
volatile FIXED_POINT K1 = 20; #define K1 (20)
volatile FIXED_POINT K2 = (2 * CUBE_WIDTH) + 10; #define K2 (2 * CUBE_WIDTH + 10)
#define MULT_FP(a,b) ((a * b) >> FP) #define MULT_FP(a, b) ((a * b) >> FP)
#define SQ(n) (n * n) #define SQ(n) (n * n)
#define SQ_FP(n) (MULT_FP(n, n)) #define SQ_FP(n) (MULT_FP(n, n))
#define PLOT_COORD(x, y, c) \
for (uint8_t i = 0 ; i < SCALE ; ++i) \
for (uint8_t j = 0 ; j < SCALE ; ++j) \
putPx(x * SCALE + i, j + (SCALE * y), chooseColor(c));
#define GET_ROTATE_X_Q(a) ({ float _a = (a) ; \ #define GET_ROTATE_X_Q(a) ({ float _a = (a) ; \
struct Quaternions q = {}; q.w = FLOAT2FIXED(cos(_a * .5)); \ struct Quaternions q = {}; q.w = FLOAT2FIXED(cos(_a * .5)); \
q.x = FLOAT2FIXED(sin(_a * .5)); q; }) q.x = FLOAT2FIXED(sin(_a * .5)); q; })
@ -149,6 +135,25 @@ init_colors()
PALETTE[lastPaletteIndex] = color_order[lastPaletteIndex]; PALETTE[lastPaletteIndex] = color_order[lastPaletteIndex];
} }
uint8_t
chooseColor(uint8_t c)
{
if (c >= 0 && c < NUM_FACES)
return c + 1; // palette 0 is bg
else
return 0;
}
void
putPx(uint16_t x, uint16_t y, uint8_t c)
{
for (uint8_t i = 0 ; i < SCALE ; ++i)
for (uint8_t j = 0 ; j < SCALE ; ++j) {
uint16_t pos = GBA_SCREEN_W * (y * SCALE + j) + x * SCALE + i;
buffer[pos] = chooseColor(c);
}
}
struct { struct {
uint8_t x; uint8_t x;
uint8_t y; uint8_t y;
@ -177,7 +182,7 @@ normalize(struct Quaternions *q)
{ {
float n = sqrt(FIXED2FLOAT(SQ_FP(q->w) + SQ_FP(q->x) + float n = sqrt(FIXED2FLOAT(SQ_FP(q->w) + SQ_FP(q->x) +
SQ_FP(q->y) + SQ_FP(q->z))); SQ_FP(q->y) + SQ_FP(q->z)));
if (n == 0 || n == 1) if (n == 0.|| n == 1.)
return; return;
q->w = FLOAT2FIXED(FIXED2FLOAT(q->w) / n); q->w = FLOAT2FIXED(FIXED2FLOAT(q->w) / n);
@ -192,17 +197,18 @@ mult(struct Quaternions *q, FIXED_POINT x, FIXED_POINT y, FIXED_POINT z)
//p = q * p * qbar //p = q * p * qbar
struct Quaternions res; struct Quaternions res;
// << 1 <=> * 2
res.w = 0; res.w = 0;
res.x = MULT_FP(x, (SQ_FP(q->w) + SQ_FP(q->x) - SQ_FP(q->y) - SQ_FP(q->z))) res.x = MULT_FP(x, (SQ_FP(q->w) + SQ_FP(q->x) - SQ_FP(q->y) - SQ_FP(q->z)))
+ (MULT_FP(y, (MULT_FP(q->x, q->y) - MULT_FP(q->w, q->z))) * 2) + (MULT_FP(y, (MULT_FP(q->x, q->y) - MULT_FP(q->w, q->z))) << 1)
+ (MULT_FP(z, (MULT_FP(q->x, q->z) + MULT_FP(q->w, q->y))) * 2); + (MULT_FP(z, (MULT_FP(q->x, q->z) + MULT_FP(q->w, q->y))) << 1);
res.y = (MULT_FP(x, (MULT_FP(q->x, q->y) + MULT_FP(q->w,q->z))) * 2) res.y = (MULT_FP(x, (MULT_FP(q->x, q->y) + MULT_FP(q->w,q->z))) << 1)
+ (MULT_FP(y, (SQ_FP(q->w) - SQ_FP(q->x) + SQ_FP(q->y) - SQ_FP(q->z)))) + (MULT_FP(y, (SQ_FP(q->w) - SQ_FP(q->x) + SQ_FP(q->y) - SQ_FP(q->z))))
+ (MULT_FP(z, (MULT_FP(q->y, q->z) - MULT_FP(q->w, q->x))) << 2); + (MULT_FP(z, (MULT_FP(q->y, q->z) - MULT_FP(q->w, q->x))) << 1);
res.z = (MULT_FP(x, (MULT_FP(q->x, q->z) - MULT_FP(q->w, q->y)))* 2) res.z = (MULT_FP(x, (MULT_FP(q->x, q->z) - MULT_FP(q->w, q->y))) << 1)
+ (MULT_FP(y, (MULT_FP(q->y, q->z) + MULT_FP(q->w, q->x))) * 2) + (MULT_FP(y, (MULT_FP(q->y, q->z) + MULT_FP(q->w, q->x))) << 1)
+ MULT_FP(z, (SQ_FP(q->w) - SQ_FP(q->x) - SQ_FP(q->y) + SQ_FP(q->z))); + MULT_FP(z, (SQ_FP(q->w) - SQ_FP(q->x) - SQ_FP(q->y) + SQ_FP(q->z)));
return res; return res;
@ -239,52 +245,17 @@ multQ(struct Quaternions *p, struct Quaternions *q)
} }
uint16_t
chooseColor(uint8_t c)
{
if (c >= 0 && c < NUM_FACES)
return c + 1; // palette 0 is bg
else
return 0;
}
uint8_t uint8_t
chooseMainFace() chooseMainFace()
{ {
int total = 0; // TODO
int faces[NUM_FACES] = {0}; return 0;
for (int k = 0; k < VWIDTH * VHEIGHT; ++k)
if (vertices[k] >= 0 && vertices[k] < NUM_FACES) {
faces[vertices[k]]++;
++total;
}
int max = 0, idx = 0;
for (int k = 0; k < NUM_FACES; ++k)
if (faces[k] > max) {
max = faces[k];
idx = k;
}
frontFacingFace = max > total * 0.9 ? idx : -1;
return frontFacingFace;
} }
// ISSUE the 4 vertices rendered do not make a convex quad
// we have to switch 2 vertices for that
#pragma GCC
uint8_t uint8_t
isInQuad(const uint16_t x, const uint16_t y, uint8_t current_face) isInQuad(const uint16_t x, const uint16_t y, uint8_t current_face)
{ {
uint16_t *points = (uint16_t *)&vertices[current_face * 8]; uint16_t *points = (uint16_t *)&vertices[current_face * 8];
// little hack
uint16_t tmpX = points[6], tmpY = points[7];
points[6] = points[4];
points[7] = points[5];
points[4] = tmpX;
points[5] = tmpY;
uint8_t pos = 0, neg = 0; uint8_t pos = 0, neg = 0;
int32_t d; int32_t d;
@ -294,15 +265,14 @@ isInQuad(const uint16_t x, const uint16_t y, uint8_t current_face)
return 1; return 1;
//Form a segment between the i'th point //Form a segment between the i'th point
int32_t x1 = points[2 * i]; uint16_t x1 = points[2 * i];
int32_t y1 = points[2 * i + 1]; uint16_t y1 = points[2 * i + 1];
//And the i+1'th, or if i is the last, with the first point //And the i+1'th, or if i is the last, with the first point
uint8_t i2 = (i + 1) % 4; uint8_t i2 = (i + 1) % 4;
int32_t x2 = points[2 * i2]; uint16_t x2 = points[2 * i2];
int32_t y2 = points[2 * i2 + 1]; uint16_t y2 = points[2 * i2 + 1];
//Compute the cross product //Compute the cross product
d = (x - x1) * (y2 - y1) - (y - y1) * (x2 - x1); d = (x - x1) * (y2 - y1) - (y - y1) * (x2 - x1);
@ -318,9 +288,27 @@ isInQuad(const uint16_t x, const uint16_t y, uint8_t current_face)
return 1; return 1;
} }
// the 4 vertices rendered do not make a convex quad
// we have to switch 2 vertices for that
// only works because we render 4 points left to right
void
makeConvex(uint16_t *points)
{
// little hack
uint16_t tmpX = points[6], tmpY = points[7];
points[6] = points[4];
points[7] = points[5];
points[4] = tmpX;
points[5] = tmpY;
}
void void
fillQuads(uint8_t current_face) fillQuads(uint8_t current_face)
{ {
makeConvex((uint16_t *)&vertices[current_face * 8]);
uint16_t top = UINT16_MAX, bot = 0, left = UINT16_MAX, right = 0; uint16_t top = UINT16_MAX, bot = 0, left = UINT16_MAX, right = 0;
for (uint8_t k = 0 ; k < 8 ; ++k) { for (uint8_t k = 0 ; k < 8 ; ++k) {
const uint16_t item = vertices[current_face * 8 + k]; const uint16_t item = vertices[current_face * 8 + k];
@ -338,10 +326,10 @@ fillQuads(uint8_t current_face)
} }
} }
for (uint16_t y = top ; y <= bot ; ++y) { for (uint16_t y = top ; y <= bot; ++y) {
for (uint16_t x = left ; x <= right ; ++x) { for (uint16_t x = left ; x <= right ; ++x) {
if (isInQuad(x, y, current_face)) if (isInQuad(x, y, current_face))
PLOT_COORD(x, y, current_face); putPx(x, y, current_face);
} }
} }
} }
@ -517,7 +505,7 @@ uint8_t
getInput() getInput()
{ {
// TODO // TODO
uint8_t c = 'd'; uint8_t c = 's';
handleAngle(c); handleAngle(c);
return c; return c;
} }
@ -533,7 +521,7 @@ main()
memset(MEM_VRAM_MODE4, 0, GBA_SCREEN_H * GBA_SCREEN_W); memset(MEM_VRAM_MODE4, 0, GBA_SCREEN_H * GBA_SCREEN_W);
memset((uint16_t *)vertices, UINT16_MAX, sizeof(uint16_t) * NUM_FACES * 4 * 2); memset((uint16_t *)vertices, UINT16_MAX, sizeof(uint16_t) * NUM_FACES * 4 * 2);
//zBuff is not correct data struct, need a map or smth //zBuff is not correct data struct, need a map or smth
memset((uint16_t *)zBuffer, 0, NUM_FACES * 2 * sizeof(FIXED_POINT)); memset((FIXED_POINT *)zBuffer, 0, NUM_FACES * 2 * sizeof(FIXED_POINT));
for (FIXED_POINT cubeX = -CUBE_WIDTH_FP + 1 * (1 << FP); for (FIXED_POINT cubeX = -CUBE_WIDTH_FP + 1 * (1 << FP);
cubeX <= CUBE_WIDTH_FP - 1 * (1 << FP); cubeX += STEP_FP - 2 * (1 << FP)) { cubeX <= CUBE_WIDTH_FP - 1 * (1 << FP); cubeX += STEP_FP - 2 * (1 << FP)) {