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
DCEmu Freak
DCEmu Freak
Posts: 94
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: 5317
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 :)
Post Reply