Is it possible to use SetRotMatrix/SetTransMatrix for geometry and camera at the same time?

Graphic based area of development (Graphics Processing Unit), including the Geometry Transform Engine (GTE), TIM, STR (MDEC), etc.
Post Reply
User avatar
NITROYUASH
Verified
Serious PSXDEV User
Serious PSXDEV User
Posts: 124
Joined: Jan 07, 2018
I am a: Game Designer
PlayStation Model: SCPH-5502
Location: Russian Federation
Contact:

Is it possible to use SetRotMatrix/SetTransMatrix for geometry and camera at the same time?

Post by NITROYUASH » November 21st, 2018, 4:57 am

Hi PSXDEV. I have a small question about SetRotMatrix (SRM) and SetTransMatrix (STM).
► Show Spoiler
In this example i have one SRM and STM for camera (viev.viev) and second for 3d primitive (omtx). But i can't make them work together. So... Is it possible to use SetRotMatrix/SetTransMatrix for geometry and camera at the same time?

User avatar
LameGuy64
Verified
Psy-Q Enthusiast
Psy-Q Enthusiast
Posts: 388
Joined: Apr 10, 2013
I am a: Hobbyist Game Developer
Motto: Commercial or not, play it!
PlayStation Model: H2000/7000
Location: Philippines
Contact:

Post by LameGuy64 » November 21st, 2018, 12:26 pm

I usually just have a pair of vectors for both the camera position and angle and then applying it to a matrix using the first person view matrix logic from my examples featuring a first person style camera.

Putting the relevant code here for easy reference:

Code: Select all

VECTOR cam_pos;     // Camera position
SVECTOR cam_rot;    // Camera rotation
MATRIX cam_mat;     // Camera matrix

VECTOR vec;         // Just a temporary

RotMatrix( &cam_rot, &cam_mat );
ApplyMatrixLV( &cam_mat, &cam_pos, &vec );	
TransMatrix( &cam_mat, &vec );

SetRotMatrix( &mtx );
SetTransMatrix( &mtx );

< sort your level geometry >
To place objects relative to the camera matrix, I do the following matrix calculations:

Code: Select all

VECTOR obj_pos;     // Object position
SVECTOR obj_rot;    // Object rotation
MATRIX obj_mtx;     // Object matrix

MATRIX tmp_mtx;     // Just a temporary

RotMatrix( &obj_rot, &obj_mtx );
TransMatrix( &obj_mtx, &obj_pos );

// The following 2 lines are only needed for lighting (light_mtx is your light direction matrix)
MulMatrix0( &light_mtx, &obj_mtx, &tmp_mtx );
SetLightMatrix( &tmp_mtx );
		
// tmp_mtx will be the matrix of the object relative to the camera
CompMatrixLV( &cam_mtx, &obj_mtx, &tmp_mtx );

SetRotMatrix( &tmp_mtx );
SetTransMatrix( &tmp_mtx );

< sort your object >

SetRotMatrix( &mtx );     // Revert back to camera matrix
SetTransMatrix( &mtx );   // (not needed if you're just sorting objects)
Object position and rotation must be absolute world-space coordinates. As in, no need to manually translate them relative to camera coordinates beforehand as the logic already does that for you. This method has worked really well for me so far.

If you plan to do a third person view I highly recommend using the LookAt function example I posted sometime ago on this forum. You can use the matrix it generates as the camera view directly.
Please don't forget to include my name if you share my work around. Credit where it is due.

Dev. Console: SCPH-7000 with SCPH-7501 ROM, MM3, PAL color fix, Direct AV ports, DB-9 port for Serial I/O, and a Xplorer FX with Caetla 0.35.

DTL-H2000 PC: Dell Optiplex GX110, Windows 98SE & Windows XP, Pentium III 933MHz, 384MB SDRAM, ATI Radeon 7000 VE 64MB, Soundblaster Audigy, 40GB Seagate HDD, Hitachi Lite-on CD-RW Drive, ZIP 250 and 3.5" Floppy.

User avatar
NITROYUASH
Verified
Serious PSXDEV User
Serious PSXDEV User
Posts: 124
Joined: Jan 07, 2018
I am a: Game Designer
PlayStation Model: SCPH-5502
Location: Russian Federation
Contact:

