3dcam-headers/3dcam-cosTable-lerp-atantable-psqrt-nodpq-quads.c
2021-02-03 15:35:51 +01:00

1247 lines
50 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 3dcam
// With huge help from @NicolasNoble : https://discord.com/channels/642647820683444236/646765703143227394/796876392670429204
/* PSX screen coordinate system
*
* Z+
* /
* /
* +------X+
* /|
* / |
* / Y+
* eye */
#include <sys/types.h>
#include <libgte.h>
#include <libgpu.h>
#include <libetc.h>
#include <stdio.h>
// Precalculated sin/cos values
//~ #include "psin.c"
//~ #include "pcos.c"
#include "atan.c"
// Sample vector model
#include "coridor.c"
//~ #include "gnd.c"
#define VMODE 0
#define SCREENXRES 320
#define SCREENYRES 240
#define CENTERX SCREENXRES/2
#define CENTERY SCREENYRES/2
#define OTLEN 256 // Maximum number of OT entries
#define PRIMBUFFLEN 2260 * sizeof(POLY_GT3) // Maximum number of POLY_GT3 primitives
// atantable
#define SWAP(a,b,c) {(c)=(a); (a)=(b); (b)=(c);} // swap(x, y, buffer)
//~ extern ushort rcossin_tbl[];
// Display and draw environments, double buffered
DISPENV disp[2];
DRAWENV draw[2];
u_long ot[2][OTLEN] = {0}; // Ordering table (contains addresses to primitives)
char primbuff[2][PRIMBUFFLEN] = {0}; // Primitive list // That's our prim buffer
//~ int primcnt=0; // Primitive counter
char * nextpri = primbuff[0]; // Primitive counter
char db = 0; // Current buffer counter
CVECTOR BGc = {50, 50, 75, 0};
VECTOR BKc = {100, 100, 100, 0};
// Local color matrix
//~ static MATRIX cmat = {
//~ /* light source #0, #1, #2, */
//~ ONE, 0, 0, /* R */
//~ 0, ONE, 0, /* G */
//~ 0, 0, ONE, /* B */
//~ };
//~ // local light matrix : Direction and reach of each light source.
//~ // Each light is aligned with the axis, hence direction is in the same coordinate system as the PSX (Y-axis down)
//~ // One == 4096 is reach/intensity of light source
//~ static MATRIX lgtmat = {
//~ // X Y Z
//~ ONE, 0, 0, // Light 0
//~ 0,0,0, // Light 1
//~ 0,0,0 // Light 2
//~ };
// Light
//~ MATRIX rottrans;
MATRIX rotlgt;
SVECTOR lgtang = {0, 0, 0};
MATRIX light;
//~ SVECTOR lgtang = {1024, -512, 1024};
static int m_cosTable[512]; // precalc costable
static const unsigned int DC_2PI = 2048; // this is from gere : https://github.com/grumpycoders/Balau/blob/master/tests/test-Handles.cc#L20-L102
static const unsigned int DC_PI = 1024;
static const unsigned int DC_PI2 = 512;
short vs;
typedef struct{
int x, xv; // x: current value += xv : new value
int y, yv; // x,y,z, vx, vy, vz are in PSX units (ONE == 4096)
int z, zv;
int pan, panv;
int tilt, tiltv;
int rol;
VECTOR pos;
SVECTOR rot;
SVECTOR dvs;
MATRIX mat;
} CAMERA;
CAMERA camera = {
0,0,
0,0,
0,0,
0,0,
0,0,
0,
{0,0,0},
{0,0,0},
{0,0,0}
};
//~ //vertex anim
//~ typedef struct {
//~ int nframes; // number of frames e.g 20
//~ int nvert; // number of vertices e.g 21
//~ SVECTOR data[]; // vertex pos as SVECTORs e.g 20 * 21 SVECTORS
//~ } VANIM;
//Pad
int pressed = 0;
// Cam stuff
int camMode = 2;
long timeB = 0;
u_long triCount = 0;
// Prototypes
// Sin/Cos Table
void generateTable(void);
int ncos(u_int t);
int nsin(u_int t);
// Atan table
int patan(int x, int y);
//sqrt
u_int psqrt(u_int n);
// PSX setup
void init(void);
void display(void);
// Utils
void LoadTexture(u_long * tim, TIM_IMAGE * tparam);
int cliptest3(short * v1);
int lerp(int start, int end, int factor); // FIXME : not working as it should
SVECTOR SVlerp(SVECTOR start, SVECTOR end, int factor); // FIXME
// Camera
void getCameraXZ(int * x, int * z, int actorX, int actorZ, int angle, int distance);
void applyCamera(CAMERA * cam);
void setCameraPos(VECTOR pos, SVECTOR rot);
// Physics
VECTOR getCollision(BODY one, BODY two);
void applyAcceleration(BODY * actor);
void callback();
int main() {
// Mesh stuff
int i;
long t, p, OTz, OTc, Flag, nclip; // t == vertex count, p == depth cueing interpolation value, OTz == value to create Z-ordered OT, Flag == see LibOver47.pdf, p.143
POLY_GT3 * poly;
DIVPOLYGON3 div = { 0 };
div.pih = SCREENXRES;
div.piv = SCREENYRES;
//~ MATRIX PolyMatrix = {0};
CVECTOR outCol ={0,0,0,0};
CVECTOR outCol1 ={0,0,0,0};
CVECTOR outCol2 ={0,0,0,0};
MATRIX Cmatrix = {0};
init();
generateTable();
VSyncCallback(callback);
//~ SetLightMatrix(&LLM);
SetColorMatrix(&cmat);
SetBackColor(BKc.vx,BKc.vy,BKc.vz);
//~ SetFarColor(BGc.r, BGc.g, BGc.b);
SetFogNearFar(1200, 1600, SCREENXRES);
for (int k = 0; k < sizeof(meshes)/sizeof(TMESH *); k++){
LoadTexture(meshes[k]->tim_data, meshes[k]->tim);
}
// physics
short physics = 1;
long time = 0;
long sec = 0;
long d1y, d2y;
long d1x, d2x;
long d1z, d2z;
//~ VECTOR gForce = {0, 0, 0, 0}; // 9.81 == 4096
VECTOR gForce = {0, 981, 100, 0}; // 9.81 == 4096
//~ modelobject_body.position = modelobject_pos;
// Actor start pos
modelobject_body.position.vx = modelobject_pos.vx = 50;
//~ modelobject_body.position.vz = 0;
//~ modelobject_body.position.vy = -350;
//~ modelobject_body.position.vz = modelobject_pos.vz = 664;
//~ // Cam stuff
//~ int camMode = 0;
VECTOR posToActor = {0, 0, 0, 0}; // position of camera relative to actor
VECTOR theta = {0, 0, 0, 0}; // rotation angles for the camera to point at actor
int angle = 0; //PSX units = 4096 == 360° = 2Pi
//~ int endCam = 0;
int dist = 0; //PSX units
int lerping = 0;
// Vertex anim
//~ SVECTOR interpCache[5];
SVECTOR a,b,c = {0,0,0,0};
short timediv = 1;
int atime = 0;
//~ if(camMode == 4){
//~ camera.pos.vx = 690;
//~ camera.pos.vz = 200;
//~ camera.pos.vy = 140;
//~ camera.pos.vx += lerp(490, -50, 128);
//~ camera.pos.vz += lerp(100, 50, 128);
//~ camera.pos.vy += lerp(100, 80, 128);
//~ }
//~ modelobject_rot.vy = -1024;
for (int k = 0; k < sizeof(meshes)/sizeof(meshes[0]); k++){
triCount += meshes[k]->tmesh->len;
}
// Main loop
while (1) {
//~ timeB = time;
time ++;
timediv = 2;
if (time % timediv == 0){
atime ++;
}
//~ timediv = 1;
//~ getCameraXZ(&camera.x, &camera.z, modelobject_pos.vx, modelobject_pos.vz, angle, dist);
//~ if (angle > 2048 || angle < -2048){
//~ angle = 0;
//~ }
//~ if (modelobject_rot.vy > 4096 || modelobject_rot.vy < -4096){
//~ modelobject_rot.vy = 0;
//~ }
long dt;
//~ // Physics
//~ if (time%2 == 0){
//~ theta.vy = -ratan2(posToActor.vx, posToActor.vz) ;
//~ theta.vx = 1024 - ratan2(dist, posToActor.vy);
// using atantable
theta.vy = patan(posToActor.vx, posToActor.vz) / 16 - 1024 ;
theta.vx = patan(dist, posToActor.vy)/16;
if(camMode != 2){
camera.rot.vy = theta.vy;
// using csin/ccos, no need for theta
// camera.rot.vy = angle;
camera.rot.vx = theta.vx;
}
if(camMode != 4){
lerping = 0;
}
if(camMode == 0){ // Camera follows actor with lerp for rotations
dist = 150;
camera.pos.vx = -(camera.x/ONE);
//~ camera.pos.vy = -(camera.y/ONE);
camera.pos.vz = -(camera.z/ONE);
//~ modelobject_rot.vy = -1024;
// mode 0 : Camera rotates to pos with easeout
getCameraXZ(&camera.x, &camera.z, modelobject_pos.vx, modelobject_pos.vz, angle, dist);
//~ angle += lerp(camera.rot.vy, 2088, 64);
//~ if (modelobject_rot.vy - camera.rot.vy < 4096){
//~ endCam = modelobject_rot.vy;
//~ } else {
//~ endCam = camera.rot.vy;
//~ }
angle += lerp(camera.rot.vy, modelobject_rot.vy, 128);
}
if (camMode == 1){ // mode 1 : Camera rotates continuously
dist = 150;
camera.pos.vx = -(camera.x/ONE);
//~ camera.pos.vy = -(camera.y/ONE);
camera.pos.vz = -(camera.z/ONE);
getCameraXZ(&camera.x, &camera.z, modelobject_pos.vx, modelobject_pos.vz, angle, dist);
angle += 10;
//~ angle = -modelobject_rot.vy / 2;
}
if (camMode == 3){ // mode 3 : Fixed Camera with actor tracking
//~ dist = SquareRoot0( (posToActor.vx * posToActor.vx ) + (posToActor.vz * posToActor.vz) );
dist = psqrt( (posToActor.vx * posToActor.vx ) + (posToActor.vz * posToActor.vz) );
camera.pos.vx = 290;
camera.pos.vz = 100;
camera.pos.vy = 180;
}
if (camMode == 2){ // mode 2 : Fixed Camera
setCameraPos(camStartPos.pos, camStartPos.rot);
//~ camera.pos.vx = camStartPos.pos.vx;
//~ camera.pos.vy = camStartPos.pos.vy;
//~ camera.pos.vz = camStartPos.pos.vz;
//~ camera.rot.vx = camStartPos.rot.vx;
//~ camera.rot.vy = camStartPos.rot.vy;
}
if(camMode == 4){ // Flyby mode from camStart to camEnd
if (!lerping){
// Set cam start position
camera.pos.vx = camPath.points[camPath.cursor].vx;
camera.pos.vy = camPath.points[camPath.cursor].vy;
camera.pos.vz = camPath.points[camPath.cursor].vz;
lerping = 1;
}
// Find distance between cam and actor
// Psyq sqrt func
//~ dist = SquareRoot0( (posToActor.vx * posToActor.vx ) + (posToActor.vz * posToActor.vz) );
// Pre calculated sqrt ( see psqrt() )
dist = psqrt( (posToActor.vx * posToActor.vx ) + (posToActor.vz * posToActor.vz) );
short r = camPath.points[camPath.cursor+1].vx - camera.pos.vx;
short s = camPath.points[camPath.cursor+1].vy - camera.pos.vy;
short t = camPath.points[camPath.cursor+1].vz - camera.pos.vz;
//~ camera.pos.vx += lerp(camPath.points[camPath.cursor].vx, camPath.points[camPath.cursor+1].vx, 64);
//~ camera.pos.vy += lerp(camPath.points[camPath.cursor].vy, camPath.points[camPath.cursor+1].vy, 64);
//~ camera.pos.vz += lerp(camPath.points[camPath.cursor].vz, camPath.points[camPath.cursor+1].vz, 64);
// easeOut
camera.pos.vx += lerp(camera.pos.vx, camPath.points[camPath.cursor+1].vx, 128);
camera.pos.vy += lerp(camera.pos.vy, camPath.points[camPath.cursor+1].vy, 128);
camera.pos.vz += lerp(camera.pos.vz, camPath.points[camPath.cursor+1].vz, 128);
//~ if ( camera.pos.vx <= camPath.points[camPath.cursor+1].vx ||
//~ camera.pos.vy >= camPath.points[camPath.cursor+1].vy ||
//~ camera.pos.vz <= camPath.points[camPath.cursor+1].vz){
//~ camPath.cursor ++;
//~ }
if ( camera.pos.vx + r == camPath.points[camPath.cursor+1].vx &&
camera.pos.vy + s == camPath.points[camPath.cursor+1].vy &&
camera.pos.vz + t == camPath.points[camPath.cursor+1].vz){
camPath.cursor ++;
}
if ( camPath.cursor == camPath.len - 1 ){
lerping = 0;
camPath.cursor = 0;
}
}
// Testing stuff
//~ if (modelobject_rot.vy < 2048 || modelobject_rot.vy > -2048){
//~ if (time % 240 == 0){
//~ modelobject_rot.vy += 1024 ;
//~ }
//~ modelobject_body.position.vx ++;
//~ dist += 10;
//~ dt = time/180+1 - time/180;
if (physics){
if(time%2 == 0){
for ( int k = 0; k < sizeof(meshes)/sizeof(meshes[0]);k ++){
if ( *meshes[k]->isRigidBody == 1 ) {
//~ dt = 1;
//~ VECTOR acceleration = {meshes[k]->body->gForce.vx / meshes[k]->body->mass, meshes[k]->body->gForce.vy / meshes[k]->body->mass, meshes[k]->body->gForce.vz / meshes[k]->body->mass};
//~ meshes[k]->body->velocity.vx += acceleration.vx * dt;
//~ meshes[k]->body->velocity.vy += acceleration.vy * dt;
//~ meshes[k]->body->velocity.vz += acceleration.vz * dt;
//~ meshes[k]->body->position.vx += meshes[k]->body->velocity.vx * dt;
//~ meshes[k]->body->position.vy += meshes[k]->body->velocity.vy * dt;
//~ meshes[k]->body->position.vz += meshes[k]->body->velocity.vz * dt;
//~ d1x = (meshes[k]->body->position.vx - meshes[k]->body->max.vx) - (modelgnd_body.position.vx + modelgnd_body.min.vx);
//~ d1y = (meshes[k]->body->position.vy - meshes[k]->body->min.vy) - (modelgnd_body.position.vy + modelgnd_body.min.vy);
//~ d1z = (meshes[k]->body->position.vz - meshes[k]->body->max.vz) - (modelgnd_body.position.vz + modelgnd_body.min.vz);
//~ d2x = (modelgnd_body.position.vx + modelgnd_body.max.vx) - (meshes[k]->body->position.vx + meshes[k]->body->max.vx);
//~ d2y = (modelgnd_body.position.vy + modelgnd_body.max.vy) - (meshes[k]->body->position.vy + meshes[k]->body->max.vy);
//~ d2z = (modelgnd_body.position.vz + modelgnd_body.max.vz) - (meshes[k]->body->position.vz + meshes[k]->body->max.vz);
applyAcceleration(meshes[k]->body);
VECTOR col;
col = getCollision( *meshes[k]->body , modelgnd_body);
//~ if (d1x >= 0 || d2x >= 0){//Touching}
//~ if (d1z >= 0 || d2z >= 0){//Touching}
//~ if (d1y >= 0 || d2y >= 0){//Touching}
//~ if (d1x >= 0 && d2x >= 0){
if (col.vx){
meshes[k]->pos->vx = meshes[k]->body->position.vx;
//~ modelobject_pos.vx = modelobject_body.position.vx;
}
//~ if (d1y >= 0 && d2y >= 0){
if (col.vy){
meshes[k]->pos->vy = meshes[k]->body->position.vy + 15;
//modelobject_pos.vy = modelobject_body.position.vy;
}
if (col.vz){
meshes[k]->pos->vz = meshes[k]->body->position.vz;
//~ modelobject_pos.vz = meshes[k]->body->position.vz;
//~ modelobject_pos.vz = modelobject_body.position.vz;
}
//~ if ( d1x < 0 || d2x < 0 ) { gForce.vx *= -1; }
//~ if ( d1y < 0 || d2y < 0 ) { gForce.vy *= -1; }
//~ if ( d1z < 0 || d2z < 0 ) { gForce.vz *= -1; }
if ( !(col.vx) ) { meshes[k]->body->gForce.vx *= -1; }
if ( !(col.vy) ) { meshes[k]->body->gForce.vy *= -1; }
if ( !(col.vz) ) { meshes[k]->body->gForce.vz *= -1; }
//~ if ( d1y < 0 || d2y < 0 ||
//~ d1z < 0 || d2z < 0 ||
//~ d1x < 0 || d2x < 0 ) {
if ( !(col.vx) ||
!(col.vy) ||
!(col.vz)
) {
meshes[k]->body->velocity.vy = meshes[k]->body->velocity.vx = meshes[k]->body->velocity.vz = 0;
//~ meshes[k]->pos->vy = meshes[k]->body->position.vy = -40 ;
//~ modelobject_pos.vy = meshes[k]->body->position.vy = 96;
}
//~ d1y = d2y = d1x = d2x = d1z = d2z = 0;
}
}
}
}
// Camera setup
//~ camera.pos.vx = -(camera.x/ONE);
//~ camera.pos.vy = -(camera.y/ONE);
//~ camera.pos.vz = -(camera.z/ONE);
// position of cam relative to actor
//~ if (DposToActor.vx - posToActor.vx || DposToActor.vy - posToActor.vy || DposToActor.vz - posToActor.vz ){
posToActor.vx = modelobject_pos.vx + camera.pos.vx;
posToActor.vz = modelobject_pos.vz + camera.pos.vz;
posToActor.vy = modelobject_pos.vy + camera.pos.vy;
//~ DposToActor = posToActor;
//~ };
// find dist between actor and cam
//~ dist = csqrt((posToActor.vx * posToActor.vx * 4096) + (posToActor.vz * posToActor.vz * 4096));
//~ dist = SquareRoot0( (posToActor.vx * posToActor.vx ) + (posToActor.vz * posToActor.vz) );
// find angles between cam and actor
//~ theta.vy = ratan2(posToActor.vx, posToActor.vz);
//~ theta.vx = 1024 - ratan2(dist, posToActor.vy);
//~ camera.rot.vy = - theta.vy;
// using csin/ccos, no need for theta
// camera.rot.vy = angle;
//~ camera.rot.vx = theta.vx;
//~ applyCamera(&camera);
// Clear the current OT
ClearOTagR(ot[db], OTLEN);
for (int k = 0; k < sizeof(meshes)/sizeof(meshes[0]); k++){
// Render the sample vector model
t=0;
if (*meshes[k]->isRigidBody){
//~ PushMatrix(); // Push current matrix on the stack
//~ SetColorMatrix(&camera.mat);
RotMatrix_gte(meshes[k]->rot, meshes[k]->mat); // Apply rotation matrix
TransMatrix(meshes[k]->mat, meshes[k]->pos); // Apply translation matrix
CompMatrix(&camera.mat, meshes[k]->mat, meshes[k]->mat); // Was using &PolyMatrix instead of meshes[k]->mat
SetRotMatrix(meshes[k]->mat); // Set default rotation matrix - Was using &PolyMatrix instead of meshes[k]->mat
SetTransMatrix(meshes[k]->mat); // Was using &PolyMatrix instead of meshes[k]->mat
}
// modelCube is a TMESH, len member == # vertices, but here it's # of triangle... So, for each tri * 3 vertices ...
for (i = 0; i < (meshes[k]->tmesh->len * 3); i += 3) {
poly = (POLY_GT3 *)nextpri;
SetPolyGT3(poly);
// Can use ?
//~ RotMeshPrimS_GCT3();
if (*meshes[k]->isPrism){
((POLY_GT3 *)poly)->tpage = getTPage(meshes[k]->tim->mode&0x3, 0,
draw[!db].clip.x,
draw[!db].clip.y
);
setUV3(poly, (poly->x0 < 0? 0 : poly->x0 > 255? 255 : poly->x0),
(poly->y0 < 0? 0 : poly->y0 > 224? 224 : poly->y0),
(poly->x1 < 0? 0 : poly->x1 > 255? 255 : poly->x1),
(poly->y1 < 0? 0 : poly->y1 > 224? 224 : poly->y1),
(poly->x2 < 0? 0 : poly->x2 > 255? 255 : poly->x2),
(poly->y2 < 0? 0 : poly->y2 > 224? 224 : poly->y2)
);
} else {
((POLY_GT3 *)poly)->tpage = getTPage(meshes[k]->tim->mode&0x3, 0,
meshes[k]->tim->prect->x,
meshes[k]->tim->prect->y
);
setUV3(poly, meshes[k]->tmesh->u[i].vx , meshes[k]->tmesh->u[i].vy + meshes[k]->tim->prect->y,
meshes[k]->tmesh->u[i+1].vx, meshes[k]->tmesh->u[i+1].vy + meshes[k]->tim->prect->y,
meshes[k]->tmesh->u[i+2].vx, meshes[k]->tmesh->u[i+2].vy + meshes[k]->tim->prect->y);
}
//~ setUV3(0, 0, 32, 0, 32, 32);
//~ setUV3(poly, meshes[k]->tmesh->u[i].vx , meshes[k]->tmesh->u[i].vy + meshes[k]->tim->prect->y,
//~ meshes[k]->tmesh->u[i+1].vx, meshes[k]->tmesh->u[i+1].vy + meshes[k]->tim->prect->y,
//~ meshes[k]->tmesh->u[i+2].vx, meshes[k]->tmesh->u[i+2].vy + meshes[k]->tim->prect->y);
// Rotate, translate, and project the vectors and output the results into a primitive
//~ OTz = RotTransPers(&meshes[k]->tmesh->v[meshes[k]->index[t]] , (long*)&poly->x0, meshes[k]->p, &Flag);
//~ OTz += RotTransPers(&meshes[k]->tmesh->v[meshes[k]->index[t+1]], (long*)&poly->x1, meshes[k]->p, &Flag);
//~ OTz += RotTransPers(&meshes[k]->tmesh->v[meshes[k]->index[t+2]], (long*)&poly->x2, meshes[k]->p, &Flag);
//~ for (int i = 0; i < 1; i++ ){
//~ for (int j = 0; j < modelCylindre_anim.nvert; j++){
//~ FntPrint("%d - ",modelCylindre_anim.data[i * modelCylindre_anim.nvert + j].vx);
//~ }
//~ }
if (*meshes[k]->isAnim){
//~ SVECTOR a,b,c = {0,0,0,0};
//~ for (int f = 0; f < 5; f++){
//~ interpCache[f] = SVlerp( (SVECTOR) meshes[k]->anim->data[0 * modelCylindre_anim.nvert + meshes[k]->index[t]], (SVECTOR) meshes[k]->anim->data[10 * modelCylindre_anim.nvert + meshes[k]->index[t]], 2048);
//~ interpCache[f+1] = SVlerp( (SVECTOR) meshes[k]->anim->data[0 * modelCylindre_anim.nvert + meshes[k]->index[t]], (SVECTOR) meshes[k]->anim->data[10 * modelCylindre_anim.nvert + meshes[k]->index[t]], 2048);
//~ interpCache[f+2] = SVlerp( (SVECTOR) meshes[k]->anim->data[0 * modelCylindre_anim.nvert + meshes[k]->index[t]], (SVECTOR) meshes[k]->anim->data[10 * modelCylindre_anim.nvert + meshes[k]->index[t]], 2048);
//~ }
//~ SVECTOR start = meshes[k]->anim->data[0 * modelCylindre_anim.nvert + meshes[k]->index[t]];
//~ SVECTOR end = meshes[k]->anim->data[10 * modelCylindre_anim.nvert + meshes[k]->index[t]];
//~ if (a.vx != 0 && b.vx != 0 && c.vx != 0){
//~ SVECTOR d,e,f;
//~ d = SVlerp( (SVECTOR) a, (SVECTOR) meshes[k]->anim->data[0 * modelCylindre_anim.nvert + meshes[k]->index[t]], 2048);
//~ e = SVlerp( (SVECTOR) b, (SVECTOR) meshes[k]->anim->data[0 * modelCylindre_anim.nvert + meshes[k]->index[t+1]], 2048);
//~ f = SVlerp( (SVECTOR) c, (SVECTOR) meshes[k]->anim->data[0 * modelCylindre_anim.nvert + meshes[k]->index[t+2]], 2048);
//~ addVector( &a , &d );
//~ addVector( &b , &e );
//~ addVector( &c , &f );
//~ } else {
//~ a = (SVECTOR) meshes[k]->anim->data[10 * modelCylindre_anim.nvert + meshes[k]->index[t]];
//~ b = (SVECTOR) meshes[k]->anim->data[10 * modelCylindre_anim.nvert + meshes[k]->index[t+1]];
//~ c = (SVECTOR) meshes[k]->anim->data[10 * modelCylindre_anim.nvert + meshes[k]->index[t+2]];
//~ }
//~ a.vx = lerp(start.vx, end.vx, 2048);
//~ a.vy = lerp(meshes[k]->anim->data[0 * modelCylindre_anim.nvert + meshes[k]->index[t]].vy, meshes[k]->anim->data[10 * modelCylindre_anim.nvert + meshes[k]->index[t]].vy, 2048);
//~ a.vz = lerp(meshes[k]->anim->data[0 * modelCylindre_anim.nvert + meshes[k]->index[t]].vz, meshes[k]->anim->data[10 * modelCylindre_anim.nvert + meshes[k]->index[t]].vz, 2048);
//~ b = meshes[k]->anim->data[10 * modelCylindre_anim.nvert + meshes[k]->index[t+1]];
//~ c = meshes[k]->anim->data[10 * modelCylindre_anim.nvert + meshes[k]->index[t+2]];
//~ SVlerp(meshes[k]->anim->data[ 0 * modelCylindre_anim.nvert + meshes[k]->index[t]], meshes[k]->anim->data[ 10 * modelCylindre_anim.nvert + meshes[k]->index[t]],64, a);
//~ SVlerp(meshes[k]->anim->data[ 0 * modelCylindre_anim.nvert + meshes[k]->index[t+1]], meshes[k]->anim->data[ 10 * modelCylindre_anim.nvert + meshes[k]->index[t+1]],64, b);
//~ SVlerp(meshes[k]->anim->data[ 0 * modelCylindre_anim.nvert + meshes[k]->index[t+2]], meshes[k]->anim->data[ 10 * modelCylindre_anim.nvert + meshes[k]->index[t+2]],64, c);
//~ FntPrint("%d %d %d\n", meshes[k]->anim->data[0 * modelCylindre_anim.nvert + meshes[k]->index[t]].vz, meshes[k]->anim->data[10 * modelCylindre_anim.nvert + meshes[k]->index[t]].vz, a.vz);
//~ FntPrint("%d %d %d\n", c.vx, c.vy, c.vz);
//~ FntPrint("%d %d %d\n", a.vx, b.vx, c.vx);
// TODO: export normals too
OTz = RotAverage3(
//~ &a,&b,&c,
&meshes[k]->anim->data[ atime%19 * modelCylindre_anim.nvert + meshes[k]->index[t]],
&meshes[k]->anim->data[ atime%19 * modelCylindre_anim.nvert + meshes[k]->index[t+1]],
&meshes[k]->anim->data[ atime%19 * modelCylindre_anim.nvert + meshes[k]->index[t+2]],
(long*)&poly->x0, (long*)&poly->x1, (long*)&poly->x2,
meshes[k]->p,
&Flag
);
} else {
OTz = RotAverage3(
&meshes[k]->tmesh->v[meshes[k]->index[t]],
&meshes[k]->tmesh->v[meshes[k]->index[t+1]],
&meshes[k]->tmesh->v[meshes[k]->index[t+2]],
(long*)&poly->x0, (long*)&poly->x1, (long*)&poly->x2,
meshes[k]->p,
&Flag
);
}
//~ OTc = OTz>>4;
//~ if (OTc < 15) {
//~ if (OTc > 5) div.ndiv = 1; else div.ndiv = 2;
//~ DivideGT3(
//~ // Vertex coord
//~ &meshes[k]->tmesh->v[meshes[k]->index[t]],
//~ &meshes[k]->tmesh->v[meshes[k]->index[t+1]],
//~ &meshes[k]->tmesh->v[meshes[k]->index[t+2]],
//~ // UV coord
//~ meshes[k]->tmesh->u[i],
//~ meshes[k]->tmesh->u[i+1],
//~ meshes[k]->tmesh->u[i+2],
//~ // Color
//~ meshes[k]->tmesh->c[i],
//~ meshes[k]->tmesh->c[i+1],
//~ meshes[k]->tmesh->c[i+2],
//~ // Gpu packet
//~ poly,
//~ &ot[db][OTz],
//~ &div);
//~ // Increment primitive list pointer
//~ nextpri += ( (sizeof(POLY_GT4) + 2) / 3 ) * (( 1 << ( div.ndiv )) << ( div.ndiv ));
//NumPrims += ((1<<(div.ndiv))<<(div.ndiv));
//~ }
// Light source stages
// 1 . Normal vector N (meshes[k]->tmesh->n) x World matrix ( meshes[k]->mat ) => vector(NW)
// 2 . Light source vector (light->dir) x Normal World coords NW => vector(L)
// 3 . Light source effect L x Light source color (light->color) => vector(LI)
// 4 . LI + BK = LT
// 5 . Vertex color ( &meshes[k]->tmesh->c[i] ) * LT
// Stages 1,2,3 : L = OuterProduct0( (VECTOR)light->dir, ApplyMatrix( (MATRIX)meshes[k]->mat, (VECTOR)meshes[k]->tmesh->n[] ) )
//
// Lij = ApplyMatrix( (MATRIX)meshes[k]->mat, (VECTOR)light->dir)
// SetLocalLightMatrix(Lij)
// L = ApplyMatrix( Lij, (VECTOR)meshes[k]->tmesh->n[] )
//~ // NormalColorDpq3()
// Interpolate a primary color vector and far color
//~ NormalColorDpq3(&meshes[k]->tmesh->n[i],
//~ &meshes[k]->tmesh->n[i+1],
//~ &meshes[k]->tmesh->n[i+2],
//~ &meshes[k]->tmesh->c[i],
//~ *meshes[k]->p,
//~ &outCol,&outCol1,&outCol2
//~ );
//~ if (*meshes[k]->isAnim){
//~ NormalColorDpq(&meshes[k]->anim->normals[ atime%19 * modelCylindre_anim.nvert + meshes[k]->index[t]], &meshes[k]->tmesh->c[meshes[k]->index[t]], *meshes[k]->p, &outCol);
//~ NormalColorDpq(&meshes[k]->anim->normals[ atime%19 * modelCylindre_anim.nvert + meshes[k]->index[t+1]], &meshes[k]->tmesh->c[meshes[k]->index[t+1]], *meshes[k]->p, &outCol1);
//~ NormalColorDpq(&meshes[k]->anim->normals[ atime%19 * modelCylindre_anim.nvert + meshes[k]->index[t+2]], &meshes[k]->tmesh->c[meshes[k]->index[t+2]], *meshes[k]->p, &outCol2);
//~ } else {
NormalColorDpq(&meshes[k]->tmesh->n[meshes[k]->index[t]] , &meshes[k]->tmesh->c[meshes[k]->index[t]], *meshes[k]->p, &outCol);
NormalColorDpq(&meshes[k]->tmesh->n[meshes[k]->index[t+1]], &meshes[k]->tmesh->c[meshes[k]->index[t+1]], *meshes[k]->p, &outCol1);
NormalColorDpq(&meshes[k]->tmesh->n[meshes[k]->index[t+2]], &meshes[k]->tmesh->c[meshes[k]->index[t+2]], *meshes[k]->p, &outCol2);
//~ }
//~ DpqColor3(&meshes[k]->tmesh->c[i],
//~ &meshes[k]->tmesh->c[i+1],
//~ &meshes[k]->tmesh->c[i+2],
//~ *meshes[k]->p,
//~ &outCol,&outCol1,&outCol2
//~ );
if (*meshes[k]->isPrism){
setRGB0(poly, meshes[k]->tmesh->c[i].r, meshes[k]->tmesh->c[i+1].g, meshes[k]->tmesh->c[i+2].b);
setRGB1(poly, meshes[k]->tmesh->c[i+1].r, meshes[k]->tmesh->c[i+1].g, meshes[k]->tmesh->c[i+1].b);
setRGB2(poly, meshes[k]->tmesh->c[i+2].r, meshes[k]->tmesh->c[i+2].g, meshes[k]->tmesh->c[i+2].b);
} else {
setRGB0(poly, outCol.r, outCol.g , outCol.b);
setRGB1(poly, outCol1.r, outCol1.g, outCol1.b);
setRGB2(poly, outCol2.r, outCol2.g, outCol2.b);
}
// Sort the primitive into the OT
//~ OTz /= 3;
// cliptest3((short *)&meshes[k]->tmesh->v[meshes[k]->index[t]])
//~ if ((OTz > 0) && (OTz < OTLEN) && (*meshes[k]->p < 2048)){
if ((OTz > 0) && (OTz < OTLEN) && (*meshes[k]->p < 4096)){
AddPrim(&ot[db][OTz-2], poly); // OTz - 2
}
nextpri += sizeof(POLY_GT3);
t+=3;
//~ if (*meshes[k]->isRigidBody){
//~ PopMatrix(); // Pull previous matrix from stack
//~ }
}
RotMatrix(&lgtang, &rotlgt);
// MulMatrix(&rotlgt, &rottrans);
MulMatrix0(&lgtmat, &rotlgt, &light);
SetLightMatrix(&light);
//~ if (*meshes[k]->isRigidBody){
//~ SetRotMatrix(&camera.mat);
//~ SetTransMatrix(&camera.mat);
//~ }
applyCamera(&camera);
}
//~ applyCamera(&camera);
FntPrint("Time : %d %d dt :%d\n",time, atime, dt);
FntPrint("Tricount: %d OTz: %d\nOTc: %d, p: %d\n",triCount, OTz, OTc, *meshes[2]->p);
FntPrint("isPrism: %d\n", *meshobject.isPrism);
FntPrint("L1: %d %d %d\n", light.m[0][0],light.m[0][1],light.m[0][2]);
FntPrint("L2: %d %d %d\n", light.m[1][0],light.m[1][1],light.m[1][2]);
FntPrint("L3: %d %d %d\n", light.m[2][0],light.m[2][1],light.m[2][2]);
//~ FntPrint("Ligt angle = %d,%d,%d\n", lgtang.vx, lgtang.vy, lgtang.vz);
//~ FntPrint("NW : %d %d %d", NW.vx, NW.vy, NW.vz);
//~ FntPrint("Lerping : %d - %d\n", lerping, camPath.cursor);
//~ FntPrint("Cam x: %d, %d\n", camera.pos.vx , camPath.points[1].vx);
//~ FntPrint("Cam y: %d, %d\n", camera.pos.vy , camPath.points[1].vy);
//~ FntPrint("Cam z: %d, %d\n", camera.pos.vz , camPath.points[1].vz);
//~ FntPrint("%d %d \n", (meshes[2]->body->position.vy + meshes[2]->body->min.vz) , (modelgnd_body.position.vz + modelgnd_body.min.vz));
//~ FntPrint("%d \n", (meshes[2]->body->position.vz + meshes[2]->body->min.vz) - (modelgnd_body.position.vz + modelgnd_body.min.vz));
//~ FntPrint("%d %d \n", (meshes[2]->body->position.vz + meshes[2]->body->max.vz) , (modelgnd_body.position.vz + modelgnd_body.max.vz));
//~ FntPrint("%d", (modelgnd_body.position.vz + modelgnd_body.max.vz) - (meshes[2]->body->position.vz + meshes[2]->body->max.vz));
//~ for (int i = 0; i < modelCylindre_anim.nframes; i++ ){
//~ for (int i = 0; i < 1; i++ ){
//~ for (int j = 0; j < modelCylindre_anim.nvert; j++){
//~ FntPrint("%d - ",modelCylindre_anim.data[i * modelCylindre_anim.nvert + j].vx);
//~ }
//~ }
//~ FntPrint("%d",modelCylindre_anim.data[2 * modelCylindre_anim.nvert + 0].vx);
//~ FntPrint("Act pos: %d, %d,%d\n", modelobject_pos.vx, modelobject_pos.vz, modelobject_pos.vy);
//~ // Camera
//~ FntPrint("Angle : %d\nDist : %d\n", angle, dist);
//~ FntPrint("Dist : %d\n", psqrt((posToActor.vx * posToActor.vx ) + (posToActor.vz * posToActor.vz)));
//~ FntPrint("Cam pos: %d, %d, %d\n", camera.pos.vx, camera.pos.vz, camera.pos.vy);
//~ FntPrint("CamRot : %d \n", camera.rot.vy);
//~ FntPrint("Act Rot: %d\n", modelobject_rot.vy);
//~ FntPrint("LookAt x: %d\n z: %d\n", posToActor.vx, posToActor.vz);
//~ FntPrint("Theta y: %d x: %d\n", theta.vy, theta.vx);
//~ FntPrint("ThetaD %d\n", modelobject_rot.vy - camera.rot.vy);
//~ FntPrint("Nsin : %d, Ncos: %d\n", nsin(angle), ncos(angle));
// Physics
//~ FntPrint("d1 : %d, %d, %d\n", d1x, d1z, d1y);
//~ FntPrint("d2 : %d, %d, %d\n", d2x, d2z, d2y);
//~ FntPrint("Lerp : %d\n", lerp(490, -50, 160));
//~ FntPrint("CamMode : %d %d\n", camMode, pressed);
//~ FntPrint("short %d", sizeof(short));
FntFlush(-1);
display();
//~ frame = VSync(-1);
}
return 0;
}
void init(){
// Reset the GPU before doing anything and the controller
PadInit(0);
ResetGraph(0);
// Initialize and setup the GTE
InitGeom();
SetGeomOffset(CENTERX, CENTERY); // x, y offset
SetGeomScreen(CENTERX); // Distance between eye and screen
// Set the display and draw environments
SetDefDispEnv(&disp[0], 0, 0 , SCREENXRES, SCREENYRES);
SetDefDispEnv(&disp[1], 0, SCREENYRES, SCREENXRES, SCREENYRES);
SetDefDrawEnv(&draw[0], 0, SCREENYRES, SCREENXRES, SCREENYRES);
SetDefDrawEnv(&draw[1], 0, 0, SCREENXRES, SCREENYRES);
if (VMODE)
{
SetVideoMode(MODE_PAL);
disp[0].screen.y += 8;
disp[1].screen.y += 8;
}
setRGB0(&draw[0], BGc.r, BGc.g, BGc.b);
setRGB0(&draw[1], BGc.r, BGc.g, BGc.b);
draw[0].isbg = 1;
draw[1].isbg = 1;
PutDispEnv(&disp[db]);
PutDrawEnv(&draw[db]);
// Init font system
FntLoad(960, 0);
FntOpen(16, 180, 240, 96, 0, 512);
}
void display(void){
DrawSync(0);
vs = VSync(0);
PutDispEnv(&disp[db]);
PutDrawEnv(&draw[db]);
SetDispMask(1);
DrawOTag(ot[db] + OTLEN - 1);
db = !db;
nextpri = primbuff[db];
}
// Nic's function
void getCameraXZ(int * x, int * z, int actorX, int actorZ, int angle, int distance) {
// Using Nic's Costable : https://github.com/grumpycoders/Balau/blob/master/tests/test-Handles.cc#L20-L102
// https://godbolt.org/z/q6cMcj
*x = (actorX * ONE) + (distance * nsin(angle));
*z = (actorZ * ONE) - (distance * ncos(angle));
//~ *x = (actorX * ONE) + (distance * csin(angle));
//~ *z = (actorZ * ONE) - (distance * ccos(angle)); // Z is pointing away from the eye
// @soapy https://discord.com/channels/642647820683444236/663664210525290507/797188403748929547
//~ *x = (actorX * ONE) + (distance * rcossin_tbl[(angle & 0xFFFU) * 2]);
//~ *z = (actorZ * ONE) - (distance * rcossin_tbl[(angle & 0xFFFU) * 2 + 1]); // Z is pointing away from the eye
// Using precalculated psin and pcos
//~ *x = (actorX * ONE) + (distance * psin[angle]);
//~ *z = (actorZ * ONE) - (distance * pcos[angle]); // Z is pointing away from the eye
}
// @Will : you might want to use sin/cos to move the camera in a circle but you could do that by moving it along its tangent and then clamping the distance
void applyCamera(CAMERA * cam){
VECTOR vec; // Vector that holds the output values of the following instructions
RotMatrix_gte(&cam->rot, &cam->mat); // Convert rotation angle in psx units (360° == 4096) to rotation matrix)
ApplyMatrixLV(&cam->mat, &cam->pos, &vec); // Multiply matrix by vector pos and output to vec
TransMatrix(&cam->mat, &vec); // Apply transform vector
SetRotMatrix(&cam->mat); // Set Rotation matrix
SetTransMatrix(&cam->mat); // Set Transform matrix
}
void setCameraPos(VECTOR pos, SVECTOR rot){
camera.pos = pos;
camera.rot = rot;
};
void LoadTexture(u_long * tim, TIM_IMAGE * tparam){ // This part is from Lameguy64's tutorial series : lameguy64.net/svn/pstutorials/chapter1/3-textures.html login/pw: annoyingmous
OpenTIM(tim); // Open the tim binary data, feed it the address of the data in memory
ReadTIM(tparam); // This read the header of the TIM data and sets the corresponding members of the TIM_IMAGE structure
LoadImage(tparam->prect, tparam->paddr); // Transfer the data from memory to VRAM at position prect.x, prect.y
DrawSync(0); // Wait for the drawing to end
if (tparam->mode & 0x8){ // check 4th bit // If 4th bit == 1, TIM has a CLUT
LoadImage(tparam->crect, tparam->caddr); // Load it to VRAM at position crect.x, crect.y
DrawSync(0); // Wait for drawing to end
}
}
int lerp(int start, int end, int factor){
// lerp interpolated cam movement
// InBetween = Value 1 + ( ( Value2 - Value1 ) * lerpValue ) ;
// lerpValue should be a float between 0 and 1.
// This'll have to be a fixed point value between 0-4096
// easeOut
//~ return ( ( start ) + ( end - start ) * factor ) / 4096;
// easeIn
return ( ( start ) + ( end - start ) * factor ) / 4096;
// kinda linear
//~ return (( start ) + ( end - start )) * factor / 4096;
}
SVECTOR SVlerp(SVECTOR start, SVECTOR end, int factor){
SVECTOR output = {0,0,0,0};
output.vx = lerp(start.vx, end.vx, factor);
output.vy = lerp(start.vy, end.vy, factor);
output.vz = lerp(start.vz, end.vz, factor);
return output;
}
VECTOR getCollision(BODY one, BODY two){
VECTOR d1, d2, col;
d1.vx = (one.position.vx - one.max.vx) - (two.position.vx + two.min.vx);
d1.vy = (one.position.vy - one.min.vy) - (two.position.vy + two.min.vy);
d1.vz = (one.position.vz - one.max.vz) - (two.position.vz + two.min.vz);
d2.vx = (two.position.vx + two.max.vx) - (one.position.vx + one.max.vx);
d2.vy = (two.position.vy + two.max.vy) - (one.position.vy + one.max.vy);
d2.vz = (two.position.vz + two.max.vz) - (one.position.vz + one.max.vz);
col.vx = d1.vx >= 0 && d2.vx >= 0;
col.vy = d1.vy >= 0 && d2.vy >= 0;
col.vz = d1.vz >= 0 && d2.vz >= 0;
return col;
}
void applyAcceleration(BODY * actor){
short dt = 1;
VECTOR acceleration = {actor->gForce.vx / actor->mass, actor->gForce.vy / actor->mass, actor->gForce.vz / actor->mass};
actor->velocity.vx += acceleration.vx * dt;
actor->velocity.vy += acceleration.vy * dt;
actor->velocity.vz += acceleration.vz * dt;
actor->position.vx += actor->velocity.vx * dt;
actor->position.vy += actor->velocity.vy * dt;
actor->position.vz += actor->velocity.vz * dt;
}
// A few notes on the following code :
int ncos(unsigned int t) {
t %= DC_2PI;
int r;
if (t < DC_PI2) {
r = m_cosTable[t];
} else if (t < DC_PI) {
r = -m_cosTable[DC_PI - 1 - t];
} else if (t < (DC_PI + DC_PI2)) {
r = -m_cosTable[t - DC_PI];
} else {
r = m_cosTable[DC_2PI - 1 - t];
};
return r >> 12;
};
// sin(x) = cos(x - pi / 2)
int nsin(unsigned int t) {
t %= DC_2PI;
if (t < DC_PI2){
return ncos(t + DC_2PI - DC_PI2);
};
return ncos(t - DC_PI2);
};
// f(n) = cos(n * 2pi / 2048) <- 2048 is == DC_2PI value
// f(n) = 2 * f(1) * f(n - 1) - f(n - 2)
void generateTable(void){
m_cosTable[0] = 16777216; // 2^24 * cos(0 * 2pi / 2048) => 2^24 * 1 = 2^24 : here, 2^24 defines the precision we want after the decimal point
static const long long C = 16777137; // 2^24 * cos(1 * 2pi / 2048) = C = f(1);
m_cosTable[1] = C;
for (int i = 2; i < 512; i++){
m_cosTable[i] = ((C * m_cosTable[i - 1]) >> 23) - m_cosTable[i - 2];
m_cosTable[511] = 0;
}
};
// https://github.com/Arsunt/TR2Main/blob/411cacb35914c616cb7960c0e677e00c71c7ee88/3dsystem/phd_math.cpp#L432
int patan(int x, int y){
int result;
int swapBuf;
int flags = 0;
// if either x or y are 0, return 0
if( x == 0 && y == 0){
return 0;
}
if( x < 0 ) {
flags |= 4;
x = -x;
}
if ( y < 0 ) {
flags |= 2;
y = -y;
}
if ( y > x ) {
flags |= 1;
SWAP(x, y ,swapBuf);
}
result = AtanBaseTable[flags] + AtanAngleTable[0x800 * y / x];
if ( result < 0 ){
result = -result;
return result;
}
}
u_int psqrt(u_int n){
u_int result = 0;
u_int base = 0x40000000;
u_int basedResult;
for( ; base != 0; base >>= 2 ) {
for( ; base != 0; base >>= 2 ) {
basedResult = base + result;
result >>= 1;
if( basedResult > n ) {
break;
}
n -= basedResult;
result |= base;
}
}
return result;
}
int cliptest3(short *v1)
{
if( v1[0]<0 && v1[2]<0 && v1[4]<0 ) return 0;
if( v1[1]<0 && v1[3]<0 && v1[5]<0 ) return 0;
if( v1[0] > SCREENXRES && v1[2] > SCREENXRES && v1[4] > SCREENXRES) return 0;
if( v1[1] > SCREENYRES && v1[3] > SCREENYRES && v1[5] > SCREENYRES) return 0;
return 1;
}
void callback(){
int pad = PadRead(0);
if (pad & PADRright && !pressed){
if(camMode < 4){
camMode += 1;
} else {
setCameraPos(camStartPos.pos, camStartPos.rot);
camPath.cursor = 0;
camMode = 0;
}
pressed = 1;
}
if (!(pad & PADRright)){
pressed = 0;
}
if (pad & PADRdown){
lgtang.vy += 32;
//~ lgtang.vx += 32;
}
if (pad & PADRup){
lgtang.vz += 32;
//~ lgtang.vx += 32;
}
//~ RotMatrix(&lgtang, &rotlgt);
//~ MulMatrix(&rotlgt, &rottrans);
if (pad & PADLdown && !pressed){
if (*meshobject.isPrism){
*meshobject.isPrism = 0;
} else {
*meshobject.isPrism = 1;
}
pressed = 1;
}
if (!pad & PADLdown){
pressed = 0;
}
}