I present you a new multiplatform 3D library: LMP3D

This forum is for discussion pertaining to homebrew software for the Dreamcast, such as homebrew games, emulators/interpreters, and other homebrew software/applications. Porting requests and developmental ideas are not to be made here; you can make those here. If you need any help burning discs for homebrew software, this is the place to ask as well.
Post Reply
Kannagi
DCEmu Cool Newbie
DCEmu Cool Newbie
Posts: 15
Joined: Mon Jul 28, 2014 3:24 pm

I present you a new multiplatform 3D library: LMP3D

Post by Kannagi » Thu Apr 26, 2018 4:08 pm

Hello,I will talk here mainly about the dreamcast version.
I use only very little lib pvr, the code is a new version or a modified version of the code of the lib pvr.

The lib can load a 3D model, read a .tar file (equivalent to a .zip without compression), pcx, png and bmp.

Currently it can display 18-19 k triangles per frame.
It can display 26k triangles per frame, if I do a double-buffer for vertex (The rendering on Dreamcast is done in 'parrallle' so it takes a double buffer to avoid data collisions), nevertheless it takes a lot of VRAM, and it's unlikely that you will display as many 3D model without code for the game.

So the best I think is to make a 30 fps version if you want to display the 26 k triangles by frames, (and that avoids me to have a double vertex buffer) and it also allows to have the animation by skeleton with 26k triangles ^^

For the speed of display, I think I managed to be close to the limit, currently according to my test I have 45 cycles for vertex calculations and 55 cycles for the index(so triangle) and 20 cycles for the transfer.

I tested on my console (with an SD card) :
Image

LXDREAM:
Image

An example code (but not finished, I have to hide even more its internal functioning):

Code: Select all

int __attribute__((optimize("-O0"), noinline)) main2()
{

	LMP3D_TAR tar;
	LMP3D_Model *model;

	LMP3D_Tar(&tar,NULL,"zack.bcm",LMP3D_TAR_OFFSET,DATA_ROM,size_DATA_ROM);
	model = LMP3D_Load_Model(NULL,tar.offset,DATA_ROM,tar.size);

	LMP3D_Tar(&tar,NULL,"font.png",LMP3D_TAR_OFFSET,DATA_ROM,size_DATA_ROM);

	LMP3D_Texture* texture,*texture2;

	texture = LMP3D_Load_Texture(NULL,tar.offset,DATA_ROM,tar.size);

	LMP3D_Texture_Convert(texture,LMP3D_FORMAT_BGRA1555);

	//Upload VRAM
	texture->address = 0x3D0000;
	LMP3D_Texture_Upload_VRAM(texture);
	LMP3D_Texture_Free_Pixel(texture);
	//----------

	LMP3D_Tar(&tar,NULL,"ffccdif_1.png",LMP3D_TAR_OFFSET,DATA_ROM,size_DATA_ROM);

	texture2 = LMP3D_Load_Texture(NULL,tar.offset,DATA_ROM,tar.size);

	LMP3D_Texture_Convert(texture2,LMP3D_FORMAT_BGRA1555);

	//convertTwiddle(texture);

	texture2->address = 0x400000;
	LMP3D_Texture_Upload_VRAM(texture2);
	LMP3D_Texture_Free_Pixel(texture2);

	model->position.z = 400;
	model->position.y = 100;
	model->rotate.x = PI/2;

	char strinfo[100],strfps[50];

	int tmpx,i,tmpy;
	int number = 1;
	int vblank = 0;

	LMP3D_Event event;

	while(1)
	{
		LMP3D_Event_Update(&event);

		if(event.key[Button_Up] == LMP3D_KEY_DOWNW) model->position.z += 8;
		if(event.key[Button_Down] == LMP3D_KEY_DOWNW) model->position.z -= 8;

		if(event.key[Button_R1] == LMP3D_KEY_DOWN) number++;
		if(event.key[Button_L1] == LMP3D_KEY_DOWN) number--;

		if(event.key[Button_A] == LMP3D_KEY_DOWN) typetest++;
		typetest &=3;

		model->rotate.y += 0.04f;


		DC_InitB(texture2->address);

		for(i = 0;i <  number;i++)
		{
			tmpx = (i&0x7)<<5;
			tmpy = (i&0xF8)<<4;

			model->position.x = tmpx;
			model->position.y = tmpy+100;

			Draw_Model(model);
		}

		DC_Finish();

		DC_Init_Sprite(texture2->address);

		DC_DrawSprite(16,64);

		DC_Init_Sprite(texture->address);

		Draw_Text(16,16,strinfo);

		DC_Finish();

		sprintf(strinfo,"Vblank :%d\nnumber %d\nTri %d ,VRAM : %x ,type %d\n",vblank,number,model->nf*number,pvr_offset,typetest);



		vblank = LMP3D_VBlank();

		LMP3D_FlipBuffer(NULL);



		LMP3D_VBlank();
	}

	return 0;
}

