DirectJ - Sorry Capn'

Started by gaarazero, July 23, 2007, 09:12:39

Previous topic - Next topic

gaarazero

I was reading over some of the posts on the DirectX binding for Java and I just couldn't help myself.  I know CaptainJester is working on one and I still offer my help to his project.  This comes from me having way too much time on my hands.  I really need a job  :-\.

Here's my attempt at a Java binding for DirectX, I call it DirectJ.  So far, it's been quite smooth.  There's a lot of foundation already implemented for DirectX compared to OpenGL (e.g. D3DXCreateTextureFromFile, D3DXMatrix, D3DXFont, etc ).  This is done all in D3DX; think of it like GLU or GLUT on steroids.  This makes using DirectX really nice.  Since DirectX uses the COM interface, it makes it more like Java than OpenGL's C functional programming.  But, the way I am accessing the COM objects has some potential for memory leaks due to Java's garbage collector.  So far I have not run into those problems yet.  Here's a quick snapshot of what I'm working with so far:



I've got vertex buffers and user provided (UP) draw methods working.  Although the vertex buffers are acting up, but they still work.  Texture loading because of one of the nice methods listed above, as well as fonts for the same reason.

You can browse the source code here.  I will try and have a jar and dll ready at some point for people to try it out.  There has been no real performance hits, other than using D3DXFont, which is notoriously slow ( I was getting about 3000+ fps when rendering one line of text ).  I've also tried to optimize what I have written so far to gain any boost in speed.  I've tried really hard to keep all the naming conventions so someone coming from C/C++ DirectX will have little to no trouble finding methods, enums, and structs.

I am currently working on adding lighting, some more D3DX methods, and a real D3DCanvas.  Since D3DX is a great complement to DirectX, I feel it should be added with any bind that comes out, that is why I am putting it in, although it it is quite large.  Here is what the code looks like to create this scene.  For those who have never used DirectX, this will look kinda funky.  But, it works. 

import org.directj.d3d.*;
import org.directj.d3d.enums.*;
import org.directj.d3d.structs.*;
import org.directj.d3dx.*
import org.directj.d3dx.enums.*;
import org.directj.d3dx.structs.*;

...

Direct3D9 d3d = D3D.Direct3DCreate9( D3D.D3D_SDK_VERSION );
D3DCanvas can = new D3DCanvas();
DisplayMode dm = d3d.GetAdapterDisplayMode( D3D.D3DADAPTER_DEFAULT );

PresentParameters m_d3dpp = new PresentParameters();
m_d3dpp.BackBufferFormat = dm.Format;
m_d3dpp.BackBufferCount = 1;
m_d3dpp.MultiSampleType = MultiSampleType.NONE;
m_d3dpp.hDeviceWindow = can.getHWnd();
m_d3dpp.Windowed = true;
m_d3dpp.BackBufferWidth = 640;
m_d3dpp.BackBufferHeight = 480;
m_d3dpp.EnableAutoDepthStencil = true;
m_d3dpp.AutoDepthStencilFormat = Format.D16;
m_d3dpp.Flags = 0; 
m_d3dpp.FullScreen_RefreshRateInHz = 0;
m_d3dpp.SwapEffect = SwapEffect.FLIP;
m_d3dpp.PresentationInterval = D3D.D3DPRESENT_INTERVAL_IMMEDIATE;

Direct3DDevice9 dev = null;
try {
	dev = d3d.CreateDevice( D3D.D3DADAPTER_DEFAULT, 
							DevType.HAL, 
							can, 
							D3D.D3DCREATE_HARDWARE_VERTEXPROCESSING, 
							m_d3dpp );
} catch( Exception e ) {
	e.printStackTrace();
}
Color color = new Color(), fcolor = new Color(), f2color = new Color();
color.fromColor(88, 99, 110, 255);
fcolor.fromColor(255, 255, 255, 255);
f2color.fromColor( 0, 0, 0, 255 );

Viewport vp = new Viewport();
vp.X = vp.Y = 0;
vp.Width = 640;
vp.Height = 480;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
dev.SetViewport( vp );

dev.SetRenderState( RenderStateType.ZENABLE, true );
dev.SetRenderState( RenderStateType.LIGHTING, false );
dev.SetRenderState( RenderStateType.ZWRITEENABLE, true );
dev.SetRenderState( RenderStateType.POINTSIZE, 10.5f );
dev.SetRenderState( RenderStateType.CULLMODE, Cull.NONE );
dev.SetRenderState( RenderStateType.ALPHABLENDENABLE, true );
dev.SetRenderState( RenderStateType.SRCBLEND, Blend.SRCALPHA );
dev.SetRenderState( RenderStateType.DESTBLEND, Blend.INVSRCALPHA );
dev.SetRenderState( RenderStateType.AMBIENT, new Color( 0, 0, 1.0f, 1 ).asColor() );

Direct3DVertexBuffer9 vb = dev.CreateVertexBuffer( 64, D3D.D3DUSAGE_WRITEONLY, D3D.D3DFVF_XYZ | D3D.D3DFVF_DIFFUSE, Pool.MANAGED );

