Jump to content
  • Advertisement
Sign in to follow this  
nagajim

Help Please - Direct3D - Newbie

This topic is 4862 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I am writing a RailRoad game (VB.NET) in which the user has a "bird's eye view" over a 2D landscape. I use large satellite images (upto 10000x10000 pixels) onto which I wish to draw the tracks (simple lines and rounded rectangles) and some text (static elements). Trains are also represented by simple rounded rectangles (can be static or moving). I originally was using offscreen DC's and GDIplus to draw on them and then using BilBlt to assemble a composite "visible" image before BitBlt'ing this to my picturebox. However, I ran into memory problems and decided to recode using Direct3D. I followed the advice from another thread "Texture from Surface 2/22/2003" (basically I create a texture to accomodate the size of my picturebox, load my large image onto a surface, Get a surface from my Texture, Load this surface with a portion of my image surface, and then render the Texture.). This works well and I can scroll around my large image. However, where do I go from here? Do I draw all my static elements (at image load) onto my image surface and then display only a portion as above.(if so how? I tried using GDIplus but can't get it to work - and I can't find any Direct3D structures to draw to a surface.). Or do I use "Device.DrawUserPrimatives(...)" and go directly to the Device? (this seems wasteful as I would need to recalculate what is visible each frame). Also how do I best handle the moving elements? Their position is recalculated each time so perhaps using "Device.DrawUserPrimatives(...)" is fine? Many thanks in advance, NagaJim

Share this post


Link to post
Share on other sites
Advertisement
Hi there nagajim,
How are you doing?
Well what I think you will need is a good structure/framework. Right now I think the problem is that you don't really know how things are placed together (Correct my if i'm wrong).

Your camera seems to be the only really tricky part here. The rest are just static textures that you will render to a scene, and move the accordingly.


You will need the following methods and COM interfaces

[Interfaces]
IDirect3D9
IDirect3DDevice9
IDirect3DTexture9

[Methods]
D3DXCreateTextureFromFile();
IDirect3DDevice9::SetFVF();
IDirect3DDevice9::SetTexture();
IDirect3DDevice9::DrawPrimitives();
IDirect3DDevice9::SetTransform();

[Structures]
D3DXMATRIX

What you will do is create Direct3D (IDirect3D9) and then the device (IDirect3DDevice9).
The device is what you will use to draw primitives (IDirect3DDevice9::DrawPrimitives()).
1) You translate the entity (train or whatever) using the matrix
2) You then load the texture using D3DXCreateTextureFromFile();
3) You set the matrix using IDirect3DDevice9::SetTransform();
4) Set the texture
5) Set the FVF (Flexible vertex format)
6) Draw the primitives

That is basic and I might have missed a few details but in a sense it will place you in the right direction. If you need any other help do not hesitate to ask.

Share this post


Link to post
Share on other sites
What are your requirements and restrictions? Do you want the user to place the railroad tracks on the image? Do you want a train to follow the railroad?

One thing you could do is have a separate 10000x10000 image with complete transparency and just add the railroads to it. Now you have two images, the ground texture, and the overlay. This of course is highly inefficient, but that's why your requirements and restrictions will be needed. :) Anyway, you could then load both surfaces, then render two quads with the same texture coordinates. Basically you'd just set the texture to Tex1 for the first quad and render it, then set to Tex2 and render it again.

Optimally, you would want to store the tracks in a data file, and load them and place them at run-time. This could be done by locking the surface that contains the ground texture, pasting your railroad textures over the image based on the data file, then unlocking the texture. A one time thing.

You could also draw the tracks as you scroll, keeping a few tracks rendered just outside the view of the camera to keep them from "popping" into view. In this case you would need to coordinatize everything and keep track of where you are in the world. This may be overkill if the first or second solution gets you the gold though.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Hi Pieter,
Thanks for replying. OK I'm now completely lost.

Currently this is what I have coded:

Private Sub InitializeGraphics()
.
.
.
'Create device
GraphicsDevice = New Direct3D.Device(0, Direct3D.devicetype.hardware, Me.pictureBox1,CreateFlags.SoftwareVertexProcessing, presentParams)

'Create Texture
mapimage=textureloader.FromFile(graphicsdevice,application.StartupPath & "\texture.jpg")
.
.
End Sub

Private Sub MapDrawLoad(sender As System.Object,..)
.
.
.
'Create a Surface to hold image
backbuffer=graphicsdevice.CreateOffscreenPlainSurface(intMaxX,intMaxY,format.A8B8G8R8,pool.Scratch)
'Load Surface from File
surfaceloader.FromFile(backbuffer,rectangle.FromLTRB(0,0,intmaxX,intmaxY), strfile,rectangle.FromLTRB(0,0,intmaxX,intmaxY), filter.None,color.White.ToArgb)
.
.
.
End Sub

Private Sub Render()
.
.
'Get Surface for our Trexture
imgsurface=mapimage.getsurfacelevel(0)
'Load Surface of Texture with part of our image surface
surfaceloader.FromSurface(imgsurface,backbuffer,rectangle.FromLTRB(lefthook,tophook,lefthook+picturebox1.width,tophook+picturebox1.Height),filter.None,0)
.
.
graphicsdevice.BeginScene()
graphicsdevice.VertexFormat = CustomVertex.TransformedColored.Format

spriteimage.Begin(spriteflags.AlphaBlend)
spriteimage.Draw2d(mapimage,rectangle.empty,rectangle.empty,new point(0,0),color.White)
spriteimage.End()

graphicsdevice.EndScene()
graphicsdevice.Present()

End Sub

This allows me to display a part of my 2D image (10000x10000) in a picturebox (900x600) and to scroll around the image (lefthook, tophook).

Perhaps rather simplistically what I was hoping I could do was to draw (at map load time) my static items (lines and rounded boxes) onto my surface "backbuffer", such that the "Render" routine would "Present" the composite image (which is essentially a background, which the user can scroll) to the device.

The moving elements I thought I could draw using something like
graphicsdevice.DrawUserPrimitives(PrimitiveType.LineList, Inum, Line_data)
in my "Render" routine.

You are perfectly correct when you say I don't really know how things are placed together. The IDirect3D... Interface & Methods and the D3DXMatrix Structure which you reference all say that they are not intended to be used directly from my code.

I would appreciate any assistance - but slowly please - at least until I'm off my knees.

Once again many thanks for your help.

Jim (NagaJim)

Share this post


Link to post
Share on other sites
Hi Supernat,
Restrictions and Requirements:
The tracks (single pixel wide lines and 5 pixel wide rectangles to represent track ballast) are drawn on the terrain image at map load time. Yes the trains follow these tracks, the user controlling speed, switch changes (so route), uncoupling cars etc.

The track data is stored in a separate file and consists of coordinate pairs defining straight lines (curves are approximated by having small straight line sections). In addition a track scheme is also stored - ie each end point may connect to 0 (end of line or map exit), 1 (normal track to track connections) or 2 (a switch) other tracks - 3-way switches are not used.

On a large map (say a large freight yard) there could be 5000 or more such tracks.

On the 3 schemes which you mentioned I would prefer to use the 2nd. ie load the terrain image to a surface, load the track data, and draw tracks on top of terrain. This would be a one time thing only done each time the user "enters" a new map.

You mentioned Textures but I found I could not use them as my Graphics card cant handle a texture greater than 2048x2048. Perhaps I have misunderstood your 3rd paragraph.

I have part of this scheme working ie load the terrain image to a surface and then load part of that surface to a texture and then render the texture to my picturebox. (see code snippets previously posted - Apologies I have posted them as Anonymous Poster). What I cant yet do is to draw my track on this same surface such that the composite image becomes the background which the user can scroll.

The moving trains usually account for a small amount of data to be drawn and I think I can draw those to the Devices backbuffer over the previously rendered background. However, maybe employing an approach as in your 1st option for the moving elements might be better.

I agree the 3rd option is overkill - its just I dont know how to code the 2nd one which I think is the one I need.

Many thanks for taking the time to help me - it is much appreciated.

Jim (NagaJim)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!