3D preview

M

Michele Santucci

Re all,

Im writing (in managed C#) a simple application for path planning purposes
and I would like to put
the 3d preview of the object that I'm supposed to be planning the path for
(the is object provided
in .obj wavefront format or .x).
Since my application is a simple MDI gui I wish to put a simple child
toolbox with the '3d object viewer'
embeeded within where I will show the object itself probably floating on a
plane.
Is there a simple way to achieve that or I need to look for a specialized
control?

Thanks in advance,
Michele Santucci
 
P

Peter Duniho

Michele said:
Re all,

Im writing (in managed C#) a simple application for path planning
purposes and I would like to put
the 3d preview of the object that I'm supposed to be planning the path
for (the is object provided
in .obj wavefront format or .x).
Since my application is a simple MDI gui I wish to put a simple child
toolbox with the '3d object viewer'
embeeded within where I will show the object itself probably floating on
a plane.
Is there a simple way to achieve that or I need to look for a
specialized control?

There's no built-in control that takes as input data in the .x format
and automatically renders it in 3D for you. Though, that seems like a
reasonably useful thing to have, so maybe there's a third-party
implementation out there. Google can help you with that.

Otherwise, assuming by your question you mean that you actually want a
component that handles the 3D rendering for you, you'll have to
implement a custom control yourself. The custom control isn't too hard;
it will be the rendering that's a bit tricky.

Someone else asked recently about 3D rendering in .NET, and I found a
few web sites that seemed promising. I've been playing around a bit
with them, and while the samples aren't written the way I'd write them,
they do mostly work. You might find those links useful:

http://www.mdxinfo.com/tutorials.php?view=The basics
http://www.drunkenhyena.com/cgi-bin/dx9_net.pl
http://www.kalme.de/index.php?option=com_content&task=section&id=4&Itemid=26

Unfortunately, while I've got a new sample that I wrote while I was
investigating the above sites, it's not complete yet. All I've got is
hard-coded meshes, and no lighting at all. But if I get to a point
where it seems useful to post, I'll be happy to share.

Pete
 
V

vanderghast

The Example MeshFile, from chapter 5 of Managed DirectX by Tom Miller should
compile correctly after you remove the line calling the method Commit( ) of
the object Light (that method was not required and has been removed from the
API). That will be the only line with a compile error, after you added the
required references Microsoft.DirectX and Microsoft.DirectX.Direct3D
(requires DirectX SDK).

I assume you use a 32 bit OS. I still has an unresolved problem with 64 bit
OS ('' is not a valid Win32 application), so I won't take the risk to post
the code until that problem is still solved. It is less that 200 lines of
code (including comments). And it is not 'my' code so start with either...


Vanderghast, Access MVP


(...)
 
P

Peter Duniho

vanderghast said:
[...]
I assume you use a 32 bit OS. I still has an unresolved problem with 64
bit OS ('' is not a valid Win32 application), so I won't take the risk
to post the code until that problem is still solved. It is less that 200
lines of code (including comments). And it is not 'my' code so start
with either...

That generally occurs when one is trying to mix 64-bit code with 32-bit
code. In .NET, that's usually the outcome when an assembly has a target
CPU of "Any CPU", but is trying to interop with a 32-bit DLL. In that
case, one either needs to set the assembly to target "x86" only, or make
sure that the referenced DLL always matches the platform default (i.e.
you have a 64-bit version to use with the .NET assembly running on a
64-bit OS).

Pete
 
V

vanderghast

That does the trick ( Build: Platform target: x86 instead of the
default, Any CPU). At least, I can now use

Device device = null;

without generating the error.

I look to see if I can simplify Tom Miller's code enough to not be pure cut
and paste... even if, anyhow, the result will greatly be inspired from his
code, pp72-77.

Thanks for the trick, anyhow.


Vanderghast, Access MVP


Peter Duniho said:
vanderghast said:
[...]
I assume you use a 32 bit OS. I still has an unresolved problem with 64
bit OS ('' is not a valid Win32 application), so I won't take the risk to
post the code until that problem is still solved. It is less that 200
lines of code (including comments). And it is not 'my' code so start with
either...

That generally occurs when one is trying to mix 64-bit code with 32-bit
code. In .NET, that's usually the outcome when an assembly has a target
CPU of "Any CPU", but is trying to interop with a 32-bit DLL. In that
case, one either needs to set the assembly to target "x86" only, or make
sure that the referenced DLL always matches the platform default (i.e. you
have a 64-bit version to use with the .NET assembly running on a 64-bit
OS).

Pete
 
V

vanderghast

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace Chapter5Code
{
/// COPYRIGHT: this code is taken from
/// Managed DirectX 9 Graphics and Game Programming, Kick Start
/// at Sams, by Tom Miller
///
///
http://www.amazon.com/Managed-Direc...=sr_1_1?ie=UTF8&s=books&qid=1264541659&sr=8-1
///
/// lightly modified to take into account
/// modifications having occured since the publication
/// of the book.
///
/// You can resize the window, but not reloading the textures, the
x-file will then stay black.
///
/// See the original code to get comments, or consult the book to get
extra explanations.




public class Form1 : System.Windows.Forms.Form
{
private Device device = null;
private Mesh mesh = null;
private Material[] meshMaterials;
private Texture[] meshTextures;
private System.ComponentModel.Container components = null;
private float angle = 0.0f;

public Form1()
{

InitializeComponent();
this.SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.Opaque, true);
}


public void InitializeGraphics()
{
PresentParameters presentParams = new PresentParameters();

presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.AutoDepthStencilFormat = DepthFormat.D16;
presentParams.EnableAutoDepthStencil = true;

device = new Device(0, DeviceType.Hardware, this,
CreateFlags.SoftwareVertexProcessing, presentParams);

// Load our mesh, our function here down
LoadMesh(@"..\..\tiny.x");
}

private void LoadMesh(string file)
{
ExtendedMaterial[] mtrl;

// Load our mesh
mesh = Mesh.FromFile(file, MeshFlags.Managed, device, out mtrl);

// If we have any materials, store them
if ((mtrl != null) && (mtrl.Length > 0))
{
meshMaterials = new Material[mtrl.Length];
meshTextures = new Texture[mtrl.Length];

// Store each material and texture
for (int i = 0; i < mtrl.Length; i++)
{
meshMaterials = mtrl.Material3D;
if ((mtrl.TextureFilename != null) &&
(mtrl.TextureFilename != string.Empty))
{
// We have a texture, try to load it
meshTextures = TextureLoader.FromFile(device,
@"..\..\" + mtrl.TextureFilename);
}
}
}
}

private void SetupCamera()
{
device.Transform.Projection =
Matrix.PerspectiveFovLH((float)Math.PI / 4, ((float) this.Width) /
this.Height, 1.0f, 10000.0f);
device.Transform.View = Matrix.LookAtLH(new Vector3(0,0,
580.0f), new Vector3(0,0,0), new Vector3(0,1,0));
device.Lights[0].Type = LightType.Directional;
device.Lights[0].Diffuse = Color.White;
device.Lights[0].Direction = new Vector3(0, -1, -1);
device.Lights[0].Enabled = true;

}

protected override void OnPaint(System.Windows.Forms.PaintEventArgs
e)
{
device.Clear(ClearFlags.Target | ClearFlags.ZBuffer,
Color.CornflowerBlue, 1.0f, 0);

SetupCamera();

device.BeginScene();

DrawMesh(angle / (float)Math.PI, angle / (float)Math.PI * 2.0f,
angle / (float)Math.PI / 4.0f, 0.0f, 0.0f, 0.0f);

device.EndScene();

device.Present();

this.Invalidate();
}

private void DrawMesh(float yaw, float pitch, float roll, float x,
float y, float z)
{
angle += 0.01f;

device.Transform.World = Matrix.RotationYawPitchRoll(yaw, pitch,
roll) * Matrix.Translation(x, y, z);
for (int i = 0; i < meshMaterials.Length; i++)
{
device.Material = meshMaterials;
device.SetTexture(0, meshTextures);
mesh.DrawSubset(i);
}
}


protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.Size = new Size(800,600);
this.Text = "Form1";
}
#endregion


static void Main()
{
using (Form1 frm = new Form1())
{
frm.Show();
frm.InitializeGraphics();
Application.Run(frm);
}
}
}
}
 
M

Michele Santucci

Re all,

thank you for your hints, the code provided works fine.
I just have some problems with textures and/or lights ...
after I change windows size at run time the object keeps
being 'rotated' and visualized but everything (except background)
turns 'black'....

best regards,
Mike

vanderghast said:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace Chapter5Code
{
/// COPYRIGHT: this code is taken from
/// Managed DirectX 9 Graphics and Game Programming, Kick Start
/// at Sams, by Tom Miller
///
///
http://www.amazon.com/Managed-Direc...=sr_1_1?ie=UTF8&s=books&qid=1264541659&sr=8-1
///
/// lightly modified to take into account
/// modifications having occured since the publication
/// of the book.
///
/// You can resize the window, but not reloading the textures, the
x-file will then stay black.
///
/// See the original code to get comments, or consult the book to get
extra explanations.




public class Form1 : System.Windows.Forms.Form
{
private Device device = null;
private Mesh mesh = null;
private Material[] meshMaterials;
private Texture[] meshTextures;
private System.ComponentModel.Container components = null;
private float angle = 0.0f;

public Form1()
{

InitializeComponent();
this.SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.Opaque, true);
}


public void InitializeGraphics()
{
PresentParameters presentParams = new PresentParameters();

presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.AutoDepthStencilFormat = DepthFormat.D16;
presentParams.EnableAutoDepthStencil = true;

device = new Device(0, DeviceType.Hardware, this,
CreateFlags.SoftwareVertexProcessing, presentParams);

// Load our mesh, our function here down
LoadMesh(@"..\..\tiny.x");
}

private void LoadMesh(string file)
{
ExtendedMaterial[] mtrl;

// Load our mesh
mesh = Mesh.FromFile(file, MeshFlags.Managed, device, out
mtrl);

// If we have any materials, store them
if ((mtrl != null) && (mtrl.Length > 0))
{
meshMaterials = new Material[mtrl.Length];
meshTextures = new Texture[mtrl.Length];

// Store each material and texture
for (int i = 0; i < mtrl.Length; i++)
{
meshMaterials = mtrl.Material3D;
if ((mtrl.TextureFilename != null) &&
(mtrl.TextureFilename != string.Empty))
{
// We have a texture, try to load it
meshTextures = TextureLoader.FromFile(device,
@"..\..\" + mtrl.TextureFilename);
}
}
}
}

private void SetupCamera()
{
device.Transform.Projection =
Matrix.PerspectiveFovLH((float)Math.PI / 4, ((float) this.Width) /
this.Height, 1.0f, 10000.0f);
device.Transform.View = Matrix.LookAtLH(new Vector3(0,0,
580.0f), new Vector3(0,0,0), new Vector3(0,1,0));
device.Lights[0].Type = LightType.Directional;
device.Lights[0].Diffuse = Color.White;
device.Lights[0].Direction = new Vector3(0, -1, -1);
device.Lights[0].Enabled = true;

}

protected override void OnPaint(System.Windows.Forms.PaintEventArgs
e)
{
device.Clear(ClearFlags.Target | ClearFlags.ZBuffer,
Color.CornflowerBlue, 1.0f, 0);

SetupCamera();

device.BeginScene();

DrawMesh(angle / (float)Math.PI, angle / (float)Math.PI * 2.0f,
angle / (float)Math.PI / 4.0f, 0.0f, 0.0f, 0.0f);

device.EndScene();

device.Present();

this.Invalidate();
}

private void DrawMesh(float yaw, float pitch, float roll, float x,
float y, float z)
{
angle += 0.01f;

device.Transform.World = Matrix.RotationYawPitchRoll(yaw,
pitch, roll) * Matrix.Translation(x, y, z);
for (int i = 0; i < meshMaterials.Length; i++)
{
device.Material = meshMaterials;
device.SetTexture(0, meshTextures);
mesh.DrawSubset(i);
}
}


protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.Size = new Size(800,600);
this.Text = "Form1";
}
#endregion


static void Main()
{
using (Form1 frm = new Form1())
{
frm.Show();
frm.InitializeGraphics();
Application.Run(frm);
}
}
}
}
 
V

vanderghast

Yes, indeed, you would need to reload the textures, probably even better to
call InitializeGraphics on resizing (increasing one of the dimension), since
the back buffer has to be increased too. Without doing it, you probably have
inefficient bitblt ( the initial size differs to the actual one ) occurring
anyhow (maybe hard to notice on performing video card). So redo the whole
initialization on resizing or use fix borders for the form.

Vanderghast, Access MVP
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top