Normally this should look like this(PC/PS2):

Code: Select all

void game(LMP3D_Buffer *buffer)
{
	LMP3D_TAR tar;

	LMP3D_Event event;
	LMP3D_Camera camera;
	camera = LMP3D_Camera_Init();

	LMP3D_Event_Init(&event);
	LMP3D_Model *model;

	LMP3D_Tar(&tar,"DATA","zack.bcm",LMP3D_TAR_OFFSET,NULL,0);
	
	model = LMP3D_Load_Model("DATA",tar.offset,NULL,0);
	
	LMP3D_Tar(&tar,"DATA","font.png",LMP3D_TAR_OFFSET,NULL,0);
	LMP3D_Texture *texture = LMP3D_Load_Texture("DATA",tar.offset,NULL,tar.size);
	LMP3D_Texture_Upload(texture);
	LMP3D_Texture_Free_Pixel(texture);
	
	char string[100],strfps[50];
	int vblank = 0;
	
	int t_end,t_begin,fps = 0,total=0;
	
	Vector3 p;
	
	p.x = 0;
	p.y = 0;
	p.z = 0;
	
	int i,number = 1,tmpx,tmpy;
	
	while(event.exit == 0)
	{
			model->rotate.y += 0.01;
		LMP3D_Event_Update(&event);
	
		//camera
		LMP3D_Camera_Perspective(camera);
	
		LMP3D_Clear();
	
		if(event.key[Button_Up] == LMP3D_KEY_DOWNW) p.z += 8;
		if(event.key[Button_Down] == LMP3D_KEY_DOWNW) p.z -= 8;
	
	
		if(event.key[Button_R1] == LMP3D_KEY_DOWN) number++;
		if(event.key[Button_L1] == LMP3D_KEY_DOWN) number--;
	
	
		if(event.key[Button_R2] == LMP3D_KEY_DOWN) number +=10;
		if(event.key[Button_L2] == LMP3D_KEY_DOWN) number -=10;
	
		if(event.key[Button_Start] == LMP3D_KEY_DOWN) model->test = 0;
	
		LMP3D_Texture_Setup(model->texture[0]);
	
		for(i = 0;i <  number;i++)
		{
	
			tmpx = (i%20)*30;
			//tmpy = (i/30)*140;
			tmpy = 0;
			model->position.x = tmpx-0;
			model->position.y = 100-tmpy;
			model->position.z = 400+p.z;
	
			model->scale.x = 1;
	
			LMP3D_Model_Draw(model);
		}
	
	
		LMP3D_Camera_Ortho2D();
	
		LMP3D_Texture_Setup(texture);
	
		sprintf(string,"Time %s\nVblank :%d\nnumber %d\nTri %d\nperf %d\n",strfps,vblank,number,model->nf*number,model->test);
		bitmap_font2(string,8,8);
	
	
	
	
	
	
		t_end = clock();
		if(fps >= 60)
		{
			total += t_end-t_begin;
			sprintf(strfps,"%d/%d",total,CLOCKS_PER_SEC/60);
			total = 0;
			fps = 0;
		}
		fps++;
	
	
		LMP3D_FlipBuffer(buffer);
		vblank = LMP3D_VBlank();
		t_begin = clock();
	
	
	}
	

}