Post by NITROYUASH » November 21st, 2018, 8:55 pm

CompMatrixLV( &cam_mtx, &obj_mtx, &tmp_mtx );

cam_mtx? Not cam_mat? This is fine?

User avatar
LameGuy64
Verified
Psy-Q Enthusiast
Psy-Q Enthusiast
Posts: 388
Joined: Apr 10, 2013
I am a: Hobbyist Game Developer
Motto: Commercial or not, play it!
PlayStation Model: H2000/7000
Location: Philippines
Contact:

Post by LameGuy64 » November 21st, 2018, 9:36 pm

That's just my preferred naming convention. You can name it whatever you want really.
Please don't forget to include my name if you share my work around. Credit where it is due.

Dev. Console: SCPH-7000 with SCPH-7501 ROM, MM3, PAL color fix, Direct AV ports, DB-9 port for Serial I/O, and a Xplorer FX with Caetla 0.35.

DTL-H2000 PC: Dell Optiplex GX110, Windows 98SE & Windows XP, Pentium III 933MHz, 384MB SDRAM, ATI Radeon 7000 VE 64MB, Soundblaster Audigy, 40GB Seagate HDD, Hitachi Lite-on CD-RW Drive, ZIP 250 and 3.5" Floppy.

User avatar
NITROYUASH
Verified
Serious PSXDEV User
Serious PSXDEV User
Posts: 124
Joined: Jan 07, 2018
I am a: Game Designer
PlayStation Model: SCPH-5502
Location: Russian Federation
Contact:

Post by NITROYUASH » November 21st, 2018, 9:45 pm

Okay, this is code for camera (Looks familiar, doesn't it? :D):

Code: Select all

void CalculateCamera() {
	
	// This function simply calculates the viewpoint matrix based on the camera coordinates...
	// It must be called on every frame before drawing any objects.

	//View handler
	GsVIEW2 view;
	
	// Temporary
	VECTOR	vec;
	
	// Copy the camera (base) matrix for the viewpoint matrix
	view.view = Camera.coord2.coord;
	view.super = WORLD;

	RotMatrix(&Camera.rot, &view.view);
	ApplyMatrixLV(&view.view, &Camera.pos, &vec);
	TransMatrix(&view.view, &vec);

	// This is for geometry
	SetRotMatrix(&view.view);
	SetTransMatrix(&view.view);
	
	// Set the viewpoint matrix to the GTE
	GsSetView2(&view);
	
}
So, my CompMatrixLV would be look like this?
CompMatrixLV(&view.view, &omtx, &tmtx);

User avatar
LameGuy64
Verified
Psy-Q Enthusiast
Psy-Q Enthusiast
Posts: 388
Joined: Apr 10, 2013
I am a: Hobbyist Game Developer
Motto: Commercial or not, play it!
PlayStation Model: H2000/7000
Location: Philippines
Contact:

Post by LameGuy64 » November 22nd, 2018, 1:06 pm

That should do it for the first person camera. I'm not sure how libgs would treat it though as I haven't used that library in a long time as I usually use plain libgte+libgpu for graphics.
Please don't forget to include my name if you share my work around. Credit where it is due.

Dev. Console: SCPH-7000 with SCPH-7501 ROM, MM3, PAL color fix, Direct AV ports, DB-9 port for Serial I/O, and a Xplorer FX with Caetla 0.35.

DTL-H2000 PC: Dell Optiplex GX110, Windows 98SE & Windows XP, Pentium III 933MHz, 384MB SDRAM, ATI Radeon 7000 VE 64MB, Soundblaster Audigy, 40GB Seagate HDD, Hitachi Lite-on CD-RW Drive, ZIP 250 and 3.5" Floppy.

User avatar
NITROYUASH
Verified
Serious PSXDEV User
Serious PSXDEV User
Posts: 124
Joined: Jan 07, 2018
I am a: Game Designer
PlayStation Model: SCPH-5502
Location: Russian Federation
Contact:

Post by NITROYUASH » December 1st, 2018, 5:45 am

Code: Select all

CompMatrixLV(&view.view, &omtx, &tmtx);
Yeah, it's working, but i miss something and it's seems, um, like this (including TMD models). Looks like i need to do something with OT?
► Show Spoiler

User avatar
LameGuy64
Verified
Psy-Q Enthusiast
Psy-Q Enthusiast
Posts: 388
Joined: Apr 10, 2013
I am a: Hobbyist Game Developer
Motto: Commercial or not, play it!
PlayStation Model: H2000/7000
Location: Philippines
Contact:

Post by LameGuy64 » December 1st, 2018, 7:07 pm

Ah, looks like things aren't z-sorting right. Nothing to do with matrices at least.

How do you sort TMDs into the ordering table? Also, I see my old lightbulb model :).
Please don't forget to include my name if you share my work around. Credit where it is due.

