Click here to Skip to main content
15,867,686 members
Articles / Desktop Programming / MFC

3DHelper

Rate me:
Please Sign up or sign in to vote.
4.61/5 (9 votes)
17 Feb 2009CPOL3 min read 58.1K   1.2K   44   18
Helper class to display 3D data
3DHelperDemo

Introduction

Ever had the problem to display 3D-related data? E.g. to display a 3D-curve in a Windows dialog window? Don't like to implement a whole DirectX/OpenGL class hierarchy?
There is a solution: The 3DHelper class!

More tools can be found on my homepage.

Background  

If you are familiar with 3D programming, you already might have used free/not so free libraries to perform the task of rendering 3D objects onto your screen.
The big (in my opinion!) drawback of that approach is: your code is getting more and more complicated to maintain and even understand. Not to mention portability.

Having just some files to be included into your project, performing all the necessary math-stuff to "get  3D" sounds too nice to be true? Now its real!

The Solution

The aim of the API described in this article is simply to help you to project 3D data into your 2D window.
Given a 3D point (e.g. a point being part of a nurbs-surface, a 3D function value, etc.) the API transforms this point and returns a coordinate pair representing a dot in your window. 

And the best - there is no sophisticated OpenGL/DirectX stuff involved. This is a pure software solution.

Using the Code 

To allow the API to help you, it needs some basic steps to be performed:

  1. Add a variable of type CMF3DHelper to your project.
  2. At start up (and after each resize event) call the CMF3DHelper::Initialize() function of your variable. (see 1.)
    This Initialize() function needs parameters:
    • A pointer to the device context (DC) of your window (used to get the window size)
    • The "cube" representing your data, represented by two vectors: vmin and vmax.
      All of your data points should lay inside that cube. Imagine something like a bounding cube, covering all your data points.
      Example in 2D: you need to display a curve of form y=sin(x) where x is between [-PI] and [+PI]. The result of that function is in range of [-1] up to [+1].
      Therefore you have to define the bounding box (2D!) using two corners:
      (-1, -PI) which is top left and 
      (+1, +PI) similar to bottom right.
    • A flag (bSupportTrackBall) to tell the API whether to perform rotation controlled by mouse or not. 
  3. For each data point to be calculated, call the RenderPoint() function. It returns the corresponding screen(=window) coordinates of your 3D data point.

The best to do is to check 3DHelperDemoSimple project. I reduced the code to the minimum (no checking code) to clarify the steps.
Open the 3DHelperDemoSimple project, and select the OnInitDialog method.

Only the lines below are added to the code generated by the wizard:    

C++
// Initialize the 3D system
initialize();

The initialize function itself is implemented some lines below.
Steps performed:

  1. Initialize the API.
  2. Start the update timer, used to refresh the mouse (=rotation) information. In our case, the whole scene will be repainted each 25 milliseconds.
C++
// Set up initial 3D system
void CMy3DHelperDemoSimpleDlg::initialize()
{
	CWnd *pTarget = GetDlgItem(IDC_STATIC_PLACEHOLDER);
	m_c3DHelper.Initialize(pTarget->GetDC(), NeHe::Vector(-2.0f, -2.0f, -2.0f), 
		NeHe::Vector(2.0f,2.0f,2.0f), TRUE);

	// Timer used to refresh "trackball" information
	SetTimer(1, 25, NULL);
}

Triggered by the timer, every 25 ms the OnTimer function will be entered.
Inside, the trackball position will be updated (UpdateTrackBall, which again needs the current DC as parameter), and the scene will be redrawn (redraw()).

C++
void CMy3DHelperDemoSimpleDlg::OnTimer(UINT nIDEvent) 
{
	// Timer is used to refresh trackball information
	if(nIDEvent == 1) {
		KillTimer(nIDEvent); // Prevent timer "overlapping"
		m_c3DHelper.UpdateTrackBall
			(GetDlgItem(IDC_STATIC_PLACEHOLDER)->GetDC());
		redraw();
		SetTimer(1, 25, NULL); // Start timer for next redrawing round
	}
	CDialog::OnTimer(nIDEvent);
}