So you have 4.3MB for VRAM (Texture) , I think I will do 4 functions for 2D (optimized so, the Dreamcast can display Quad quickly):
-Sprite
-Sprite_Array
-Text
-TileMap

The code works on Windows, Linux, PS1 / PS2.

For each platform I manage the appropriate conversions floating / fixed number, a small idea of what format is optimized for each platform:
PC: floating point number, index
PS1: fixed number, no index
PS2: fixed number, index + submesh
DC: floating point number, index

I create a converter (internal) that converts the images into the appropriate format, here are the recommended formats:
PS1, PS2: PCX
DC: PNG or VQ compressed (not done yet)
PC: PNG

(if someone wants to create a specific dreamcast .vq format I'll thank him a lot :D ).

For 3D format, I use my own format, a converter exists here : https://github.com/Kannagi/BCMConvert
The source code : https://github.com/Kannagi/LMP3D

And here's a video of a demo of my lib:
https://www.youtube.com/watch?v=AEwg1k-KOf4

Thanks for reading me ! :)
User avatar
lerabot
Insane DCEmu
Insane DCEmu
Posts: 109
Joined: Sun Nov 01, 2015 8:25 pm

Re: I present you a new multiplatform 3D library: LMP3D

Post by lerabot » Fri Apr 27, 2018 7:41 am

Good job! Starring this on github!
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5333
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Contact:

Re: I present you a new multiplatform 3D library: LMP3D

Post by BlueCrab » Fri Apr 27, 2018 3:44 pm

Kannagi wrote:
Thu Apr 26, 2018 4:08 pm
(if someone wants to create a specific dreamcast .vq format I'll thank him a lot :D ).
KOS includes a tool that can be used to VQ encode images from PNG/JPG files. That would probably be a good place to start from if you're looking for code to do so.
Kannagi
DCEmu Cool Newbie
DCEmu Cool Newbie
Posts: 15
Joined: Mon Jul 28, 2014 3:24 pm

Re: I present you a new multiplatform 3D library: LMP3D

Post by Kannagi » Sat Apr 28, 2018 1:09 am

Thank you, so I tested the vqenc program, and I have the compressed VQ that works!
This makes 64 texture of 512x512 possible ^^

I will try to update to make a usable version of the lib ;)

@lerabot Thank you , This will allow my project to have more visibility and be seen as serious if it has a significant number of stars :)
park
DCEmu Junior
DCEmu Junior
Posts: 41
Joined: Tue Jun 24, 2008 10:46 am

Re: I present you a new multiplatform 3D library: LMP3D

Post by park » Sat Apr 28, 2018 11:41 am

This is pretty cool. You should consider posting it on Dreamcast talk. Maybe sending info about it to Dreamcast junkyard to get the word out.
Kannagi
DCEmu Cool Newbie
DCEmu Cool Newbie
Posts: 15
Joined: Mon Jul 28, 2014 3:24 pm

Re: I present you a new multiplatform 3D library: LMP3D

Post by Kannagi » Sat Apr 28, 2018 3:20 pm

Thank you, I'm waiting for my lib is usable for really advertising !
But I went on the Discord, to see what other Dreamcast developers did and talked about my project ;)
b0b
DCEmu Fast Newbie
DCEmu Fast Newbie
Posts: 17
Joined: Thu Mar 15, 2007 12:04 pm

Re: I present you a new multiplatform 3D library: LMP3D

Post by b0b » Sun Apr 29, 2018 6:13 am

this is pretty cool!
the z-near clipping and lighting is not implemented yet? or did i missed it? i only took a quick look so far, i really need to adjust to your coding style first. wouldn't it be better to write the assembly stuff in extra *.s or *.S files instead of inline asm? :D

are you interested in some kind of collaboration?
Kannagi
DCEmu Cool Newbie
DCEmu Cool Newbie
Posts: 15
Joined: Mon Jul 28, 2014 3:24 pm