ByteBuffer vert, bb = BufferUtil.createByteBuffer( 64 );

FloatBuffer fb = bb.asFloatBuffer();
fb.put( 10.0f ).put( 10.0f ).put( 0.0f ).put( 0 );
fb.put( 10.0f ).put( 200.0f ).put( 0.0f ).put( 0 );
fb.put( 200.0f ).put( 10.0f ).put( 0.0f ).put( 0 );
fb.put( 200.0f ).put( 200.0f ).put( 0.0f ).put( 0 );
fb.clear();
IntBuffer ib = bb.asIntBuffer();
ib.put( 3, new Color( 255, 0, 0, 255 ).asColor() );
ib.put( 7, new Color( 0, 255, 0, 255 ).asColor() );
ib.put( 11, new Color( 0, 0, 255, 255 ).asColor() );
ib.put( 15, new Color( 0, 0, 0, 255 ).asColor() );

vert = vb.Lock( 0, 0, D3D.D3DLOCK_DISCARD );
vert.put( bb );
vert.clear();
ib = vert.asIntBuffer();
ib.put( 3, new Color( 255, 0, 0, 255 ).asColor() );
ib.put( 7, new Color( 0, 255, 0, 255 ).asColor() );
ib.put( 11, new Color( 0, 0, 255, 255 ).asColor() );
ib.put( 15, new Color( 0, 0, 0, 255 ).asColor() );
vb.Unlock();

ByteBuffer vbtex = BufferUtil.createByteBuffer( 80 );
vbtex.putFloat( 10.0f ).putFloat( 10.0f ).putFloat( 0.0f ).putFloat( 0 ).putFloat( 1 );
vbtex.putFloat( 10.0f ).putFloat( 200.0f ).putFloat( 0.0f ).putFloat( 0 ).putFloat( 0 );
vbtex.putFloat( 200.0f ).putFloat( 10.0f ).putFloat( 0.0f ).putFloat( 1 ).putFloat( 1 );
vbtex.putFloat( 200.0f ).putFloat( 200.0f ).putFloat( 0.0f ).putFloat( 1 ).putFloat( 0 );
vbtex.clear();

Direct3DTexture9 tex = D3DX.D3DXCreateTextureFromFile( dev, "E:/My Documents/My Pictures/546.jpg" );

XFont fnt = D3DX.D3DXCreateFont( dev, 16, 0, XFont.FW_EXTRABOLD, 0, false, XFont.DEFAULT_CHARSET, XFont.OUT_TT_ONLY_PRECIS, XFont.ANTIALIASED_QUALITY, XFont.DEFAULT_PITCH | XFont.FF_DONTCARE, "Default" );
Rect rct = new Rect( 30, 30, 200, 200 );
Rect rct2 = new Rect( 30, 300, 200, 200 );
Rect rct3 = new Rect( 420, 300, 200, 200 );
Rect rct4 = new Rect( 210, 300, 200, 200 );

XMatrix mat = new XMatrix(), mat2 = new XMatrix(), mat3 = new XMatrix(), mat4 = new XMatrix();
D3DX.D3DXMatrixIdentity( mat );
D3DX.D3DXMatrixIdentity( mat2 );
D3DX.D3DXMatrixIdentity( mat3 );
D3DX.D3DXMatrixIdentity( mat4 );
dev.SetTransform( TransformStateType.WORLD, mat );
dev.SetTransform( TransformStateType.VIEW, mat );

D3DX.D3DXMatrixOrthoOffCenterLH( mat, 0, 640, 0, 480, 0, 1 );
dev.SetTransform( TransformStateType.PROJECTION, mat );

D3DX.D3DXMatrixTranslation( mat2, 200, 000, 0 );
D3DX.D3DXMatrixTranslation( mat3, 400, 000, 0 );
D3DX.D3DXMatrixTranslation( mat4, 0, 200, 0 );
D3DX.D3DXMatrixIdentity( mat );