Dev. Console: SCPH-7000 with SCPH-7501 ROM, MM3, PAL color fix, Direct AV ports, DB-9 port for Serial I/O, and a Xplorer FX with Caetla 0.35.

DTL-H2000 PC: Dell Optiplex GX110, Windows 98SE & Windows XP, Pentium III 933MHz, 384MB SDRAM, ATI Radeon 7000 VE 64MB, Soundblaster Audigy, 40GB Seagate HDD, Hitachi Lite-on CD-RW Drive, ZIP 250 and 3.5" Floppy.

User avatar
NITROYUASH
Verified
Serious PSXDEV User
Serious PSXDEV User
Posts: 124
Joined: Jan 07, 2018
I am a: Game Designer
PlayStation Model: SCPH-5502
Location: Russian Federation
Contact:

Post by NITROYUASH » December 1st, 2018, 8:18 pm

How do you sort TMDs into the ordering table?
Using your TMD code and light model for testing (LinkModel + PutObject) :)

But this 2 boxes - not TMD.

Code: Select all

int Draw3DBoxF4(u_char semitrans, int start_fade_dist, int end_fade_dist, VECTOR scale, VECTOR pos, SVECTOR rot, CVECTOR *color, DIVPOLYGON4 div, POLY_F4 *obj) {
	MATRIX lmtx;	// Light Matrix
	MATRIX omtx;	// Object Matrix
	MATRIX tmtx;	// Temporary

	SVECTOR	**vp;

	int		i;
	int		nclip;
	long	p, OTz, Flag;
	
	u_char	p_count = 6;

	/* GTE has 1 matrix register, so it is better to push the
	 * matrix to preserve the current matrix register. */
	PushMatrix();

	// Rotate, translate and scale the matrix according to the specified coordinates
	RotMatrix(&rot, &omtx);
	TransMatrix(&omtx, &pos);
	ScaleMatrix(&omtx, &scale);

	// tmtx will be the matrix of the object relative to the camera
	CompMatrixLV(&view.view, &omtx, &tmtx);

	SetRotMatrix(&tmtx);
	SetTransMatrix(&tmtx);

	vp = v;
	NumPrims_local=0;
	for (i = 0; i < p_count; i++, obj++, vp += 4) {

		obj = (POLY_F4*)myPrimPtr;
			
		nclip = RotAverageNclip4(
			vp[0], vp[1], vp[2], vp[3], 
			(long *)&obj->x0, (long *)&obj->x1, 
			(long *)&obj->x3, (long *)&obj->x2,
			&p, &OTz, &Flag);

		if ((nclip > 0) && (OTz > start_fade_dist)) {
			SetPolyF4(obj);
			color[i].cd = obj->code;
			SetSemiTrans(obj, semitrans);
			OTc = OTz>>(14-OT_LENGTH);

			if (end_fade_dist == 0 || (OTc < end_fade_dist)) {

				// High LOD level (subdivided)
				if (OTc < (LOD_LV2+(LOD_LV2_DISTANCE))) {
					
					setRGB0(obj, color[i].r, color[i].g, color[i].b);
					AddPrim((u_long *)myOT[ActiveBuffer].org, obj);

					if (OTc < (LOD_LV1+(LOD_LV1_DISTANCE))) 
						div.ndiv = 2; 
					else div.ndiv = 1;
						
					//Our mesh will be divided by 4.
					DivideF4(
						&vp[0], &vp[1], &vp[3], &vp[2], 
						color[i],
						obj, (u_long *)myOT[ActiveBuffer].org,
						&div);
						
					// Increment primitive list pointer
					myPrimPtr += POLY_F4_size*((1<<(div.ndiv))<<(div.ndiv));
					NumPrims_local += ((1<<(div.ndiv))<<(div.ndiv));

				// Low LOD level (no subdivision)
				} else {
					setRGB0(obj, color[i].r, color[i].g, color[i].b);
					AddPrim((u_long *)myOT[ActiveBuffer].org, obj);
		
					myPrimPtr += POLY_F4_size;
					NumPrims_local += 1;
				}
			}
		}
	}
	PopMatrix();
	
	return (NumPrims_local);
}

