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