Redraw again is trivial. Just take your data point per point, call RenderPoint() for each of them and display the result using e.g. SetPixel() function.

The 3DHelperDemo project implements a more complex example.

Points of Interest 

I decided not to implement the whole math stuff by myself (think that is not a unique task...). So I have taken some matrix/vector code from NeHe (a GREAT site related to OpenGL, got my 5!).

To get a better idea on how OpenGL is implemented, I took a closer look at the free mesa implementation. This is a must for everyone interested in 3D implementation! 

Notes

Any feedback would be appreciated!

See more tools and updates on SoftwareHive.

History

  • 2009/02/14 - Initial release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Business Analyst UPC AT B2B customers
Austria Austria
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionMemory deallocation problem. Pin
mrsilver9-Apr-19 1:57
mrsilver9-Apr-19 1:57 
GeneralReading Pin
mateusz.matyaszek8-Jun-10 22:24
mateusz.matyaszek8-Jun-10 22:24 
GeneralRe: Reading Pin
MikeTheDwarf9-Jun-10 1:14
MikeTheDwarf9-Jun-10 1:14 
GeneralRe: Reading Pin
mateusz.matyaszek22-Jun-10 21:34
mateusz.matyaszek22-Jun-10 21:34 
GeneralRe: Reading Pin
MikeTheDwarf23-Jun-10 0:59
MikeTheDwarf23-Jun-10 0:59 
Questionuse in VB.net Pin
GeneralBiSoN27-Feb-09 23:21
GeneralBiSoN27-Feb-09 23:21 
hi i am a beginner in Programming.
AND my english isnt the best. Im sorry for that!!!

The moving grid looks VERRY! NICE.
But i am not so familiar with C++
Cry | :((

VB.net is the only Programming language for people like me...

But i need something like your helper class.
How can i use it in VB?

May be it helps if i explain it:

I wanted to give it a list of coordinates.
And it should Diplay it.
I have a colored or grayscale Image and it should shown in 3D (may be with textures of itself but i dont think it is so important).
Each pixel is a coordinate on the Z axis and the Brightnes is the "deep" of Y axis.
A zoom were verry helpful too...
I hope you can understand what i'm typing WTF | :WTF:

If someone can explain hot to release that ... i were really thankful!

MFG: General BiSoN
AnswerRe: use in VB.net Pin
MikeTheDwarf1-Mar-09 21:12
MikeTheDwarf1-Mar-09 21:12 
GeneralRe: use in VB.net [modified] Pin
GeneralBiSoN4-Mar-09 8:14
GeneralBiSoN4-Mar-09 8:14 
GeneralRe: use in VB.net Pin
MikeTheDwarf4-Mar-09 8:34
MikeTheDwarf4-Mar-09 8:34 
GeneralRe: use in VB.net Pin
GeneralBiSoN5-Mar-09 5:16
GeneralBiSoN5-Mar-09 5:16 
GeneralRe: use in VB.net Pin
MikeTheDwarf5-Mar-09 8:27
MikeTheDwarf5-Mar-09 8:27 
GeneralSounds nice Pin
john wallis17-Feb-09 11:20
john wallis17-Feb-09 11:20 
GeneralRe: Sounds nice Pin
MikeTheDwarf17-Feb-09 23:47
MikeTheDwarf17-Feb-09 23:47 
GeneralRe: Sounds nice Pin
john wallis18-Feb-09 12:22
john wallis18-Feb-09 12:22 
GeneralRe: Sounds nice Pin
john wallis18-Feb-09 12:36
john wallis18-Feb-09 12:36 
AnswerRe: Sounds nice Pin
MikeTheDwarf19-Feb-09 6:54
MikeTheDwarf19-Feb-09 6:54 
JokeRe: Sounds nice Pin
john wallis20-Feb-09 0:34
john wallis20-Feb-09 0:34 
GeneralRe: Sounds nice Pin
MikeTheDwarf20-Feb-09 5:46
MikeTheDwarf20-Feb-09 5:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.