Code: Select all

void PRIM_poly_tst() {
	
	RECT		ClearRect = { 0, 0, 384, 512 };

	POLY_F4		s[6];	/* cube surface*/
	CVECTOR		c[2][6];	/* cube colors*/

	DIVPOLYGON4 div;

	//MATRIX		omtx;

	VECTOR		cube_pos[2] = {0,0,0,0};
	VECTOR		cube_scl[2] = {0,0,0,0};
	SVECTOR		cube_rot[2] = {0,0,0,0};

	VECTOR		bulb_pos = {0,-230,0,0};
	SVECTOR		bulb_rot = {0,0,0,0};
	
	int cube_size = 196;
	int cube2_size = 196;
	int	total_prim_size = 0;
	int i,cbe;
	
	u_char	abs = false;

	ResetGraph(0);
	ClearImage2(&ClearRect, 0, 0, 0);
	ClearImage (&ClearRect, 0, 0, 0);

	/* set surface colors */
	for (cbe = 0; cbe < 2; cbe++) {
		for (i = 0; i < 6; i++) {
			c[cbe][i].r = SetRandomNUM(255);	/* R */
			c[cbe][i].g = SetRandomNUM(255);	/* G */
			c[cbe][i].b = SetRandomNUM(255);	/* B */
		}
	}
	
	init3d(0);
	
	SetPlayerCam(ONE*1, ONE*1, ONE*1, 0, 0);

	//OBJ POS
	for (cbe = 0; cbe < 2; cbe++) {
		cube_pos[0].vz = 270;
		cube_pos[1].vz = ((cube_pos[0].vz + 50) * 2);
		cube_scl[cbe].vx = cube_scl[cbe].vy = cube_scl[cbe].vz = 1024*3;
	}
	
	ObjectCount += LinkModel((u_long*)tmd_bulb, &Object[0]);		// Light bulb as a test-TMD
	
	g_iGS_R = g_iGS_G = g_iGS_B = 50;
	
	FntLoad(960, 256);
	FntOpen(0, 0, SCREENXRES, SCREENYRES, 0, 1024);

	// Set the screen resolution to the 'div' environment
	div.pih = SCREENXRES;
	div.piv = SCREENYRES;
	
	VSyncCallback(SetAnalogControl);
	
	while (1) {
		sp_cursor();
		GsSetProjection(FOV);
		SetPad(PORT1,PORT2);

		if ( (button[0] & B_CIRCLE) && (button[0] & T_L2) ) break;

		if ( (button[0] & S_SELECT) ) {
			SetPlayerCam(ONE*1, ONE*1, ONE*1, 0, 0);
		}

		if ( (button[0] & D_UP) ) {
			FOV++;
		}
		if ( (button[0] & D_DOWN) ) {
			FOV--;
		}

		for (cbe = 0; cbe < 2; cbe++) {
			if ( (button[0] & T_L1) ) {
				cube_rot[cbe].vy+=10;
			}
			if ( (button[0] & T_L2) ) {
				cube_rot[cbe].vy-=10;
			}
			if ( (button[0] & T_R1) ) {
				cube_pos[cbe].vz+=10;
			}
			if ( (button[0] & T_R2) ) {
				cube_pos[cbe].vz-=10;
			}
			if ( (button[0] & D_LEFT) ) {
				cube_scl[cbe].vx-=50;
				cube_scl[cbe].vy-=50;
				cube_scl[cbe].vz-=50;
			}
			if ( (button[0] & D_RIGHT) ) {
				cube_scl[cbe].vx+=50;
				cube_scl[cbe].vy+=50;
				cube_scl[cbe].vz+=50;
			}
		}

		if ( (button[0] & B_SQUARE) ) abs = true;
		if ( (button[0] & B_CIRCLE) ) abs = false;

		FntPrint("\n\n          %c 3D CUBE Test %c\n", cursor[pos], cursor[pos]);
		FntPrint("\n Camera: X %d Y %d Z %d\n PAN %d TIL %d", Camera.pos.vx,Camera.pos.vy,Camera.pos.vz,Camera.rot.vy,Camera.rot.vx);
		FntPrint("\n Cube: VX %d VY %d VZ %d", cube_pos[0].vx,cube_pos[0].vy,cube_pos[0].vz);
		//FntPrint("\n Prims: %d/%d",Draw3DBoxF4(cube_size, false, false, cube_pos, cube_rot, c, div, s),MAX_PRIMS);
		FntPrint("\n OTc: %d", OTc);
		
		PrepDisp();

		Player[0].x += Player[0].vx;
		Player[0].y += Player[0].vy;
		Player[0].z += Player[0].vz;
		Player[0].pan += Player[0].panv;
		Player[0].til += Player[0].tilv;

		Player[0].vx *=0.9f;
		Player[0].vy *=0.9f;
		Player[0].vz *=0.9f;
		Player[0].panv *=0.9f;
		Player[0].tilv *=0.9f;

		Camera.pos.vx = Player[0].x/ONE;
		Camera.pos.vy = Player[0].y/ONE;
		Camera.pos.vz = Player[0].z/ONE;
		Camera.rot.vy = -Player[0].pan;
		Camera.rot.vx = -Player[0].til;
		
		CalculateCamera();

		for (cbe = 0; cbe < 2; cbe++)
			Draw3DBoxF4(abs, 0, 150, cube_scl[cbe], cube_pos[cbe], cube_rot[cbe], c[cbe], div, s);

		PutObject(bulb_pos, bulb_rot, &Object[0]);
		
		Display();
	}
}