long start = System.currentTimeMillis();
int fps = 0, txtfps = 0;
while( dev.TestCooperativeLevel() ) {
	dev.BeginScene();
	dev.Clear( 0, null, D3D.D3DCLEAR_TARGET | D3D.D3DCLEAR_ZBUFFER, color, 1.0f, 0 );
	dev.SetTransform( TransformStateType.WORLD, mat );

	dev.SetFVF( D3D.D3DFVF_XYZ | D3D.D3DFVF_DIFFUSE );
	dev.DrawPrimitiveUP( PrimitiveType.TRIANGLESTRIP, 2, bb, 16 );
	fnt.DrawText( null, "DrawPrimitveUP", -1, rct2, XFont.DT_LEFT | XFont.DT_NOCLIP, fcolor );
	
	dev.SetTransform( TransformStateType.WORLD, mat3 );
	dev.SetFVF( D3D.D3DFVF_XYZ | D3D.D3DFVF_TEX1 );
	dev.SetTexture( 0, tex );
	dev.DrawPrimitiveUP( PrimitiveType.TRIANGLESTRIP, 2, vbtex, 20 );
	fnt.DrawText( null, "D3DXCreateTextureFromFile", -1, rct3, XFont.DT_LEFT | XFont.DT_NOCLIP, f2color );
	
	dev.SetTexture( 0, null );
	dev.SetTransform( TransformStateType.WORLD, mat2 );
	dev.SetFVF( D3D.D3DFVF_XYZ | D3D.D3DFVF_DIFFUSE );
	dev.SetStreamSource( 0, vb, 0, 16 );
	dev.DrawPrimitive( PrimitiveType.TRIANGLESTRIP, 0, 2 );
	fnt.DrawText( null, "DrawPrimitive\nDirect3DVertexBuffer9", -1, rct4, XFont.DT_LEFT | XFont.DT_NOCLIP, fcolor );
	
	fnt.DrawText( null, "D3DXFont\nFPS: " + txtfps, -1, rct, XFont.DT_LEFT | XFont.DT_WORDBREAK |  Font.DT_NOCLIP, fcolor );
	
	dev.EndScene();
	dev.Present( null, null, 0, 0 );

	can.update( null );
	fps++;
	if( System.currentTimeMillis() - start >= 1000 ) {
		txtfps = fps;
		fps = 0;
		start = System.currentTimeMillis();
	}
}


-gz
JNewton 0.8 - Newton Dynamics wrapper for Java!
org.lwjgl.d3d - Currently Working On

CaptainJester

No problem.  What's slowing me down is learning the system for LWJGL.  I just solved one problem, but am now working on another.  And since I am not a C expert, I have to read the code slowly to see what it is doing.  Creating the interfaces is going very smoothly, but now I have to get the display working to get a handle to a window(HWND) to create the IDirect3DDevice9.
The problems of this world cannot possibly be solved by skeptics or cynics whose horizons are limited by the obvious realities.  We need men and women who can dream of things that never were. - John Fitzgerald Kennedy(35th US President)
8)

Matzon

I am not sure about how similar these two projects are - but it would probably be beneficial to work together to create 1 dx binding.
Whether it should still be under the lwjgl umbrella I will leave undecided, tho I think it would make sense. However I dont want to force any direction at all!!.

CaptainJester

No forcing a direction needed.  My intent from the start was to have it under LWJGL.  I think it would be the most benificial.  I think gaarazero is just chomping at the bit to start working.  Once I solve the integration issues, things will move forward more quickly.  At that point he is more than welcome to contribute.  It sounds like he knows DirectX well, so that will be a bonus too.
The problems of this world cannot possibly be solved by skeptics or cynics whose horizons are limited by the obvious realities.  We need men and women who can dream of things that never were. - John Fitzgerald Kennedy(35th US President)
8)

gaarazero

I think having the binding under LWJGL would be very beneficial as well.  I don't want to step on anyones toes.  Having the option of using GL or DX would be a great draw to use LW to develop Java games.  I also agree that a single binding would be needed (org.lwjgl.directx maybe?).  Good luck!

-gz
JNewton 0.8 - Newton Dynamics wrapper for Java!
org.lwjgl.d3d - Currently Working On

gaarazero

Just updated and got an actual Canvas working.  It can be placed in a JFrame with AWT/Swing components, and should be able to work with SWT.  This may help on your problems CaptainJester.  Maybe not.  Source code.
JNewton 0.8 - Newton Dynamics wrapper for Java!
org.lwjgl.d3d - Currently Working On

CaptainJester

Thanks.  I'll take a look. 

However, my problems are more related to modifying the existing code to not be dependent on OpenGL.
The problems of this world cannot possibly be solved by skeptics or cynics whose horizons are limited by the obvious realities.  We need men and women who can dream of things that never were. - John Fitzgerald Kennedy(35th US President)
8)

gus0650

From our perspective, using LWJGL is a great idea because we use jMonkeyEngine, which is LWJGL based.

Many games & 3d engines use LWJGL and they would all benefit instantly from DX support in LWJGL.

llama

Quote from: gus0650 on September 07, 2007, 09:19:59
From our perspective, using LWJGL is a great idea because we use jMonkeyEngine, which is LWJGL based.

Many games & 3d engines use LWJGL and they would all benefit instantly from DX support in LWJGL.

Instantly meaning: 'reimplement everything the DirectX way', but yeah.. if you happen to use jMonkeyEngine, and someone will write a DirectX renderer for it (I guess some of the companies using jME will be very intrested in that, let's hope they'd do that out in the open), then you'd benifit without much effort :)

princec

That being the whole point :D Oh, and to get a few more bedroom C++ coders to try out Java.

Cas :)

elias4444

Sounds like Cas is trying to convert the gaming world over to Java. He must be a fanatic.  ;)
=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

princec

There is a method to my madness ;) If I can just get enough mindshare behind it we might get to see a console implementation...

Cas :)