program effect1_3d;


// Simple 3d effect, taken from the default c64 tutorials in advanced/3d

@define lib3d_yscale2 1 // Pixels wider than height

@define signedmath_zeropage $60 // $20-25
@define lib3d_zeropage $90 // $90-A0
@define matrix_zeropage $c0 // $C0-cf
@define muldivtables $8000
@define objPos $8800
@define max3dobjects 1

@ifndef IS_DEMO
@setvalue "output_type" "prg"
@endif
@define linemethod "Gfx::Line"
@use "gfx/lib3d"
@use "demounit"

var
	bb,x1,x2,y1,y2,l,i,j,k,f,x3,y3,time,time2,t: byte;
	zp,keep : pointer;
	ip:pointer of integer;
	// torus generated with "torus.fjo"	
	obj1 : incbin("data/torus1.bin");
	
	const sh: byte = 8;


	matX, matY, matZ, matT : Matrix::mat4;

	x,y,char : byte=0;
	len:byte=1;
	ix,m:integer;


@startblock $4000 "Code"
	
procedure SwitchDrawBank();
begin
	if Gfx::currbank=0 then begin
		Gfx::currbank := $40;
		SetBank(VIC_BANK0);
		clearbitmap(#Gfx::bank2, 29); // Clear a certain window only
	end
	
	else
	begin
		Gfx::currbank:=0;
		SetBank(VIC_BANK1);
		clearbitmap(#Gfx::bank1, 29);
	end;
	
end;

interrupt Raster();
begin
	startirq(0);
	@ifdef IS_DEMO
	// Update music and timers, only if build is currently in demo
	call(^@callPos);
	@endif

	closeirq();
end;


procedure Render();
begin
	SwitchDrawBank();
	
	Lib3d::FlipPointPointers(0);
	
	Matrix::RotateX(#matX, time*4);
	Matrix::RotateZ(#matY, time*3);
	Matrix::RotateZ(#matZ, time*2);
	
	Matrix::MatMul3(#matX, #matY, #matT);
	Matrix::MatMul3(#matT, #matZ, Lib3d::objects[0].rotmat);

	Lib3d::RotateVertices(0);	

	Lib3d::ProjectSimple(0,80,90,127+(Tables::sine128[time*16]+127)/4, 70);
	
	Lib3d::RenderWireframe(0);

	time+=1;
end;

procedure Run();
begin

	StartRasterChain(Raster(),0,0);
	Gfx::currbank :=0; // Current bitmap bank (added to high bit of putpixel)
	Gfx::InitBitmapGraphics(1, #Gfx::bank1);
	vic_data_loc:=$18;
	setmulticolormode();
	setbitmapmode();
	
	SCREEN_BG_COL:=BLUE;
	SCREEN_FG_COL:=RED;
	
	clearscreen(YELLOW,#screen_col_loc);
	clearscreen(BLUE,#screen_char_loc2);

	// Setup 3D
	Lib3d::InitializeData(@objPos);	
	Lib3d::LoadObject(0, #obj1);

	Matrix::Identity(#matX);
	Matrix::Identity(#matY);
	Matrix::Identity(#matZ);
	Matrix::Identity(Lib3d::objects[0].rotmat);
	
	while (true) do 
	begin
		Render();
		// EndClearInsideWhileLoop will simply jump to the loader address at $810 if "advance" is set to 1
		DemoUnit::EndClearInsideWhileLoop();
	end;

end;


@endblock

// This effect starts at $1000
begin
	@ifndef IS_DEMO
	disableciainterrupts(); // prevent CIA
	preventirq();
	@endif
	setmemoryconfig(1,0,0);

	Run();
end.