User avatar
LameGuy64
Verified
Psy-Q Enthusiast
Psy-Q Enthusiast
Posts: 388
Joined: Apr 10, 2013
I am a: Hobbyist Game Developer
Motto: Commercial or not, play it!
PlayStation Model: H2000/7000
Location: Philippines
Contact:

Post by LameGuy64 » December 3rd, 2018, 3:58 pm

Ah, you need to Z sort your primitives using the OTz result.

Code: Select all

DivideF4(
	&vp[0], &vp[1], &vp[3], &vp[2], 
	color[i],
	obj, (u_long *)myOT[ActiveBuffer].org+OTc,
	&div);

and...

AddPrim((u_long *)myOT[ActiveBuffer].org+OTc, obj);
That should fix your Z sorting issues. Also, you may want to do some if checks to make sure that OTc does not exceed the size of your OT array.
Please don't forget to include my name if you share my work around. Credit where it is due.

Dev. Console: SCPH-7000 with SCPH-7501 ROM, MM3, PAL color fix, Direct AV ports, DB-9 port for Serial I/O, and a Xplorer FX with Caetla 0.35.

DTL-H2000 PC: Dell Optiplex GX110, Windows 98SE & Windows XP, Pentium III 933MHz, 384MB SDRAM, ATI Radeon 7000 VE 64MB, Soundblaster Audigy, 40GB Seagate HDD, Hitachi Lite-on CD-RW Drive, ZIP 250 and 3.5" Floppy.

User avatar
NITROYUASH
Verified
Serious PSXDEV User
Serious PSXDEV User
Posts: 124
Joined: Jan 07, 2018
I am a: Game Designer
PlayStation Model: SCPH-5502
Location: Russian Federation
Contact:

Post by NITROYUASH » December 3rd, 2018, 6:23 pm

Yes, it's actually fix my problems with OTz (OTc)! Actually, i have seen this in Psy-Q examples, but didn't try to use for some reasons. Thank you so much!

Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests