3dcam-headers/3dcam-tri-quads.c

2722 lines
88 KiB
C
Raw Normal View History

2021-02-28 11:14:02 +01:00
// 3dcam
2021-03-21 12:57:01 +01:00
// With huge help from :
// @NicolasNoble : https://discord.com/channels/642647820683444236/646765703143227394/796876392670429204
// @Lameguy64
// @Impiaa
// @paul
2021-02-28 11:14:02 +01:00
/* PSX screen coordinate system
*
* Z+
* /
* /
* +------X+
* /|
* / |
* / Y+
* eye */
2021-03-21 12:57:01 +01:00
// Blender debug mode
2021-02-28 11:14:02 +01:00
// bpy. app. debug = True
#include <sys/types.h>
#include <libgte.h>
#include <libgpu.h>
#include <libetc.h>
#include <stdio.h>
#include <stdint.h>
2021-03-06 11:45:25 +01:00
#include <stddef.h>
2021-02-28 11:14:02 +01:00
// Precalculated sin/cos values
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
#include "atan.c"
2021-03-21 12:57:01 +01:00
// Sample level
2021-03-06 11:45:25 +01:00
#include "coridor2.c"
2021-02-28 11:14:02 +01:00
#define VMODE 0
#define SCREENXRES 320
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
#define SCREENYRES 240
#define CENTERX SCREENXRES/2
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
#define CENTERY SCREENYRES/2
2021-03-21 12:57:01 +01:00
#define FOV CENTERX // With a FOV of 1/2, camera focal length is ~= 16 mm / 90°
// Lower values mean wider angle
2021-02-28 11:14:02 +01:00
// pixel > cm : used in physics calculations
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
#define SCALE 4
#define FNT_POS_X 960
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
#define FNT_POS_Y 0
2021-03-21 12:57:01 +01:00
2021-03-06 11:45:25 +01:00
#define OT2LEN 8
2021-03-21 12:57:01 +01:00
#define OTLEN 256 // Maximum number of OT entries
2021-03-15 15:58:21 +01:00
#define PRIMBUFFLEN 4096 * sizeof(POLY_GT4) // Maximum number of POLY_GT3 primitives
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
// MACROS
// swap(x, y, buffer)
#define SWAP(a,b,c) {(c)=(a); (a)=(b); (b)=(c);}
2021-02-28 11:14:02 +01:00
// dotproduct of two vectors
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
#define dotProduct(v0, v1) \
2021-03-26 15:39:24 +01:00
(v0).vx * (v1).vx + \
2021-03-29 11:44:06 +02:00
(v0).vy * (v1).vy + \
2021-02-28 11:14:02 +01:00
(v0).vz * (v1).vz
// min value
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
#define min(a,b) \
(a)-(b)>0?(b):(a)
// max
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
#define max(a,b) \
(a)-(b)>0?(a):(b)
2021-03-21 12:57:01 +01:00
// substract vector
2021-02-28 11:14:02 +01:00
#define subVector(v0, v1) \
(v0).vx - (v1).vx, \
(v0).vy - (v1).vy, \
(v0).vz - (v1).vz
2021-03-26 15:39:24 +01:00
#define normalizeVector(v) \
((v)->vx << 12) >> 8, \
((v)->vy << 12) >> 8, \
((v)->vz << 12) >> 8
2021-02-28 11:14:02 +01:00
// Display and draw environments, double buffered
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
DISPENV disp[2];
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
DRAWENV draw[2];
2021-03-06 11:45:25 +01:00
// OT for BG/FG discrimination
2021-03-21 12:57:01 +01:00
2021-03-06 11:45:25 +01:00
u_long otdisc[2][OT2LEN] = {0};
// Main OT
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
u_long ot[2][OTLEN] = {0}; // Ordering table (contains addresses to primitives)
2021-03-06 11:45:25 +01:00
2021-02-28 11:14:02 +01:00
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}; // Far color
2021-03-21 12:57:01 +01:00
2021-03-19 15:40:51 +01:00
VECTOR BKc = {128, 128, 128, 0}; // Back color
2021-02-28 11:14:02 +01:00
// 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
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
//~ static MATRIX lgtmat = {
//~ // X Y Z
//~ ONE, 0, 0, // Light 0
//~ 0,0,0, // Light 1
//~ 0,0,0 // Light 2
//~ };
// Light
//~ MATRIX rottrans;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
MATRIX rotlgt;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
SVECTOR lgtang = {0, 0, 0};
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
MATRIX light;
static int m_cosTable[512]; // precalc costable
2021-03-21 12:57:01 +01:00
static const unsigned int DC_2PI = 2048; // this is from here : https://github.com/grumpycoders/Balau/blob/master/tests/test-Handles.cc#L20-L102
2021-02-28 11:14:02 +01:00
static const unsigned int DC_PI = 1024;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
static const unsigned int DC_PI2 = 512;
short vs;
typedef struct{
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
int x, xv; // x: current value += xv : new value
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
int y, yv; // x,y,z, vx, vy, vz are in PSX units (ONE == 4096)
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
int z, zv;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
int pan, panv;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
int tilt, tiltv;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
int rol;
VECTOR pos;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
SVECTOR rot;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
SVECTOR dvs;
MATRIX mat;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
} CAMERA;
CAMERA camera = {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
0,0,
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
0,0,
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
0,0,
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
0,0,
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
0,0,
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
0,
{0,0,0},
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
{0,0,0},
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
{0,0,0}
};
// physics
2021-03-21 12:57:01 +01:00
long time = 0;
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
const int gravity = 10;
2021-02-28 11:14:02 +01:00
//Pad
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
int pressed = 0;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
u_short timer = 0;
// Cam stuff
2021-03-21 12:57:01 +01:00
int camMode = 2;
2021-02-28 11:14:02 +01:00
long timeB = 0;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
int lerping = 0;
2021-03-24 11:22:30 +01:00
short curCamAngle = 0;
2021-03-15 15:58:21 +01:00
// Inverted Cam coordinates for Forward Vector calc
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
VECTOR InvCamPos = {0,0,0,0};
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
VECTOR fVecActor = {0,0,0,0};
2021-02-28 11:14:02 +01:00
u_long triCount = 0;
// Prototypes
// Stolen from grumpycoder
// Sin/Cos Table
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
void generateTable(void);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
int ncos(u_int t);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
int nsin(u_int t);
// Atan table
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
long long patan(long x, long y);
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
// Sqrt
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
u_int psqrt(u_int n);
2021-02-28 11:14:02 +01:00
// fixed point math
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
static inline int32_t dMul(int32_t a, int32_t b);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
static inline uint32_t lerpU(uint32_t start, uint32_t dest, unsigned pos);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
static inline int32_t lerpS(int32_t start, int32_t dest, unsigned pos);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
static inline int32_t lerpD(int32_t start, int32_t dest, int32_t pos);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
static inline long long lerpL(long long start, long long dest, long long pos);
// PSX setup
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
void init(void);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
void display(void);
// Utils
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
void LoadTexture(u_long * tim, TIM_IMAGE * tparam);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
int cliptest3(short * v1);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
int lerp(int start, int end, int factor); // FIXME : not working as it should
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
SVECTOR SVlerp(SVECTOR start, SVECTOR end, int factor); // FIXME
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
VECTOR getVectorTo(VECTOR actor, VECTOR target);
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
int alignAxisToVect(VECTOR target, short axis, int factor);
2021-02-28 11:14:02 +01:00
2021-03-29 11:44:06 +02:00
void worldToScreen( VECTOR * worldPos, VECTOR * screenPos );
void screenToWorld( VECTOR * screenPos, VECTOR * worldPos );
2021-03-21 12:57:01 +01:00
// Drawing
void transformMesh(MESH * meshes);
2021-03-22 14:35:28 +01:00
void drawBG(void);
void drawPoly(MESH * meshes, long * Flag, int atime);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
// Camera
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
void getCameraXZ(int * x, int * z, int actorX, int actorZ, int angle, int distance);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
void applyCamera(CAMERA * cam);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
void setCameraPos(VECTOR pos, SVECTOR rot);
// Physics
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
VECTOR getIntCollision(BODY one, BODY two);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
VECTOR getExtCollision(BODY one, BODY two);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
void ResolveCollision( BODY * one, BODY * two );
2021-03-21 12:57:01 +01:00
VECTOR angularMom(BODY body); // Not this kind of mom ;)
2021-02-28 11:14:02 +01:00
void applyAcceleration(BODY * actor);
2021-03-21 12:57:01 +01:00
// Pad
2021-02-28 11:14:02 +01:00
void callback();
int main() {
2021-03-26 15:39:24 +01:00
2021-04-01 13:12:57 +02:00
VECTOR sp = {CENTERX,CENTERY,0};
2021-03-29 11:44:06 +02:00
VECTOR wp = {0,0,0};
2021-03-22 14:35:28 +01:00
// FIXME : Poly subdiv
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
//~ DIVPOLYGON4 div4 = { 0 };
//~ div4.pih = SCREENXRES;
//~ div4.piv = SCREENYRES;
//~ div4.ndiv = 2;
//~ long OTc = 0;
2021-03-15 15:58:21 +01:00
//~ DIVPOLYGON3 div3 = { 0 };
//~ div3.pih = SCREENXRES;
//~ div3.piv = SCREENYRES;
//~ div3.ndiv = 1;
2021-02-28 11:14:02 +01:00
init();
generateTable();
VSyncCallback(callback);
2021-03-22 14:39:47 +01:00
// Load textures
2021-02-28 11:14:02 +01:00
for (int k = 0; k < sizeof(meshes)/sizeof(TMESH *); k++){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
LoadTexture(meshes[k]->tim_data, meshes[k]->tim);
2021-03-21 12:57:01 +01:00
}
2021-03-06 11:45:25 +01:00
2021-03-22 14:39:47 +01:00
// Load current BG
2021-03-06 11:45:25 +01:00
if (camPtr->tim_data){
2021-03-21 12:57:01 +01:00
2021-03-06 11:45:25 +01:00
LoadTexture(camPtr->tim_data, camPtr->BGtim);
2021-03-21 12:57:01 +01:00
2021-03-06 11:45:25 +01:00
}
2021-03-22 14:39:47 +01:00
// Physics
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
short physics = 1;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
long dt;
VECTOR col_lvl, col_sphere, col_sphere_act = {0};
// Cam stuff
2021-03-15 15:58:21 +01:00
VECTOR posToActor = {0, 0, 0, 0}; // position of camera relative to actor
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
VECTOR camAngleToAct = {0, 0, 0, 0}; // rotation angles for the camera to point at actor
2021-03-22 14:39:47 +01:00
// Sprite system
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
VECTOR posToCam = {0, 0, 0, 0};
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
VECTOR objAngleToCam = {0, 0, 0, 0};
2021-02-28 11:14:02 +01:00
2021-03-24 11:22:30 +01:00
//~ long objAngleToCam = 0;
2021-02-28 11:14:02 +01:00
int angle = 0; //PSX units = 4096 == 360° = 2Pi
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
int dist = 0; //PSX units
short timediv = 1;
int atime = 0;
2021-03-22 14:39:47 +01:00
// Polycount
2021-02-28 11:14:02 +01:00
for (int k = 0; k < sizeof(meshes)/sizeof(meshes[0]); k++){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
triCount += meshes[k]->tmesh->len;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
}
2021-03-22 14:35:28 +01:00
// Set camera starting pos
2021-03-21 12:57:01 +01:00
2021-03-06 11:45:25 +01:00
setCameraPos(camPtr->campos->pos, camPtr->campos->rot);
2021-04-01 13:12:57 +02:00
// Find curCamAngle if using pre-calculated BGs
if (camMode == 2) {
if (camPtr->tim_data){
curCamAngle = 1;
}
}
2021-02-28 11:14:02 +01:00
// Main loop
2021-03-21 12:57:01 +01:00
2021-03-22 14:35:28 +01:00
//~ while (1) {
while ( VSync(1) ) {
2021-02-28 11:14:02 +01:00
2021-03-06 11:45:25 +01:00
// Clear the main OT
2021-03-21 12:57:01 +01:00
ClearOTagR(otdisc[db], OT2LEN);
2021-03-06 11:45:25 +01:00
// Clear Secondary OT
2021-03-21 12:57:01 +01:00
2021-03-06 11:45:25 +01:00
ClearOTagR(ot[db], OTLEN);
2021-02-28 11:14:02 +01:00
// timeB = time;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
time ++;
// atime is used for animations timing
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
timediv = 1;
if (time % timediv == 0){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
atime ++;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
}
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
// Angle between camera and actor
2021-03-22 14:35:28 +01:00
2021-02-28 11:14:02 +01:00
// using atantable (faster)
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
camAngleToAct.vy = (patan(-posToActor.vx, -posToActor.vz) / 16) - 3076 ;
2021-03-22 14:35:28 +01:00
2021-03-15 15:58:21 +01:00
camAngleToAct.vx = patan(dist, posToActor.vy) >> 4;
2021-03-22 14:35:28 +01:00
// Sprite system WIP
2021-03-15 15:58:21 +01:00
//~ posToCam = getVectorTo(*meshPlan.pos, camera.pos);
2021-03-22 14:35:28 +01:00
2021-03-15 15:58:21 +01:00
//~ posToCam = getVectorTo(camera.pos, *meshPlan.pos);
2021-03-24 11:22:30 +01:00
posToCam.vx = -camera.pos.vx - modelPlan_pos.vx ;
posToCam.vz = -camera.pos.vz - modelPlan_pos.vz ;
posToCam.vy = -camera.pos.vy - modelPlan_pos.vy ;
2021-03-22 14:35:28 +01:00
2021-03-24 11:22:30 +01:00
//~ psqrt(posToCam.vx * posToCam.vx + posToCam.vy * posToCam.vy);
2021-03-22 14:35:28 +01:00
2021-03-24 11:22:30 +01:00
objAngleToCam.vy = patan( posToCam.vx,posToCam.vz );
objAngleToCam.vx = patan( posToCam.vx,posToCam.vy );
//~ objAngleToCam.vz = patan( posToCam.vz,posToCam.vy );
//~ objAngleToCam.vx = patan( psqrt(posToCam.vx * posToCam.vx + posToCam.vy * posToCam.vy), posToCam.vy );
//~ meshPlan.rot->vx = -( (objAngleToCam.vx >> 4) - 3076 ) ;
//~ meshPlan.rot->vx = (( (objAngleToCam.vx >> 4) - 3076 ) * ( (objAngleToCam.vz >> 4) - 3076 ) >> 12) * (nsin(posToCam.vz) >> 10 < 0 ? -1 : 1);
//~ meshPlan.rot->vx = ( (objAngleToCam.vx >> 4) - 3076 ) * ( (objAngleToCam.vz >> 4) - 3076 ) >> 12 ;
2021-03-22 14:35:28 +01:00
2021-03-24 11:22:30 +01:00
meshPlan.rot->vy = -( (objAngleToCam.vy >> 4) + 1024 ) ;
2021-03-15 15:58:21 +01:00
// Actor Forward vector
fVecActor = *actorPtr->pos;
fVecActor.vx = actorPtr->pos->vx + (nsin(actorPtr->rot->vy/2));
2021-03-22 14:35:28 +01:00
2021-03-15 15:58:21 +01:00
fVecActor.vz = actorPtr->pos->vz - (ncos(actorPtr->rot->vy/2));
2021-03-22 14:35:28 +01:00
// Camera modes
if(camMode != 2) {
2021-02-28 11:14:02 +01:00
2021-03-15 15:58:21 +01:00
camera.rot.vy = camAngleToAct.vy;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
// using csin/ccos, no need for theta
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
//~ camera.rot.vy = angle;
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
camera.rot.vx = camAngleToAct.vx;
2021-02-28 11:14:02 +01:00
}
2021-03-22 14:35:28 +01:00
if(camMode < 4 ) {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
lerping = 0;
2021-03-21 12:57:01 +01:00
}
2021-02-28 11:14:02 +01:00
// Camera follows actor with lerp for rotations
2021-03-22 14:35:28 +01:00
if(camMode == 0) {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
dist = 150;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camera.pos.vx = -(camera.x/ONE);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
//~ camera.pos.vy = -(camera.y/ONE);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camera.pos.vz = -(camera.z/ONE);
2021-03-15 15:58:21 +01:00
//~ InvCamPos.vx = camera.x/ONE;
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
//~ InvCamPos.vz = camera.z/ONE;
//~ applyVector(&InvCamPos, -1,-1,-1, *=);
angle = -actorPtr->rot->vy / 2;
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
//~ angle = actorPtr->rot->vy;
2021-02-28 11:14:02 +01:00
getCameraXZ(&camera.x, &camera.z, actorPtr->pos->vx, actorPtr->pos->vz, angle, dist);
// FIXME! camera lerping to pos
//~ angle += lerp(camera.rot.vy, -actorPtr->rot->vy, 128);
//~ angle = lerpD(camera.rot.vy << 12, actorPtr->rot->vy << 12, 1024 << 12) >> 12;
}
// Camera rotates continuously around actor
2021-03-22 14:35:28 +01:00
if (camMode == 1) {
2021-02-28 11:14:02 +01:00
dist = 150;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camera.pos.vx = -(camera.x/ONE);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
//~ camera.pos.vy = -(camera.y/ONE);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camera.pos.vz = -(camera.z/ONE);
2021-03-15 15:58:21 +01:00
//~ fVecActor = *actorPtr->pos;
//~ fVecActor.vx = actorPtr->pos->vx + (nsin(actorPtr->rot->vy));
//~ fVecActor.vz = actorPtr->pos->vz - (ncos(actorPtr->rot->vy));
2021-02-28 11:14:02 +01:00
getCameraXZ(&camera.x, &camera.z, actorPtr->pos->vx, actorPtr->pos->vz, angle, dist);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
angle += 10;
}
// Fixed Camera with actor tracking
2021-03-22 14:35:28 +01:00
if (camMode == 3) {
2021-02-28 11:14:02 +01:00
// Using precalc sqrt
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
dist = psqrt( (posToActor.vx * posToActor.vx ) + (posToActor.vz * posToActor.vz) );
camera.pos.vx = 190;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camera.pos.vz = 100;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camera.pos.vy = 180;
}
// Fixed Camera angle
2021-03-22 14:35:28 +01:00
if (camMode == 2) {
2021-03-21 12:57:01 +01:00
2021-04-01 13:12:57 +02:00
// If BG images exist
2021-03-25 19:55:15 +01:00
2021-04-01 13:12:57 +02:00
if (camPtr->tim_data){
2021-03-25 19:55:15 +01:00
2021-04-01 13:12:57 +02:00
if ( camAngles[ curCamAngle ]->fw.v0.vx ) {
//~ FntPrint("v3 : %d, v2 : %d\n", camAngles[ curCamAngle ]->fw.v3.vx, camAngles[ curCamAngle ]->fw.v2.vx);
//~ FntPrint("v1 : %d, v2 : %d\n", camAngles[ curCamAngle ]->fw.v1.vy, camAngles[ curCamAngle ]->fw.v2.vy);
2021-03-25 19:55:15 +01:00
2021-04-01 13:12:57 +02:00
// If actor in camAngle->fw area of screen
if ( actorPtr->pos2D.vx + CENTERX > camAngles[ curCamAngle ]->fw.v3.vx &&
actorPtr->pos2D.vx + CENTERX < camAngles[ curCamAngle ]->fw.v2.vx &&
actorPtr->pos2D.vy + CENTERY > camAngles[ curCamAngle ]->fw.v3.vy &&
actorPtr->pos2D.vy + CENTERY < camAngles[ curCamAngle ]->fw.v2.vy
) {
if (curCamAngle < 5) {
2021-03-25 19:55:15 +01:00
2021-04-01 13:12:57 +02:00
curCamAngle++;
camPtr = camAngles[ curCamAngle ];
2021-03-25 19:55:15 +01:00
2021-04-01 13:12:57 +02:00
LoadTexture(camPtr->tim_data, camPtr->BGtim);
}
}
}
if ( camAngles[ curCamAngle ]->bw.v0.vx ) {
FntPrint("v3 : %d, v3 : %d\n", camAngles[ curCamAngle ]->bw.v3.vx, camAngles[ curCamAngle ]->bw.v3.vy);
FntPrint("v2 : %d, v2 : %d\n", camAngles[ curCamAngle ]->bw.v2.vx, camAngles[ curCamAngle ]->bw.v2.vy);
// If actor in camAngle->bw area of screen
if ( actorPtr->pos2D.vx + CENTERX < camAngles[ curCamAngle ]->bw.v3.vx &&
actorPtr->pos2D.vx + CENTERX > camAngles[ curCamAngle ]->bw.v2.vx &&
actorPtr->pos2D.vy + CENTERY < camAngles[ curCamAngle ]->bw.v3.vy &&
actorPtr->pos2D.vy + CENTERY > camAngles[ curCamAngle ]->bw.v2.vy
) {
if (curCamAngle > 0) {
2021-03-25 19:55:15 +01:00
2021-04-01 13:12:57 +02:00
curCamAngle--;
2021-03-25 19:55:15 +01:00
2021-04-01 13:12:57 +02:00
camPtr = camAngles[ curCamAngle ];
2021-03-25 19:55:15 +01:00
2021-04-01 13:12:57 +02:00
LoadTexture(camPtr->tim_data, camPtr->BGtim);
2021-03-25 19:55:15 +01:00
2021-04-01 13:12:57 +02:00
}
2021-03-29 11:44:06 +02:00
}
2021-04-01 13:12:57 +02:00
2021-03-25 19:55:15 +01:00
}
}
2021-03-06 11:45:25 +01:00
setCameraPos(camPtr->campos->pos, camPtr->campos->rot);
2021-02-28 11:14:02 +01:00
}
// Flyby mode with LERP from camStart to camEnd
2021-03-22 14:35:28 +01:00
if (camMode == 4) {
2021-02-28 11:14:02 +01:00
// If key pos exist for camera
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
if (camPath.len) {
// Lerping sequence has not begun
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
if (!lerping){
// Set cam start position ( first key pos )
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camera.pos.vx = camPath.points[camPath.cursor].vx;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camera.pos.vy = camPath.points[camPath.cursor].vy;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camera.pos.vz = camPath.points[camPath.cursor].vz;
// Lerping sequence is starting
lerping = 1;
// Set cam pos index to 0
camPath.pos = 0;
}
// Pre calculated sqrt ( see psqrt() )
2021-03-15 15:58:21 +01:00
dist = psqrt( (posToActor.vx * posToActor.vx ) + (posToActor.vz * posToActor.vz));
2021-02-28 11:14:02 +01:00
// Fixed point precision 2^12 == 4096
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
int precision = 12;
camera.pos.vx = lerpD(camPath.points[camPath.cursor].vx << precision, camPath.points[camPath.cursor+1].vx << precision, camPath.pos << precision) >> precision;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camera.pos.vy = lerpD(camPath.points[camPath.cursor].vy << precision, camPath.points[camPath.cursor+1].vy << precision, camPath.pos << precision) >> precision;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camera.pos.vz = lerpD(camPath.points[camPath.cursor].vz << precision, camPath.points[camPath.cursor+1].vz << precision, camPath.pos << precision) >> precision;
//~ FntPrint("Cam %d, %d\n", (int32_t)camPath.points[camPath.cursor].vx, camPath.points[camPath.cursor+1].vx);
2021-03-06 11:45:25 +01:00
//~ FntPrint("Cam %d, %d, %d\n", camera.pos.vx, camera.pos.vy, camera.pos.vz);
//~ FntPrint("Theta y: %d x: %d\n", theta.vy, theta.vx);
//~ FntPrint("Pos: %d Cur: %d\nTheta y: %d x: %d\n", camPath.pos, camPath.cursor, theta.vy, theta.vx);
2021-02-28 11:14:02 +01:00
// Linearly increment the lerp factor
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camPath.pos += 20;
// If camera has reached next key pos, reset pos index, move cursor to next key pos
if (camPath.pos > (1 << precision) ){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camPath.pos = 0;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camPath.cursor ++;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
}
// Last key pos is reached, reset cursor to first key pos, lerping sequence is over
if ( camPath.cursor == camPath.len - 1 ){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
lerping = 0;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camPath.cursor = 0;
}
} else {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
// if no key pos exists, switch to next camMode
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camMode ++; }
}
// Camera "on a rail" - cam is tracking actor, and moving with constraints on all axis
2021-03-22 14:35:28 +01:00
2021-02-28 11:14:02 +01:00
if (camMode == 5) {
// track actor. If theta (actor/cam rotation angle) is above or below an arbitrary angle,
// move cam so that the angle doesn't increase/decrease anymore.
if (camPath.len) {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
// Lerping sequence has not begun
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
if (!lerping){
// Set cam start position ( first key pos )
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camera.pos.vx = camPath.points[camPath.cursor].vx;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camera.pos.vy = camPath.points[camPath.cursor].vy;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camera.pos.vz = camPath.points[camPath.cursor].vz;
// Lerping sequence is starting
2021-03-22 14:35:28 +01:00
2021-02-28 11:14:02 +01:00
lerping = 1;
// Set cam pos index to 0
2021-03-22 14:35:28 +01:00
2021-02-28 11:14:02 +01:00
camPath.pos = 0;
}
// Pre calculated sqrt ( see psqrt() )
2021-03-22 14:35:28 +01:00
2021-03-15 15:58:21 +01:00
dist = psqrt( (posToActor.vx * posToActor.vx ) + (posToActor.vz * posToActor.vz));
2021-02-28 11:14:02 +01:00
// Fixed point precision 2^12 == 4096
2021-03-22 14:35:28 +01:00
2021-02-28 11:14:02 +01:00
short precision = 12;
camera.pos.vx = lerpD(camPath.points[camPath.cursor].vx << precision, camPath.points[camPath.cursor + 1].vx << precision, camPath.pos << precision) >> precision;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camera.pos.vy = lerpD(camPath.points[camPath.cursor].vy << precision, camPath.points[camPath.cursor + 1].vy << precision, camPath.pos << precision) >> precision;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camera.pos.vz = lerpD(camPath.points[camPath.cursor].vz << precision, camPath.points[camPath.cursor + 1].vz << precision, camPath.pos << precision) >> precision;
//~ FntPrint("Cam %d, %d\n", (int32_t)camPath.points[camPath.cursor].vx, camPath.points[camPath.cursor+1].vx);
//~ FntPrint("Cam %d, %d, %d\n", camera.pos.vx, camera.pos.vy, camera.pos.vz);
//~ FntPrint("Pos: %d Cur: %d\nTheta y: %d x: %d\n", camPath.pos, camPath.cursor, theta.vy, theta.vx);
2021-04-01 13:12:57 +02:00
//~ FntPrint("%d", camAngleToAct.vy);
2021-03-24 11:22:30 +01:00
2021-03-15 15:58:21 +01:00
if ( camAngleToAct.vy < -50 ) {
2021-03-21 12:57:01 +01:00
2021-03-06 11:45:25 +01:00
camPath.pos += 40;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
}
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
if ( camAngleToAct.vy > 50 ) {
2021-03-21 12:57:01 +01:00
2021-03-06 11:45:25 +01:00
camPath.pos -= 40;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
}
// If camera has reached next key pos, reset pos index, move cursor to next key pos
2021-03-22 14:35:28 +01:00
2021-02-28 11:14:02 +01:00
if (camPath.pos > (1 << precision) ){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camPath.pos = 0;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camPath.cursor ++;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
//~ camPath.dir = 1;
}
if (camPath.pos < -100 ){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camPath.pos = 1 << precision;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camPath.cursor --;
2021-03-22 14:35:28 +01:00
2021-02-28 11:14:02 +01:00
//~ camPath.dir *= -1;
}
// Last key pos is reached, reset cursor to first key pos, lerping sequence is over
2021-03-22 14:35:28 +01:00
2021-02-28 11:14:02 +01:00
if ( camPath.cursor == camPath.len - 1 || camPath.cursor < 0 ){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
lerping = 0;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camPath.cursor = 0;
}
} else {
// if no key pos exists, switch to next camMode
2021-03-21 12:57:01 +01:00
camMode ++;
}
2021-02-28 11:14:02 +01:00
}
//~ dt = time/180+1 - time/180;
2021-04-01 13:12:57 +02:00
// Spatial partitioning
2021-03-16 16:18:36 +01:00
2021-03-22 14:35:28 +01:00
for ( int msh = 0; msh < curNode->siblings->index; msh ++ ) {
// Actor
2021-03-16 16:18:36 +01:00
if ( !getIntCollision( *actorPtr->body , *curNode->siblings->list[msh]->plane->body).vx &&
!getIntCollision( *actorPtr->body , *curNode->siblings->list[msh]->plane->body).vz )
{
2021-03-24 11:22:30 +01:00
if ( curNode != curNode->siblings->list[msh] ) {
curNode = curNode->siblings->list[msh];
2021-03-22 14:35:28 +01:00
2021-03-24 11:22:30 +01:00
levelPtr = curNode->plane;
}
2021-03-22 14:35:28 +01:00
}
2021-04-01 13:12:57 +02:00
// FIXME ! //~ // Moveable prop
2021-03-22 14:35:28 +01:00
2021-03-25 19:55:15 +01:00
//~ if ( !getIntCollision( *propPtr->body , *curNode->siblings->list[msh]->plane->body).vx &&
//~ !getIntCollision( *propPtr->body , *curNode->siblings->list[msh]->plane->body).vz ) {
2021-03-24 11:22:30 +01:00
2021-03-25 19:55:15 +01:00
//~ if ( propPtr->node != curNode->siblings->list[ msh ]){
2021-03-24 11:22:30 +01:00
2021-03-25 19:55:15 +01:00
//~ propPtr->node = curNode->siblings->list[ msh ];
//~ }
//~ } else
if ( !getIntCollision( *propPtr->body , *curNode->plane->body).vx &&
2021-03-24 11:22:30 +01:00
!getIntCollision( *propPtr->body , *curNode->plane->body).vz ) {
2021-03-22 14:35:28 +01:00
2021-03-24 11:22:30 +01:00
propPtr->node = curNode;
2021-03-16 16:18:36 +01:00
}
}
2021-03-22 14:35:28 +01:00
// Physics
2021-03-16 16:18:36 +01:00
2021-03-21 12:57:01 +01:00
if ( physics ) {
2021-03-16 16:18:36 +01:00
2021-03-20 15:03:37 +01:00
// if(time%1 == 0){
2021-03-16 16:18:36 +01:00
2021-03-21 12:57:01 +01:00
for ( int k = 0; k < sizeof(meshes)/sizeof(meshes[0]);k ++ ) {
2021-03-20 15:03:37 +01:00
//~ for ( int k = 0; k < curNode->objects->index ; k ++){
if ( ( *meshes[k]->isRigidBody == 1 ) ) {
//~ if ( ( *curNode->rigidbodies->list[k]->isRigidBody == 1 ) ) {
2021-02-28 11:14:02 +01:00
2021-03-20 15:03:37 +01:00
//~ applyAcceleration(curNode->rigidbodies->list[k]->body);
2021-02-28 11:14:02 +01:00
2021-03-20 15:03:37 +01:00
applyAcceleration(meshes[k]->body);
2021-02-28 11:14:02 +01:00
// Get col with level ( modelgnd_body )
2021-03-15 15:58:21 +01:00
2021-03-19 15:40:51 +01:00
col_lvl = getIntCollision( *meshes[k]->body , *levelPtr->body );
2021-03-15 15:58:21 +01:00
2021-03-25 19:55:15 +01:00
//~ col_sphere = getIntCollision( *propPtr->body, *propPtr->node->plane->body );
2021-03-22 14:35:28 +01:00
2021-03-25 19:55:15 +01:00
// col_sphere = getIntCollision( *propPtr->body, *levelPtr->body );
2021-02-28 11:14:02 +01:00
col_sphere_act = getExtCollision( *actorPtr->body, *propPtr->body );
2021-03-20 15:03:37 +01:00
//~ // If no col with ground, fall off
2021-02-28 11:14:02 +01:00
if ( col_lvl.vy ) {
2021-03-22 14:35:28 +01:00
2021-02-28 11:14:02 +01:00
if (!col_lvl.vx && !col_lvl.vz){actorPtr->body->position.vy = actorPtr->body->min.vy;}
2021-03-22 14:35:28 +01:00
2021-02-28 11:14:02 +01:00
}
if (col_sphere.vy){
if (!col_sphere.vx && !col_sphere.vz){propPtr->body->position.vy = propPtr->body->min.vy; }
}
2021-03-22 14:35:28 +01:00
if (col_sphere_act.vx && col_sphere_act.vz ){
2021-02-28 11:14:02 +01:00
2021-03-22 14:35:28 +01:00
propPtr->body->velocity.vx += actorPtr->body->velocity.vx;// * ONE / propPtr->body->restitution ;
propPtr->body->velocity.vz += actorPtr->body->velocity.vz;// * ONE / propPtr->body->restitution ;
2021-02-28 11:14:02 +01:00
2021-03-22 14:35:28 +01:00
if (propPtr->body->velocity.vx){
2021-02-28 11:14:02 +01:00
2021-03-22 14:35:28 +01:00
VECTOR L = angularMom(*propPtr->body);
propPtr->rot->vz -= L.vx;
}
2021-02-28 11:14:02 +01:00
2021-03-22 14:35:28 +01:00
if (propPtr->body->velocity.vz){
2021-02-28 11:14:02 +01:00
2021-03-22 14:35:28 +01:00
VECTOR L = angularMom(*propPtr->body);
propPtr->rot->vx -= L.vz;
}
}
2021-02-28 11:14:02 +01:00
meshes[k]->pos->vx = meshes[k]->body->position.vx;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
meshes[k]->pos->vy = meshes[k]->body->position.vy ;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
meshes[k]->pos->vz = meshes[k]->body->position.vz;
}
2021-03-20 15:03:37 +01:00
meshes[k]->body->velocity.vy = 0;
2021-03-21 12:57:01 +01:00
2021-03-20 15:03:37 +01:00
meshes[k]->body->velocity.vx = 0;
2021-03-21 12:57:01 +01:00
2021-03-20 15:03:37 +01:00
meshes[k]->body->velocity.vz = 0;
2021-02-28 11:14:02 +01:00
}
2021-03-25 19:55:15 +01:00
2021-03-20 15:03:37 +01:00
// }
2021-02-28 11:14:02 +01:00
}
2021-04-01 13:12:57 +02:00
if ( (camMode == 2) && (camPtr->tim_data ) ) {
worldToScreen(actorPtr->pos, &actorPtr->pos2D);
2021-03-29 11:44:06 +02:00
2021-04-01 13:12:57 +02:00
}
2021-03-22 14:35:28 +01:00
// Camera setup
2021-02-28 11:14:02 +01:00
// position of cam relative to actor
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
posToActor.vx = actorPtr->pos->vx + camera.pos.vx;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
posToActor.vz = actorPtr->pos->vz + camera.pos.vz;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
posToActor.vy = actorPtr->pos->vy + camera.pos.vy;
2021-03-22 14:35:28 +01:00
// Polygon drawing
2021-03-15 15:58:21 +01:00
2021-03-21 12:57:01 +01:00
static long Flag;
2021-03-15 15:58:21 +01:00
2021-03-24 11:22:30 +01:00
if ( (camMode == 2) && (camPtr->tim_data ) ) {
//~ if (camPtr->tim_data){
drawBG();
2021-04-01 13:12:57 +02:00
// Loop on camAngles
2021-03-24 11:22:30 +01:00
2021-04-01 13:12:57 +02:00
for ( int mesh = 0 ; mesh < camAngles[ curCamAngle ]->index; mesh ++ ) {
2021-03-24 11:22:30 +01:00
transformMesh(camAngles[curCamAngle]->objects[mesh]);
drawPoly(camAngles[curCamAngle]->objects[mesh], &Flag, atime);
}
2021-04-01 13:12:57 +02:00
// Get screen coordinates of actor
2021-03-24 11:22:30 +01:00
//~ }
}
else {
2021-03-22 14:35:28 +01:00
//~ long t = 0;
// Draw current node's plane
drawPoly( curNode->plane, &Flag, atime);
// Draw surrounding planes
for ( int sibling = 0; sibling < curNode->siblings->index; sibling++ ) {
drawPoly( curNode->siblings->list[ sibling ]->plane, &Flag, atime);
}
// Draw adjacent planes's children
2021-02-28 11:14:02 +01:00
2021-03-22 14:35:28 +01:00
for ( int sibling = 0; sibling < curNode->siblings->index; sibling++ ) {
2021-02-28 11:14:02 +01:00
2021-03-22 14:35:28 +01:00
for ( int object = 0; object < curNode->siblings->list[ sibling ]->objects->index; object++ ) {
long t = 0;
transformMesh(curNode->siblings->list[ sibling ]->objects->list[ object ]);
drawPoly( curNode->siblings->list[ sibling ]->objects->list[ object ], &Flag, atime);
}
}
// Draw current plane children
for ( int object = 0; object < curNode->objects->index; object++ ) {
transformMesh(curNode->objects->list[ object ]);
2021-02-28 11:14:02 +01:00
2021-03-22 14:35:28 +01:00
drawPoly( curNode->objects->list[ object ], &Flag, atime);
}
// Draw rigidbodies
for ( int object = 0; object < curNode->rigidbodies->index; object++ ) {
transformMesh(curNode->rigidbodies->list[ object ]);
2021-02-28 11:14:02 +01:00
2021-03-22 14:35:28 +01:00
drawPoly( curNode->rigidbodies->list[ object ], &Flag, atime);
}
2021-03-24 11:22:30 +01:00
2021-03-29 11:44:06 +02:00
}
2021-04-01 13:12:57 +02:00
2021-03-22 14:35:28 +01:00
// Find and apply light rotation matrix
2021-03-15 15:58:21 +01:00
2021-03-22 14:35:28 +01:00
RotMatrix(&lgtang, &rotlgt);
2021-02-28 11:14:02 +01:00
2021-03-22 14:35:28 +01:00
MulMatrix0(&lgtmat, &rotlgt, &light);
2021-03-06 11:45:25 +01:00
2021-03-22 14:35:28 +01:00
SetLightMatrix(&light);
2021-03-06 11:45:25 +01:00
2021-03-22 14:35:28 +01:00
// Set camera
applyCamera(&camera);
2021-03-21 12:57:01 +01:00
// Add secondary OT to main OT
2021-03-22 14:35:28 +01:00
2021-03-21 12:57:01 +01:00
AddPrims(otdisc[db], ot[db] + OTLEN - 1, ot[db]);
2021-03-06 11:45:25 +01:00
2021-03-22 14:35:28 +01:00
//~ FntPrint("CurNode : %x\nIndex: %d", curNode, curNode->siblings->index);
2021-03-21 12:57:01 +01:00
2021-03-22 14:35:28 +01:00
FntPrint("Time : %d dt :%d\n", VSync(-1) / 60, dt);
2021-04-01 13:12:57 +02:00
FntPrint("%d\n", curCamAngle );
//~ FntPrint("Actor : %d %d\n", actorPtr->pos->vx, actorPtr->pos->vy);
2021-03-21 12:57:01 +01:00
2021-04-01 13:12:57 +02:00
FntPrint("%d %d\n", actorPtr->pos->vx, actorPtr->pos->vy);
FntPrint("%d %d\n", actorPtr->pos2D.vx + CENTERX, actorPtr->pos2D.vy + CENTERY);
2021-03-25 19:55:15 +01:00
2021-04-01 13:12:57 +02:00
//~ FntPrint(" %d %d %d\n", wp.vx, wp.vy, wp.vz);
2021-03-26 15:39:24 +01:00
2021-03-21 12:57:01 +01:00
FntFlush(-1);
display();
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
//~ frame = VSync(-1);
2021-02-28 11:14:02 +01:00
}
return 0;
}
2021-03-21 12:57:01 +01:00
void init() {
2021-03-22 14:35:28 +01:00
ResetCallback();
2021-02-28 11:14:02 +01:00
// Reset the GPU before doing anything and the controller
2021-03-21 12:57:01 +01:00
ResetGraph(0);
2021-03-22 14:35:28 +01:00
PadInit(0);
2021-02-28 11:14:02 +01:00
// Initialize and setup the GTE
2021-03-21 12:57:01 +01:00
InitGeom();
SetGeomOffset( CENTERX, CENTERY ); // x, y offset
SetGeomScreen( FOV ); // Distance between eye and screen - Camera FOV
// 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);
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
// If PAL
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
if ( VMODE ) {
2021-02-28 11:14:02 +01:00
SetVideoMode(MODE_PAL);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
disp[0].screen.y += 8;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
disp[1].screen.y += 8;
}
2021-03-21 12:57:01 +01:00
// Set Draw area color
2021-02-28 11:14:02 +01:00
setRGB0(&draw[0], BGc.r, BGc.g, BGc.b);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
setRGB0(&draw[1], BGc.r, BGc.g, BGc.b);
2021-03-21 12:57:01 +01:00
// Set Draw area clear flag
2021-02-28 11:14:02 +01:00
draw[0].isbg = 1;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
draw[1].isbg = 1;
2021-03-21 12:57:01 +01:00
// Set the disp and draw env
2021-02-28 11:14:02 +01:00
PutDispEnv(&disp[db]);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
PutDrawEnv(&draw[db]);
// Init font system
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
FntLoad(FNT_POS_X, FNT_POS_Y);
2021-03-21 12:57:01 +01:00
2021-04-01 13:12:57 +02:00
FntOpen(16, 90, 240, 180, 0, 512);
2021-03-22 14:39:47 +01:00
// Lighting setup
SetColorMatrix(&cmat);
SetBackColor(BKc.vx,BKc.vy,BKc.vz);
SetFarColor(BGc.r, BGc.g, BGc.b);
SetFogNearFar(1200, 1600, SCREENXRES);
2021-03-21 12:57:01 +01:00
};
2021-02-28 11:14:02 +01:00
void display(void){
2021-03-22 14:35:28 +01:00
//~ DrawSync(0);
vs = VSync(2); // Using VSync 2 insures constant framerate. 0 makes the fr polycount dependant.
ResetGraph(1);
2021-02-28 11:14:02 +01:00
PutDispEnv(&disp[db]);
2021-04-01 13:12:57 +02:00
2021-02-28 11:14:02 +01:00
PutDrawEnv(&draw[db]);
SetDispMask(1);
2021-03-06 11:45:25 +01:00
// Main OT
DrawOTag(otdisc[db] + OT2LEN - 1);
2021-02-28 11:14:02 +01:00
db = !db;
nextpri = primbuff[db];
2021-03-21 12:57:01 +01:00
};
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
}
};
void transformMesh(MESH * mesh){
2021-03-29 11:44:06 +02:00
MATRIX mat;
2021-03-21 12:57:01 +01:00
// Apply rotation matrix
2021-03-29 11:44:06 +02:00
RotMatrix_gte(mesh->rot, &mat);
2021-03-21 12:57:01 +01:00
// Apply translation matrix
2021-03-29 11:44:06 +02:00
TransMatrix(&mat, mesh->pos);
2021-03-21 12:57:01 +01:00
// Compose matrix with cam
2021-03-29 11:44:06 +02:00
CompMatrix(&camera.mat, &mat, &mat);
2021-03-21 12:57:01 +01:00
// Set default rotation and translation matrices
2021-03-29 11:44:06 +02:00
SetRotMatrix(&mat);
2021-03-21 12:57:01 +01:00
2021-03-29 11:44:06 +02:00
SetTransMatrix(&mat);
2021-03-21 12:57:01 +01:00
2021-03-22 14:35:28 +01:00
//~ }
2021-03-21 12:57:01 +01:00
};
2021-03-22 14:35:28 +01:00
// Drawing
2021-03-21 12:57:01 +01:00
2021-03-22 14:35:28 +01:00
void drawPoly(MESH * mesh, long * Flag, int atime){
2021-03-21 12:57:01 +01:00
2021-03-22 14:35:28 +01:00
long nclip, t = 0;
2021-03-21 12:57:01 +01:00
// mesh is POLY_GT3 ( triangle )
if (mesh->index[t].code == 4) {
POLY_GT3 * poly;
// len member == # vertices, but here it's # of triangle... So, for each tri * 3 vertices ...
for ( int i = 0; i < (mesh->tmesh->len * 3); i += 3 ) {
// If mesh is not part of precalculated background, draw them, else, discard
if ( !( *mesh->isBG ) || camMode != 2) {
poly = (POLY_GT3 *)nextpri;
// If Vertex Anim flag is set, use it
if (*mesh->isAnim){
// If interpolation flag is set, use it
if(mesh->anim->interpolate){
// Ping pong
//~ //if (mesh->anim->cursor > 4096 || mesh->anim->cursor < 0){
//~ // mesh->anim->dir *= -1;
//~ //}
// Fixed point math precision
short precision = 12;
// Find next keyframe
if (mesh->anim->cursor > (1 << precision)) {
// There are still keyframes to interpolate between
if ( mesh->anim->lerpCursor < mesh->anim->nframes - 1 ) {
mesh->anim->lerpCursor ++;
mesh->anim->cursor = 0;
}
// We've reached last frame, go back to first frame
if ( mesh->anim->lerpCursor == mesh->anim->nframes - 1 ) {
mesh->anim->lerpCursor = 0;
mesh->anim->cursor = 0;
}
}
// Let's lerp between keyframes
2021-03-25 19:55:15 +01:00
// TODO : Finish lerped animation implementation
2021-03-21 12:57:01 +01:00
// Vertex 1
mesh->tmesh->v[ mesh->index[ t ].order.vx ].vx = lerpD( mesh->anim->data[mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[t].order.vx].vx << precision , mesh->anim->data[(mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[t].order.vx].vx << precision, mesh->anim->cursor << precision) >> precision;
mesh->tmesh->v[ mesh->index[ t ].order.vx ].vz = lerpD( mesh->anim->data[mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[t].order.vx].vz << precision , mesh->anim->data[(mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[t].order.vx].vz << precision, mesh->anim->cursor << precision) >> precision;
mesh->tmesh->v[ mesh->index[ t ].order.vx ].vy = lerpD( mesh->anim->data[mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[t].order.vx].vy << precision , mesh->anim->data[(mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[t].order.vx].vy << precision, mesh->anim->cursor << precision) >> precision;
// Vertex 2
mesh->tmesh->v[ mesh->index[ t ].order.vz ].vx = lerpD( mesh->anim->data[mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[t].order.vz].vx << precision , mesh->anim->data[(mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[t].order.vz].vx << precision, mesh->anim->cursor << precision) >> precision;
mesh->tmesh->v[ mesh->index[ t ].order.vz ].vz = lerpD( mesh->anim->data[mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[t].order.vz].vz << precision , mesh->anim->data[(mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[t].order.vz].vz << precision, mesh->anim->cursor << precision) >> precision;
mesh->tmesh->v[ mesh->index[ t ].order.vz ].vy = lerpD( mesh->anim->data[mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[t].order.vz].vy << precision , mesh->anim->data[(mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[t].order.vz].vy << precision, mesh->anim->cursor << precision) >> precision;
// Vertex 3
mesh->tmesh->v[ mesh->index[ t ].order.vy ].vx = lerpD( mesh->anim->data[mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[t].order.vy].vx << precision , mesh->anim->data[(mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[t].order.vy].vx << precision, mesh->anim->cursor << precision) >> precision;
mesh->tmesh->v[ mesh->index[ t ].order.vy ].vz = lerpD( mesh->anim->data[mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[t].order.vy].vz << precision , mesh->anim->data[(mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[t].order.vy].vz << precision, mesh->anim->cursor << precision) >> precision;
mesh->tmesh->v[ mesh->index[ t ].order.vy ].vy = lerpD( mesh->anim->data[mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[t].order.vy].vy << precision , mesh->anim->data[(mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[t].order.vy].vy << precision, mesh->anim->cursor << precision) >> precision;
2021-03-25 19:55:15 +01:00
mesh->anim->cursor += 24 * mesh->anim->dir;
2021-03-21 12:57:01 +01:00
// Coord transformation from world space to screen space
nclip = RotAverageNclip3(
&mesh->tmesh->v[ mesh->index[t].order.vx ],
&mesh->tmesh->v[ mesh->index[t].order.vz ],
&mesh->tmesh->v[ mesh->index[t].order.vy ],
( long* ) &poly->x0, ( long* ) &poly->x1, ( long* ) &poly->x2,
mesh->p,
mesh->OTz,
Flag
);
2021-03-25 19:55:15 +01:00
2021-03-21 12:57:01 +01:00
} else {
// No interpolation
// Use the pre-calculated vertices coordinates from the animation data
nclip = RotAverageNclip3(
&mesh->anim->data[ atime % mesh->anim->nframes * mesh->anim->nvert + mesh->index[t].order.vx ],
&mesh->anim->data[ atime % mesh->anim->nframes * mesh->anim->nvert + mesh->index[t].order.vz ],
&mesh->anim->data[ atime % mesh->anim->nframes * mesh->anim->nvert + mesh->index[t].order.vy ],
( long* ) &poly->x0, ( long* ) &poly->x1, ( long* ) &poly->x2,
mesh->p,
mesh->OTz,
Flag
);
}
} else {
// No animation
// Use model's regular vertex coordinates
nclip = RotAverageNclip3(
&mesh->tmesh->v[ mesh->index[t].order.vx ],
&mesh->tmesh->v[ mesh->index[t].order.vz ],
&mesh->tmesh->v[ mesh->index[t].order.vy ],
( long * ) &poly->x0, ( long * ) &poly->x1, ( long * ) &poly->x2,
mesh->p,
mesh->OTz,
Flag
);
2021-03-25 19:55:15 +01:00
2021-03-21 12:57:01 +01:00
}
// Do not draw invisible meshes
if ( nclip > 0 && *mesh->OTz > 0 && (*mesh->p < 4096) ) {
SetPolyGT3( poly );
// If isPrism flag is set, use it
if ( *mesh->isPrism ) {
// Transparency effect :
// Use current DRAWENV clip as TPAGE instead of regular textures
( (POLY_GT3 *) poly )->tpage = getTPage( mesh->tim->mode&0x3, 0,
draw[db].clip.x,
draw[db].clip.y
);
// Use projected coordinates (results from RotAverage...) as UV coords and clamp them to 0-255,0-224
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 {
// No transparency effect
// Use regular TPAGE
( (POLY_GT3 *) poly )->tpage = getTPage(mesh->tim->mode&0x3, 0,
mesh->tim->prect->x,
mesh->tim->prect->y
);
setUV3(poly, mesh->tmesh->u[i].vx , mesh->tmesh->u[i].vy + mesh->tim->prect->y,
mesh->tmesh->u[i+2].vx, mesh->tmesh->u[i+2].vy + mesh->tim->prect->y,
mesh->tmesh->u[i+1].vx, mesh->tmesh->u[i+1].vy + mesh->tim->prect->y);
}
// CLUT setup
// If tim mode == 0 | 1 (4bits/8bits image), set CLUT coordinates
if ( (mesh->tim->mode & 0x3 ) < 2){
setClut(poly,
mesh->tim->crect->x,
mesh->tim->crect->y);
}
2021-03-24 11:22:30 +01:00
if (*mesh->isSprite){
2021-03-21 12:57:01 +01:00
2021-03-24 11:22:30 +01:00
SetShadeTex( poly, 1 );
2021-03-21 12:57:01 +01:00
2021-03-24 11:22:30 +01:00
}
2021-03-21 12:57:01 +01:00
// Defaults depth color to neutral grey
2021-03-22 14:35:28 +01:00
CVECTOR outCol = { 128,128,128,0 };
CVECTOR outCol1 = { 128,128,128,0 };
CVECTOR outCol2 = { 128,128,128,0 };
2021-03-21 12:57:01 +01:00
NormalColorDpq(&mesh->tmesh->n[ mesh->index[t].order.vx ], &mesh->tmesh->c[ mesh->index[t].order.vx ], *mesh->p, &outCol);
NormalColorDpq(&mesh->tmesh->n[ mesh->index[t].order.vz ], &mesh->tmesh->c[ mesh->index[t].order.vz ], *mesh->p, &outCol1);
NormalColorDpq(&mesh->tmesh->n[ mesh->index[t].order.vy ], &mesh->tmesh->c[ mesh->index[t].order.vy ], *mesh->p, &outCol2);
// If transparent effect is in use, inhibate shadows
if (*mesh->isPrism){
// Use un-interpolated (i.e: no light, no fog) colors
setRGB0(poly, mesh->tmesh->c[i].r, mesh->tmesh->c[i].g, mesh->tmesh->c[i].b);
setRGB1(poly, mesh->tmesh->c[i+1].r, mesh->tmesh->c[i+1].g, mesh->tmesh->c[i+1].b);
setRGB2(poly, mesh->tmesh->c[i+2].r, mesh->tmesh->c[i+2].g, mesh->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);
}
if ( (*mesh->OTz > 0) && (*mesh->OTz < OTLEN) && (*mesh->p < 4096) ) {
AddPrim(&ot[db][*mesh->OTz-2], poly);
}
2021-03-29 11:44:06 +02:00
//~ mesh->pos2D.vx = *(&poly->x0);
//~ mesh->pos2D.vy = *(&poly->x0 + 1);
// mesh->pos2D.vy = poly->x0;
// FntPrint("%d %d\n", *(&poly->x0), *(&poly->x0 + 1));
2021-03-25 19:55:15 +01:00
2021-03-21 12:57:01 +01:00
nextpri += sizeof(POLY_GT3);
}
t+=1;
}
}
}
// If mesh is quad
if (mesh->index[t].code == 8) {
POLY_GT4 * poly4;
for (int i = 0; i < (mesh->tmesh->len * 4); i += 4) {
// if mesh is not part of BG, draw them, else, discard
if ( !(*mesh->isBG) || camMode != 2 ) {
poly4 = (POLY_GT4 *)nextpri;
// Vertex Anim
if (*mesh->isAnim){
// with interpolation
if ( mesh->anim->interpolate ){
// ping pong
//~ if (mesh->anim->cursor > 4096 || mesh->anim->cursor < 0){
//~ mesh->anim->dir *= -1;
//~ }
short precision = 12;
if ( mesh->anim->cursor > 1<<precision ) {
if ( mesh->anim->lerpCursor < mesh->anim->nframes - 1 ) {
mesh->anim->lerpCursor ++;
mesh->anim->cursor = 0;
}
if ( mesh->anim->lerpCursor == mesh->anim->nframes - 1 ) {
mesh->anim->lerpCursor = 0;
mesh->anim->cursor = 0;
}
}
// Vertex 1
mesh->tmesh->v[ mesh->index[ t ].order.vx ].vx = lerpD( mesh->anim->data[ mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[ t ].order.vx ].vx << 12 , mesh->anim->data[ (mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[ t ].order.vx ].vx << 12, mesh->anim->cursor << 12) >> 12;
mesh->tmesh->v[ mesh->index[ t ].order.vx ].vz = lerpD( mesh->anim->data[ mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[ t ].order.vx ].vz << 12 , mesh->anim->data[ (mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[ t ].order.vx ].vz << 12, mesh->anim->cursor << 12) >> 12;
mesh->tmesh->v[ mesh->index[ t ].order.vx ].vy = lerpD( mesh->anim->data[ mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[ t ].order.vx ].vy << 12 , mesh->anim->data[ (mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[ t ].order.vx ].vy << 12, mesh->anim->cursor << 12) >> 12;
// Vertex 2
mesh->tmesh->v[ mesh->index[ t ].order.vz ].vx = lerpD( mesh->anim->data[ mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[ t ].order.vz ].vx << 12 , mesh->anim->data[ (mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[ t ].order.vz ].vx << 12, mesh->anim->cursor << 12) >> 12;
mesh->tmesh->v[ mesh->index[ t ].order.vz ].vz = lerpD( mesh->anim->data[ mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[ t ].order.vz ].vz << 12 , mesh->anim->data[ (mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[ t ].order.vz ].vz << 12, mesh->anim->cursor << 12) >> 12;
mesh->tmesh->v[ mesh->index[ t ].order.vz ].vy = lerpD( mesh->anim->data[ mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[ t ].order.vz ].vy << 12 , mesh->anim->data[ (mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[ t ].order.vz ].vy << 12, mesh->anim->cursor << 12) >> 12;
// Vertex 3
mesh->tmesh->v[ mesh->index[ t ].order.vy ].vx = lerpD( mesh->anim->data[ mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[ t ].order.vy ].vx << 12 , mesh->anim->data[ (mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[ t ].order.vy ].vx << 12, mesh->anim->cursor << 12) >> 12;
mesh->tmesh->v[ mesh->index[ t ].order.vy ].vz = lerpD( mesh->anim->data[ mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[ t ].order.vy ].vz << 12 , mesh->anim->data[ (mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[ t ].order.vy ].vz << 12, mesh->anim->cursor << 12) >> 12;
mesh->tmesh->v[ mesh->index[ t ].order.vy ].vy = lerpD( mesh->anim->data[ mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[ t ].order.vy ].vy << 12 , mesh->anim->data[ (mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[ t ].order.vy ].vy << 12, mesh->anim->cursor << 12) >> 12;
// Vertex 4
mesh->tmesh->v[ mesh->index[ t ].order.pad ].vx = lerpD( mesh->anim->data[ mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[ t ].order.pad ].vx << 12 , mesh->anim->data[ (mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[ t ].order.pad ].vx << 12, mesh->anim->cursor << 12) >> 12;
mesh->tmesh->v[ mesh->index[ t ].order.pad ].vz = lerpD( mesh->anim->data[ mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[ t ].order.pad ].vz << 12 , mesh->anim->data[ (mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[ t ].order.pad ].vz << 12, mesh->anim->cursor << 12) >> 12;
mesh->tmesh->v[ mesh->index[ t ].order.pad ].vy = lerpD( mesh->anim->data[ mesh->anim->lerpCursor * mesh->anim->nvert + mesh->index[ t ].order.pad ].vy << 12 , mesh->anim->data[ (mesh->anim->lerpCursor + 1) * mesh->anim->nvert + mesh->index[ t ].order.pad ].vy << 12, mesh->anim->cursor << 12) >> 12;
mesh->anim->cursor += 2 * mesh->anim->dir;
// Coord transformations
nclip = RotAverageNclip4(
&mesh->tmesh->v[ mesh->index[t].order.pad ],
&mesh->tmesh->v[ mesh->index[t].order.vz],
&mesh->tmesh->v[ mesh->index[t].order.vx ],
&mesh->tmesh->v[ mesh->index[t].order.vy ],
( long* )&poly4->x0, ( long* )&poly4->x1, ( long* )&poly4->x2, ( long* )&poly4->x3,
mesh->p,
mesh->OTz,
Flag
);
} else {
// No interpolation, use all vertices coordinates in anim data
nclip = RotAverageNclip4(
&mesh->anim->data[ atime % mesh->anim->nframes * mesh->anim->nvert + mesh->index[t].order.pad ],
&mesh->anim->data[ atime % mesh->anim->nframes * mesh->anim->nvert + mesh->index[t].order.vz ],
&mesh->anim->data[ atime % mesh->anim->nframes * mesh->anim->nvert + mesh->index[t].order.vx ],
&mesh->anim->data[ atime % mesh->anim->nframes * mesh->anim->nvert + mesh->index[t].order.vy ],
( long* )&poly4->x0, ( long* )&poly4->x1, ( long* )&poly4->x2, ( long* )&poly4->x3,
mesh->p,
mesh->OTz,
Flag
);
}
} else {
// No animation
// Use regulare vertex coords
nclip = RotAverageNclip4(
&mesh->tmesh->v[ mesh->index[t].order.pad ],
&mesh->tmesh->v[ mesh->index[t].order.vz],
&mesh->tmesh->v[ mesh->index[t].order.vx ],
&mesh->tmesh->v[ mesh->index[t].order.vy ],
(long*)&poly4->x0, (long*)&poly4->x1, (long*)&poly4->x2, (long*)&poly4->x3,
mesh->p,
mesh->OTz,
Flag
);
}
if (nclip > 0 && *mesh->OTz > 0 && (*mesh->p < 4096)) {
SetPolyGT4(poly4);
// FIXME : Polygon subdiv - is it working ?
//~ OTc = *mesh->OTz >> 4;
//~ FntPrint("OTC:%d", OTc);
//~ if (OTc < 4) {
//~ if (OTc > 1) div4.ndiv = 1; else div4.ndiv = 2;
//~ DivideGT4(
//~ // Vertex coord
//~ &mesh->tmesh->v[ mesh->index[t].order.pad ],
//~ &mesh->tmesh->v[ mesh->index[t].order.vz ],
//~ &mesh->tmesh->v[ mesh->index[t].order.vx ],
//~ &mesh->tmesh->v[ mesh->index[t].order.vy ],
//~ // UV coord
//~ mesh->tmesh->u[i+3],
//~ mesh->tmesh->u[i+2],
//~ mesh->tmesh->u[i+0],
//~ mesh->tmesh->u[i+1],
//~ // Color
//~ mesh->tmesh->c[i],
//~ mesh->tmesh->c[i+1],
//~ mesh->tmesh->c[i+2],
//~ mesh->tmesh->c[i+3],
//~ // Gpu packet
//~ poly4,
//~ &ot[db][*mesh->OTz],
//~ &div4);
//~ // Increment primitive list pointer
//~ nextpri += ( (sizeof(POLY_GT4) + 3) / 4 ) * (( 1 << ( div4.ndiv )) << ( div4.ndiv ));
//~ triCount = ((1<<(div4.ndiv))<<(div4.ndiv));
//~ } else if (OTc < 48) {
// Transparency effect
if (*mesh->isPrism){
// Use current DRAWENV clip as TPAGE
( (POLY_GT4 *) poly4)->tpage = getTPage(mesh->tim->mode&0x3, 0,
draw[db].clip.x,
draw[db].clip.y
);
// Use projected coordinates
setUV4( poly4,
(poly4->x0 < 0? 0 : poly4->x0 > 255? 255 : poly4->x0),
(poly4->y0 < 0? 0 : poly4->y0 > 224? 224 : poly4->y0),
(poly4->x1 < 0? 0 : poly4->x1 > 255? 255 : poly4->x1),
(poly4->y1 < 0? 0 : poly4->y1 > 224? 224 : poly4->y1),
(poly4->x2 < 0? 0 : poly4->x2 > 255? 255 : poly4->x2),
(poly4->y2 < 0? 0 : poly4->y2 > 224? 224 : poly4->y2),
(poly4->x3 < 0? 0 : poly4->x3 > 255? 255 : poly4->x3),
(poly4->y3 < 0? 0 : poly4->y3 > 224? 224 : poly4->y3)
);
} else {
// Use regular TPAGE
( (POLY_GT4 *) poly4)->tpage = getTPage(
mesh->tim->mode&0x3, 0,
mesh->tim->prect->x,
mesh->tim->prect->y
);
// Use model UV coordinates
setUV4( poly4,
mesh->tmesh->u[i+3].vx, mesh->tmesh->u[i+3].vy + mesh->tim->prect->y,
mesh->tmesh->u[i+2].vx, mesh->tmesh->u[i+2].vy + mesh->tim->prect->y,
mesh->tmesh->u[i+0].vx, mesh->tmesh->u[i+0].vy + mesh->tim->prect->y,
mesh->tmesh->u[i+1].vx, mesh->tmesh->u[i+1].vy + mesh->tim->prect->y
);
}
2021-03-24 11:22:30 +01:00
if (*mesh->isSprite){
SetShadeTex( poly4, 1 );
}
2021-03-21 12:57:01 +01:00
// If tim mode == 0 | 1, set CLUT coordinates
if ( (mesh->tim->mode & 0x3) < 2 ) {
setClut(poly4,
mesh->tim->crect->x,
mesh->tim->crect->y
);
}
CVECTOR outCol = {128,128,128,0};
CVECTOR outCol1 = {128,128,128,0};
CVECTOR outCol2 = {128,128,128,0};
CVECTOR outCol3 = {128,128,128,0};
NormalColorDpq(&mesh->tmesh->n[ mesh->index[t].order.pad ] , &mesh->tmesh->c[ mesh->index[t].order.pad ], *mesh->p, &outCol);
NormalColorDpq(&mesh->tmesh->n[ mesh->index[t].order.vz ], &mesh->tmesh->c[ mesh->index[t].order.vz ], *mesh->p, &outCol1);
NormalColorDpq(&mesh->tmesh->n[ mesh->index[t].order.vx ], &mesh->tmesh->c[ mesh->index[t].order.vx ], *mesh->p, &outCol2);
NormalColorDpq(&mesh->tmesh->n[ mesh->index[t].order.vy ], &mesh->tmesh->c[ mesh->index[t].order.vy ], *mesh->p, &outCol3);
if (*mesh->isPrism){
setRGB0(poly4, mesh->tmesh->c[i].r, mesh->tmesh->c[i].g, mesh->tmesh->c[i].b);
setRGB1(poly4, mesh->tmesh->c[i+1].r, mesh->tmesh->c[i+1].g, mesh->tmesh->c[i+1].b);
setRGB2(poly4, mesh->tmesh->c[i+2].r, mesh->tmesh->c[i+2].g, mesh->tmesh->c[i+2].b);
setRGB3(poly4, mesh->tmesh->c[i+3].r, mesh->tmesh->c[i+3].g, mesh->tmesh->c[i+3].b);
} else {
setRGB0(poly4, outCol.r, outCol.g , outCol.b);
setRGB1(poly4, outCol1.r, outCol1.g, outCol1.b);
setRGB2(poly4, outCol2.r, outCol2.g, outCol2.b);
setRGB3(poly4, outCol3.r, outCol3.g, outCol3.b);
}
if ( (*mesh->OTz > 0) && (*mesh->OTz < OTLEN) && (*mesh->p < 4096) ) {
AddPrim( &ot[ db ][ *mesh->OTz-3 ], poly4 );
}
nextpri += sizeof( POLY_GT4 );
}
t += 1;
}
}
}
};
2021-03-22 14:35:28 +01:00
void drawBG(void){
// Draw BG image in two SPRT since max width == 256 px
SPRT * sprt;
DR_TPAGE * tpage;
// Left part
sprt = ( SPRT * ) nextpri;
setSprt( sprt );
setRGB0( sprt, 128, 128, 128 );
setXY0( sprt, 0, 0 );
setWH( sprt, 256, SCREENYRES );
setUV0( sprt, 0, 0 );
setClut( sprt,
camPtr->BGtim->crect->x,
camPtr->BGtim->crect->y
);
addPrim( &otdisc[ db ][ OT2LEN-1 ], sprt );
nextpri += sizeof( SPRT );
// Change TPAGE
tpage = (DR_TPAGE *) nextpri;
setDrawTPage(
tpage, 0, 1,
getTPage(
camPtr->BGtim->mode & 0x3, 0,
camPtr->BGtim->prect->x,
camPtr->BGtim->prect->y
)
);
addPrim(&otdisc[db][OT2LEN-1], tpage);
nextpri += sizeof(DR_TPAGE);
// Right part
sprt = ( SPRT * ) nextpri;
setSprt( sprt );
setRGB0( sprt, 128, 128, 128 );
setXY0( sprt, SCREENXRES - ( SCREENXRES - 256 ), 0 );
setWH( sprt, SCREENXRES - 256, SCREENYRES );
setUV0( sprt, 0, 0 );
setClut( sprt,
camPtr->BGtim->crect->x,
camPtr->BGtim->crect->y
);
addPrim( &otdisc[ db ][ OT2LEN-1 ], sprt );
nextpri += sizeof( SPRT );
tpage = ( DR_TPAGE * ) nextpri;
// Change TPAGE
setDrawTPage(
tpage, 0, 1,
getTPage(
camPtr->BGtim->mode & 0x3, 0,
camPtr->BGtim->prect->x + 128,
camPtr->BGtim->prect->y
)
);
addPrim( &otdisc[ db ][ OT2LEN-1 ], tpage );
nextpri += sizeof( DR_TPAGE );
};
2021-03-21 12:57:01 +01:00
// Maths
2021-02-28 11:14:02 +01:00
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
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
*x = (actorX << 12) + (distance * nsin(angle));
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
*z = (actorZ << 12) - (distance * ncos(angle));
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
};
2021-02-28 11:14:02 +01:00
// @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
2021-03-21 12:57:01 +01:00
void applyCamera( CAMERA * cam ) {
2021-02-28 11:14:02 +01:00
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
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
SetTransMatrix(&cam->mat); // Set Transform matrix
2021-03-21 12:57:01 +01:00
};
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
void setCameraPos( VECTOR pos, SVECTOR rot ) {
2021-02-28 11:14:02 +01:00
camera.pos = pos;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
camera.rot = rot;
2021-03-21 12:57:01 +01:00
};
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
VECTOR getVectorTo( VECTOR actor, VECTOR target ) {
VECTOR direction = { subVector(target, actor) };
VECTOR Ndirection = {0,0,0,0};
u_int distSq = (direction.vx * direction.vx) + (direction.vz * direction.vz);
direction.pad = psqrt(distSq);
VectorNormal(&direction, &Ndirection);
return Ndirection ;
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
};
2021-03-29 11:44:06 +02:00
// From 'psyq/addons/graphics/ZIMEN/CLIP.C'
void worldToScreen( VECTOR * worldPos, VECTOR * screenPos ) {
2021-04-01 13:12:57 +02:00
int distToScreen; // corresponds to FOV
2021-03-29 11:44:06 +02:00
MATRIX curRot; // current rotation matrix
// Get current matrix and projection */
distToScreen = ReadGeomScreen();
ReadRotMatrix(&curRot);
// Get Rotation, Translation coordinates, apply perspective correction
2021-04-01 13:12:57 +02:00
// Muliply world coordinates vector by current rotation matrix, store in screenPos
2021-03-29 11:44:06 +02:00
ApplyMatrixLV(&curRot, worldPos, screenPos);
2021-04-01 13:12:57 +02:00
// Get world translation vectors from rot and add to screenPos vx, vy, vz
2021-03-29 11:44:06 +02:00
applyVector(screenPos, curRot.t[0], curRot.t[1], curRot.t[2], +=);
// Correct perspective
2021-04-01 13:12:57 +02:00
screenPos -> vx = screenPos -> vx * distToScreen / ( screenPos -> vz + 1 ) ; // Add 1 to avoid division by 0
2021-03-29 11:44:06 +02:00
2021-04-01 13:12:57 +02:00
screenPos -> vy = screenPos -> vy * distToScreen / ( screenPos -> vz + 1 ) ;
screenPos -> vz = distToScreen ;
2021-03-29 11:44:06 +02:00
};
void screenToWorld( VECTOR * screenPos, VECTOR * worldPos ) {
2021-04-01 13:12:57 +02:00
int distToScreen; // corresponds to FOV
2021-03-29 11:44:06 +02:00
2021-04-01 13:12:57 +02:00
MATRIX curRot, invRot; // current rotation matrix, transpose matrix
2021-03-29 11:44:06 +02:00
2021-04-01 13:12:57 +02:00
VECTOR Trans; // working translation vector
2021-03-29 11:44:06 +02:00
2021-04-01 13:12:57 +02:00
// Get current matrix and projection
2021-03-29 11:44:06 +02:00
distToScreen = ReadGeomScreen();
2021-04-01 13:12:57 +02:00
ReadRotMatrix( &curRot );
2021-03-29 11:44:06 +02:00
2021-04-01 13:12:57 +02:00
PushMatrix(); // Store matrix on the stack (slow!)
2021-03-29 11:44:06 +02:00
2021-04-01 13:12:57 +02:00
//// worldTrans = invRot * (screenPos - Rot.t)
2021-03-29 11:44:06 +02:00
2021-04-01 13:12:57 +02:00
// Get world translation
Trans.vx = screenPos->vx - curRot.t[0]; // Substract world translation from screenpos
2021-03-29 11:44:06 +02:00
2021-04-01 13:12:57 +02:00
Trans.vy = screenPos->vy - curRot.t[1];
2021-03-29 11:44:06 +02:00
2021-04-01 13:12:57 +02:00
Trans.vz = screenPos->vz - curRot.t[2];
// We want the inverse of the current rotation matrix.
//
// Inverse matrix : M^-1 = 1 / detM * T(M)
// We know that the determinant of a rotation matrix is 1, thus:
// M^-1 = T(M)
//
// Get transpose of current rotation matrix
// > The transpose of a matrix is a new matrix whose rows are the columns of the original.
// https://www.quora.com/What-is-the-geometric-interpretation-of-the-transpose-of-a-matrix
TransposeMatrix( &curRot, &invRot );
2021-03-29 11:44:06 +02:00
2021-04-01 13:12:57 +02:00
// Multiply the transpose of current rotation matrix by the current translation vector
2021-03-29 11:44:06 +02:00
2021-04-01 13:12:57 +02:00
ApplyMatrixLV( &invRot, &Trans, worldPos );
2021-03-29 11:44:06 +02:00
2021-04-01 13:12:57 +02:00
// Get original rotation matrix back
2021-03-29 11:44:06 +02:00
PopMatrix();
};
2021-03-21 12:57:01 +01:00
//~ int alignAxisToVect(VECTOR target, short axis, int factor){
//~ }
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
// Lerp
2021-02-28 11:14:02 +01:00
int lerp(int start, int end, int factor){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
// lerp interpolated cam movement
// InBetween = Value 1 + ( ( Value2 - Value1 ) * lerpValue ) ;
// lerpValue should be a float between 0 and 1.
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
return ( start ) + (( end - start ) * factor ) >> 12;
2021-03-21 12:57:01 +01:00
};
2021-02-28 11:14:02 +01:00
long long easeIn(long long i, int div){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
return ((i << 7) * (i << 7) * (i << 7) / div ) >> 19;
2021-03-21 12:57:01 +01:00
};
2021-02-28 11:14:02 +01:00
int easeOut(int i){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
return (4096 >> 7) - ((4096 - (i << 7)) * (4096 - (i << 7))) >> 12;
2021-03-21 12:57:01 +01:00
};
2021-02-28 11:14:02 +01:00
int easeInOut(int i, int div){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
return lerp(easeIn(i, div), easeOut(i) , i);
2021-03-21 12:57:01 +01:00
};
2021-02-28 11:14:02 +01:00
SVECTOR SVlerp(SVECTOR start, SVECTOR end, int factor){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
SVECTOR output = {0,0,0,0};
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
output.vx = lerp(start.vx, end.vx, factor);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
output.vy = lerp(start.vy, end.vy, factor);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
output.vz = lerp(start.vz, end.vz, factor);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
return output;
2021-03-21 12:57:01 +01:00
};
2021-03-15 15:58:21 +01:00
2021-03-21 12:57:01 +01:00
// Physics
2021-02-28 11:14:02 +01:00
VECTOR getIntCollision(BODY one, BODY two){
VECTOR d1, d2, col;
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
short correction = 50;
2021-02-28 11:14:02 +01:00
2021-03-16 16:18:36 +01:00
d1.vx = (one.position.vx + one.max.vx) - (two.position.vx + two.min.vx);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
d1.vy = (one.position.vy + one.max.vy) - (two.position.vy + two.min.vy);
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
d1.vz = (one.position.vz + one.max.vz) - (two.position.vz + two.min.vz);
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
2021-03-16 16:18:36 +01:00
d2.vx = (two.position.vx + two.max.vx) - (one.position.vx - one.max.vx);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
d2.vy = (two.position.vy + two.max.vy) - (one.position.vy + one.min.vy);
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
d2.vz = (two.position.vz + two.max.vz) - (one.position.vz - one.max.vz);
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
col.vx = !(d1.vx > 0 && d2.vx > 0);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
col.vy = d1.vy > 0 && d2.vy > 0;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
col.vz = !(d1.vz > 0 && d2.vz > 0);
return col;
2021-03-21 12:57:01 +01:00
};
2021-02-28 11:14:02 +01:00
VECTOR getExtCollision(BODY one, BODY two){
VECTOR d1, d2, col;
d1.vx = (one.position.vx + one.max.vx) - (two.position.vx + two.min.vx);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
d1.vy = (one.position.vy + one.max.vy) - (two.position.vy + two.min.vy);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
d1.vz = (one.position.vz + one.max.vz) - (two.position.vz + two.min.vz);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
d2.vx = (two.position.vx + two.max.vx) - (one.position.vx + one.min.vx);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
d2.vy = (two.position.vy + two.max.vy) - (one.position.vy + one.min.vy);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
d2.vz = (two.position.vz + two.max.vz) - (one.position.vz + one.min.vz);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
col.vx = d1.vx > 0 && d2.vx > 0;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
col.vy = d1.vy > 0 && d2.vy > 0;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
col.vz = d1.vz > 0 && d2.vz > 0;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
return col;
2021-03-21 12:57:01 +01:00
};
2021-02-28 11:14:02 +01:00
void applyAcceleration(BODY * actor){
short dt = 1;
VECTOR acceleration = {actor->invMass * actor->gForce.vx , (actor->invMass * actor->gForce.vy) + (gravity * ONE), actor->invMass * actor->gForce.vz};
//~ FntPrint("acc: %d %d %d\n", acceleration.vx, acceleration.vy, acceleration.vz );
actor->velocity.vx += (acceleration.vx * dt) >> 12;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
actor->velocity.vy += (acceleration.vy * dt) >> 12;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
actor->velocity.vz += (acceleration.vz * dt) >> 12;
//~ FntPrint("acc: %d %d %d\n", acceleration.vx / ONE, acceleration.vy / ONE, acceleration.vz / ONE );
actor->position.vx += (actor->velocity.vx * dt);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
actor->position.vy += (actor->velocity.vy * dt);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
actor->position.vz += (actor->velocity.vz * dt);
//~ FntPrint("vel: %d %d %d\n", actor->velocity.vx, actor->velocity.vy, actor->velocity.vz );
2021-03-21 12:57:01 +01:00
};
2021-02-28 11:14:02 +01:00
//~ // https://gamedevelopment.tutsplus.com/tutorials/how-to-create-a-custom-2d-physics-engine-the-basics-and-impulse-resolution--gamedev-6331
void ResolveCollision( BODY * one, BODY * two ){
2021-03-21 12:57:01 +01:00
//~ FntPrint("rv: %d, %d, %d\n", one->velocity.vx, one->velocity.vy, one->velocity.vz);
// Calculate relative velocity
VECTOR rv = { subVector( one->velocity, two->velocity) };
//~ FntPrint("rv: %d, %d, %d\n", rv.vx,rv.vy,rv.vz);
// Collision normal
VECTOR normal = { subVector( two->position, one->position ) };
// Normalize collision normal
normal.vx = normal.vx > 0 ? 1 : normal.vx < 0 ? -1 : 0 ;
normal.vy = normal.vy > 256 ? 1 : normal.vy < -256 ? -1 : 0 ;
normal.vz = normal.vz > 0 ? 1 : normal.vz < 0 ? -1 : 0 ;
//~ FntPrint("norm: %d, %d, %d\n", normal.vx,normal.vy,normal.vz);
// Calculate relative velocity in terms of the normal direction
long velAlongNormal = dotProduct( rv, normal );
//~ FntPrint("velN: %d\n", velAlongNormal);
// Do not resolve if velocities are separating
if(velAlongNormal > 0)
2021-02-28 11:14:02 +01:00
return;
2021-03-21 12:57:01 +01:00
// Calculate restitution
long e = min( one->restitution, two->restitution );
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
//~ FntPrint("e: %d\n", e);
//~ // Calculate impulse scalar
long j = -(1 + e) * velAlongNormal * ONE;
j /= one->invMass + two->invMass;
//~ j /= ONE;
//~ FntPrint("j: %d\n", j);
// Apply impulse
applyVector(&normal, j, j, j, *=);
//~ FntPrint("Cnormal %d %d %d\n",normal.vx,normal.vy,normal.vz);
VECTOR velOne = normal;
VECTOR velTwo = normal;
applyVector(&velOne,one->invMass,one->invMass,one->invMass, *=);
applyVector(&velTwo,two->invMass,two->invMass,two->invMass, *=);
//~ FntPrint("V1 %d %d %d\n", velOne.vx/4096,velOne.vy/4096,velOne.vz/4096);
//~ FntPrint("V2 %d %d %d\n", velTwo.vx/4096,velTwo.vy/4096,velTwo.vz/4096);
applyVector(&one->velocity, velOne.vx/4096/4096, velOne.vy/4096/4096, velOne.vz/4096/4096, +=);
applyVector(&two->velocity, velTwo.vx/4096/4096, velTwo.vy/4096/4096, velTwo.vz/4096/4096, -=);
//~ FntPrint("V1 %d %d %d\n", velOne.vx/4096/4096,velOne.vy/4096/4096,velOne.vz/4096/4096);
//~ FntPrint("V2 %d %d %d\n", velTwo.vx/4096/4096,velTwo.vy/4096/4096,velTwo.vz/4096/4096);
};
2021-02-28 11:14:02 +01:00
VECTOR angularMom(BODY body){
// L = r * p
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
// p = m * v
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
VECTOR w = {0,0,0,0};
2021-03-15 15:58:21 +01:00
int r = (body.max.vx - body.min.vx) >> 1;
2021-02-28 11:14:02 +01:00
2021-03-15 15:58:21 +01:00
w.vx = (r * body.mass * body.velocity.vx) >> 2;
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
w.vy = (r * body.mass * body.velocity.vy) >> 2;
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
w.vz = (r * body.mass * body.velocity.vz) >> 2;
2021-02-28 11:14:02 +01:00
2021-03-16 16:18:36 +01:00
//~ FntPrint("v: %d, r:%d, w:%d\n", body.velocity.vz * r, r * r, w.vz);
2021-02-28 11:14:02 +01:00
return w;
2021-03-21 12:57:01 +01:00
};
2021-02-28 11:14:02 +01:00
// From : https://github.com/grumpycoders/pcsx-redux/blob/7438e9995833db5bc1e14da735bbf9dc78300f0b/src/mips/shell/math.h
static inline int32_t dMul(int32_t a, int32_t b) {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
long long r = a;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
r *= b;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
return r >> 24;
2021-03-21 12:57:01 +01:00
};
2021-02-28 11:14:02 +01:00
// standard lerp function
// s = source, an arbitrary number up to 2^24
// d = destination, an arbitrary number up to 2^24
// p = position, a number between 0 and 256, inclusive
// p = 0 means output = s
// p = 256 means output = d
2021-03-21 12:57:01 +01:00
static inline uint32_t lerpU(uint32_t start, uint32_t dest, unsigned pos) { return (start * (256 - pos) + dest * pos) >> 8; };
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
static inline int32_t lerpS(int32_t start, int32_t dest, unsigned pos) { return (start * (256 - pos) + dest * pos) >> 8; };
2021-02-28 11:14:02 +01:00
// start, dest and pos have to be << x, then the result has to be >> x where x defines precision:
// precision = 2^24 - 2^x
// << x : 0 < pos < precision
// https://discord.com/channels/642647820683444236/646765703143227394/811318550978494505
// my angles are between 0 and 2048 (full circle), so 2^11 for the range of angles; with numbers on a 8.24 representation, a 1.0 angle (or 2pi) means it's 2^24, so to "convert" my angles from 8.24 to my internal discrete cos, I only have to shift by 13
2021-03-21 12:57:01 +01:00
static inline int32_t lerpD(int32_t start, int32_t dest, int32_t pos) { return dMul(start, 16777216 - pos) + dMul(dest, pos); };
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
static inline long long lerpL(long long start, long long dest, long long pos){ return dMul( (start << 12), 16777216 - (pos << 12) ) + dMul((dest << 12), (pos << 12) ) >> 12; };
2021-02-28 11:14:02 +01:00
// A few notes on the following code :
int ncos(unsigned int t) {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
t %= DC_2PI;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
int r;
if (t < DC_PI2) {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
r = m_cosTable[t];
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
} else if (t < DC_PI) {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
r = -m_cosTable[DC_PI - 1 - t];
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
} else if (t < (DC_PI + DC_PI2)) {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
r = -m_cosTable[t - DC_PI];
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
} else {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
r = m_cosTable[DC_2PI - 1 - t];
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
};
return r >> 12;
};
// sin(x) = cos(x - pi / 2)
int nsin(unsigned int t) {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
t %= DC_2PI;
if (t < DC_PI2){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
return ncos(t + DC_2PI - DC_PI2);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
};
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
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
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
static const long long C = 16777137; // 2^24 * cos(1 * 2pi / 2048) = C = f(1);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
m_cosTable[1] = C;
for (int i = 2; i < 512; i++){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
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
2021-03-15 15:58:21 +01:00
long long patan(long x, long y){
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
long long result;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
int swapBuf;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
int flags = 0;
// if either x or y are 0, return 0
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
if( x == 0 && y == 0){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
return 0;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
}
if( x < 0 ) {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
flags |= 4;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
x = -x;
}
if ( y < 0 ) {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
flags |= 2;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
y = -y;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
}
if ( y > x ) {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
flags |= 1;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
SWAP(x, y ,swapBuf);
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
}
result = AtanBaseTable[flags] + AtanAngleTable[0x800 * y / x];
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
if ( result < 0 ){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
result = -result;
return result;
}
2021-03-21 12:57:01 +01:00
};
2021-02-28 11:14:02 +01:00
u_int psqrt(u_int n){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
u_int result = 0;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
u_int base = 0x40000000;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
u_int basedResult;
for( ; base != 0; base >>= 2 ) {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
for( ; base != 0; base >>= 2 ) {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
basedResult = base + result;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
result >>= 1;
if( basedResult > n ) {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
break;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
}
n -= basedResult;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
result |= base;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
}
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
}
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
return result;
2021-03-21 12:57:01 +01:00
};
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
int cliptest3( short *v1 ) {
2021-02-28 11:14:02 +01:00
if( v1[0]<0 && v1[2]<0 && v1[4]<0 ) return 0;
2021-03-21 12:57:01 +01:00
if( v1[1]<0 && v1[3]<0 && v1[5]<0 ) return 0;
2021-02-28 11:14:02 +01:00
if( v1[0] > SCREENXRES && v1[2] > SCREENXRES && v1[4] > SCREENXRES) return 0;
2021-03-21 12:57:01 +01:00
if( v1[1] > SCREENYRES && v1[3] > SCREENYRES && v1[5] > SCREENYRES) return 0;
2021-02-28 11:14:02 +01:00
return 1;
2021-03-21 12:57:01 +01:00
};
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
void callback() {
2021-02-28 11:14:02 +01:00
u_short pad = PadRead(0);
static u_short lastPad;
static short forceApplied = 0;
int div = 4096 >> 7;
static int lerpValues[4096 >> 7];
static short cursor = 0;
2021-03-24 11:22:30 +01:00
//~ static short curCamAngle = 0;
2021-03-06 11:45:25 +01:00
2021-03-21 12:57:01 +01:00
if( !lerpValues[0] ) {
2021-02-28 11:14:02 +01:00
for ( long long i = 0; i < div ; i++ ){
2021-03-21 12:57:01 +01:00
lerpValues[(div-1)-i] = lerp(-24, -264, easeIn(i, div));
2021-02-28 11:14:02 +01:00
}
}
2021-03-21 12:57:01 +01:00
if( timer ) {
timer--;
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
}
if( cursor>0 ) {
cursor--;
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
}
2021-02-28 11:14:02 +01:00
2021-03-21 12:57:01 +01:00
if ( pad & PADR1 && !timer ) {
2021-03-06 11:45:25 +01:00
if (!camPtr->tim_data){
2021-03-21 12:57:01 +01:00
2021-03-06 11:45:25 +01:00
if(camMode < 6){
camMode ++;
2021-03-21 12:57:01 +01:00
2021-03-06 11:45:25 +01:00
lerping = 0;
} else {
2021-03-21 12:57:01 +01:00
2021-03-06 11:45:25 +01:00
setCameraPos(camPtr->campos->pos, camPtr->campos->rot);
2021-03-21 12:57:01 +01:00
2021-03-06 11:45:25 +01:00
camPath.cursor = 0;
2021-03-21 12:57:01 +01:00
2021-03-06 11:45:25 +01:00
camMode = 0;
2021-03-21 12:57:01 +01:00
2021-03-06 11:45:25 +01:00
lerping = 0;
}
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
} else {
2021-03-24 11:22:30 +01:00
if (curCamAngle > 4) {
curCamAngle = 0;
}
2021-03-21 12:57:01 +01:00
2021-03-06 11:45:25 +01:00
if (curCamAngle < 5) {
2021-03-21 12:57:01 +01:00
2021-03-06 11:45:25 +01:00
curCamAngle++;
2021-03-21 12:57:01 +01:00
2021-03-22 14:35:28 +01:00
camPtr = camAngles[ curCamAngle ];
2021-03-21 12:57:01 +01:00
2021-03-06 11:45:25 +01:00
LoadTexture(camPtr->tim_data, camPtr->BGtim);
2021-03-21 12:57:01 +01:00
2021-03-24 11:22:30 +01:00
}
2021-02-28 11:14:02 +01:00
}
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
lastPad = pad;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
timer = 10;
}
2021-03-21 12:57:01 +01:00
if ( !(pad & PADR1) && lastPad & PADR1 ) {
2021-02-28 11:14:02 +01:00
//~ pressed = 0;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
}
2021-03-21 12:57:01 +01:00
if ( pad & PADL2 ) {
2021-02-28 11:14:02 +01:00
lgtang.vy += 32;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
}
2021-03-21 12:57:01 +01:00
if ( pad & PADL1 ) {
2021-02-28 11:14:02 +01:00
lgtang.vz += 32;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
}
2021-03-21 12:57:01 +01:00
if ( pad & PADRup && !timer ){
2021-02-28 11:14:02 +01:00
if (*actorPtr->isPrism){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
*actorPtr->isPrism = 0;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
} else {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
*actorPtr->isPrism = 1;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
}
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
timer = 10;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
lastPad = pad;
}
if ( pad & PADRdown && !timer ){
//~ if (actorPtr->body->gForce.vy >= 0 && actorPtr->body->position.vy >= actorPtr->body->min.vy ){
//~ forceApplied -= 150;
//~ }
cursor = div - 15;
2021-03-25 19:55:15 +01:00
2021-02-28 11:14:02 +01:00
timer = 30;
2021-03-25 19:55:15 +01:00
2021-02-28 11:14:02 +01:00
lastPad = pad;
}
2021-03-21 12:57:01 +01:00
if ( !(pad & PADRdown) && lastPad & PADRdown ) {
2021-02-28 11:14:02 +01:00
//~ lastPad = pad;
}
2021-03-21 12:57:01 +01:00
if ( pad & PADRleft && !timer ) {
2021-02-28 11:14:02 +01:00
if (actorPtr->anim->interpolate){
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
actorPtr->anim->interpolate = 0;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
} else {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
actorPtr->anim->interpolate = 1;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
}
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
timer = 10;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
lastPad = pad;
}
2021-03-21 12:57:01 +01:00
if ( pad & PADLup ) {
2021-03-15 15:58:21 +01:00
actorPtr->body->gForce.vz = getVectorTo(fVecActor, *actorPtr->pos).vz >> 8 ;
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
actorPtr->body->gForce.vx = -getVectorTo(fVecActor, *actorPtr->pos).vx >> 8 ;
2021-02-28 11:14:02 +01:00
lastPad = pad;
}
if ( !(pad & PADLup) && lastPad & PADLup) {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
actorPtr->body->gForce.vz = 0;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
actorPtr->body->gForce.vx = 0;
}
2021-03-21 12:57:01 +01:00
if ( pad & PADLdown ) {
2021-03-15 15:58:21 +01:00
actorPtr->body->gForce.vz = -getVectorTo(fVecActor, *actorPtr->pos).vz >> 8 ;
2021-03-21 12:57:01 +01:00
2021-03-15 15:58:21 +01:00
actorPtr->body->gForce.vx = getVectorTo(fVecActor, *actorPtr->pos).vx >> 8 ;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
lastPad = pad;
}
if ( !(pad & PADLdown) && lastPad & PADLdown) {
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
actorPtr->body->gForce.vz = 0;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
actorPtr->body->gForce.vx = 0;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
lastPad = pad;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
}
2021-03-21 12:57:01 +01:00
if ( pad & PADLleft ) {
2021-03-15 15:58:21 +01:00
actorPtr->rot->vy -= 32;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
lastPad = pad;
}
2021-03-21 12:57:01 +01:00
if ( pad & PADLright ) {
2021-03-15 15:58:21 +01:00
actorPtr->rot->vy += 32;
2021-03-21 12:57:01 +01:00
2021-02-28 11:14:02 +01:00
lastPad = pad;
}
2021-03-21 12:57:01 +01:00
if ( cursor ) {
2021-02-28 11:14:02 +01:00
actorPtr->body->position.vy = lerpValues[cursor];}
2021-03-21 12:57:01 +01:00
};