Re: I present you a new multiplatform 3D library: LMP3D

Post by Kannagi » Sun Apr 29, 2018 8:53 am

Thank you, yes that's right I did not put anything "z-near clipping " and "lighting".
I will also put "Viewing frustum culling" and "Contribution culling" (it will be possible to enable/disable).

Yes, I prefer inline asm but it is only a preference it is true ;)

I'm open to any contribution, and I do not always work on the Dreamcast version (I sometimes work on PS1 / PS2) :)
Kannagi
DCEmu Cool Newbie
DCEmu Cool Newbie
Posts: 15
Joined: Mon Jul 28, 2014 3:24 pm

Re: I present you a new multiplatform 3D library: LMP3D

Post by Kannagi » Sat May 12, 2018 12:37 pm

Well, I have news since :)

I finally add my 2D functions, do 4 times the same code in a slightly different way is a bit painful.
This results in:
Image

It took me a lot of time because I wanted to manage the 8bpp / 4bpp for each platform.
The Dreamcast is quite limited on this point, it only manages 1024 levels of color palette (say that the compression is not really at this level).
On PC 8bpp converted to RGBA (but if you use effects on the palette it will not work on PC ah ah xD).

I add the Backface culling on PS1, PC and Dreamcast.
On Dreamcast, there is no cross product in hardware, I made 2 inner products + subtraction :p

I hope to quickly finish the management of the Camera.
The 'Viewing frustum culling' will be easy to do, I already have my 3D box.

I have not updated for Github yet,I think I will compile the library for each platform, I will update the source code later.
So I think I'm close to a stable version, when it will be the case will remain that the Skeletal animation ^^

I made a video :
https://youtu.be/yobIrC6U320

On 30 fps, my old test should not be good (I had to put an vertexend list),I can add more triangle, and so I think 40,000 triangles per frame is widely possible :)
corvusdeux
DCEmu Newbie
DCEmu Newbie
Posts: 1
Joined: Sat Dec 08, 2018 5:03 pm

Re: I present you a new multiplatform 3D library: LMP3D

Post by corvusdeux » Sun Dec 09, 2018 6:30 am

Hello @Kannagi,

First of all congratulate you for your project and great work. It is immense and at the same time super interesting and useful.

I did not want to bother you very much, I just have some questions to ask you first about this:
"On Dreamcast, there is no cross product in hardware, I made 2 inner products + subtraction: p"

1) It has left me very crazy XD. Also with a lot of curiosity and I have researched a little. And yes, it's incredible but it's true! Already the PS1 in GTE has a function / macro for "Outter_product". That costs 6 cycles. It is true that the lighting operations "Inner_product" costs much more. But my question is: Are these types of operations really useful in 3D graphics? When the main utility is to obtain the vector orthogonal to two vectors, for example to calculate the normal vector of a face. But these vectors already come in the 3D information of the geometries do not?

2) If SH4 has cost 4/7 cycles to do "dot product". Do this alternative operation that can cost twice or triple the GTE of PS1?

On the other hand, I would like to suggest adding Sega Saturn to your library. I see that you like 2D games, and good SS was "the 2D machine of the 32bit". Also now the homebrew is very alive and the emulation has improved a lot. I see you drive with DC, and SH asm, so the SS will be familiar. It is true that their VDPs are very unique. But a challenge for a mind eager for challenges, will enjoy it! :)

And finally, seeing that you drive in SH asm. Or in asm, there is a companion of the SS homebrew world that is creating a 3D engine taking the limits never seen to the SS. He knows how to program in C and has reached a point that he needs to implement parts in asm. Would you like to take a look at your work and help you?
Sonic Z-Treme / FPS BSP 3D engine:
http://forum.jo-engine.org/index.php?to ... 94#msg2094
Advance Transparency in SS:
http://forum.jo-engine.org/index.php?to ... 05#msg2105
https://segaxtreme.net/threads/reading- ... ost-175833

Thank you in advance and congratulations again for your project. I will be aware of your project! :)

Regards,

David Gámiz Jiménez
Post Reply