We help IT Professionals succeed at work.

3D Studio - Delphi App

WoodyJ3
WoodyJ3 asked
on
467 Views
Last Modified: 2010-04-04
Hi,
   Is there an application (with source) out there that will let me load in a 3D studio file and let me manipulate it?  

What I need is a program that will load in a .3ds file or any other 3D Studio file and let me navigate though it using the mouse.  I also need to detect mouse clicks.  i.e. If I load in a house I want to click on the door and know that I clicked the Door object.  Hope this makes sense.

Any comments welcome!!!

I should mention it must use OpenGL.

Help ?????????

Cheers
Woody.
Comment
Watch Question

Commented:
Woody, today is your lucky day ;-) Just go straight to my homepage www.lischke-online.de/3DS.html and download Delphi sources for a 3ds import library.

There's a demo project which almost fullfills all your requests and comes with source too. The only thing you have to implement yourself is picking. But compared to the huge work already been done this should be something you can manage alone, I think.

Ciao, Mike

Commented:
Lische,

you did a really nice job! Nice page too.

Zif.

Commented:
Thanks Zif, writing this monster was a though job, I can tell you... (btw. it is for weeks now under the top 20 downloads on www.delphipages.com).

Ciao, Mike

Commented:
Jesus Mike that's excellent. Lotsa work in that

The Neil

Commented:
hehe
mike is waiting all year for this question :-)

now anybody know where a great treeview component is?   ;-)

Commented:
Aaah, you got me Barry :-) Hope you all have fun with my stuff!

Ciao, Mike

Author

Commented:
Yes, I must agree that is brilliant.  My only question is now.  How do I do the picking?  I'm still learning OpenGL and the routines for picking I've found don't seem to work with the "opener".  

Any Ideas?

I'll leave this question open for a while, then I'll give Mike the points.

Cheers
Woody.

Commented:
Hi Woody,

picking is not so hard as it may seem. Here's the code I use in GLScene (my OpenGL library you also can download for free from my homepage):

procedure TGLSceneViewer.PickObjects(var Rect: TRect; PickList: TGLPickList;
                                   objectCountGuess: Integer);
type
   { TODO : local type to remove }
   PCardinalVector = ^TCardinalVector;
   TCardinalVector = array[0..0] of Cardinal;
var
   buffer : PCardinalVector;
   hits : Integer;
   i : Integer;
   current, next : Cardinal;
   szmin, szmax : Single;
begin
   Assert((FState = dsNone));
   Assert(Assigned(PickList));
   ActivateRenderingContext(FCanvas.Handle, FRenderingContext);
   FState := dsPicking;
   try
      glMatrixMode(GL_PROJECTION);
      glPushMatrix;
      buffer := nil;
      try
         glLoadIdentity;
         gluPickMatrix(Rect.Left, Height - Rect.Top,
                       Abs(Rect.Right - Rect.Left), Abs(Rect.Bottom - Rect.Top),
                       TVector4i(FViewport));
         FCamera.ApplyPerspective(FViewport, Width, Height,
                                  GetDeviceCaps(Canvas.Handle, LOGPIXELSX));
         // check countguess, memory waste is not an issue here
         if objectCountGuess<8 then objectCountGuess:=8;
         hits:=-1;
         repeat
            if hits < 0 then begin
               // Allocate 4 integers per row (Egg : dunno why 4)
               // Add 32 integers of slop (an extra cache line) to end for buggy
               // hardware that uses DMA to return select results but that sometimes
               // overrun the buffer.  Yuck.
               ReallocMem(buffer, objectCountGuess * 4 * SizeOf(Integer) + 32 * 4);
               // increase buffer by 50% if we get nothing
               Inc(objectCountGuess, objectCountGuess shr 1);
            end;
            // pass buffer to opengl and prepare render
            glSelectBuffer(objectCountGuess*4, @Buffer^);
            glRenderMode(GL_SELECT);
            glInitNames;
{ TODO : glPushName(0) with no glPopName, bug ? }
            glPushName(0);
            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity;
            // render the scene (in select mode, nothing is drawn)
            if Assigned(FCamera) and Assigned(FCamera.FScene) then
               with FCamera.FScene do begin
                  ValidateTransformation(Camera);
                  RenderScene(Self);
               end;
            glFlush;
            Hits := glRenderMode(GL_RENDER);
         until Hits > -1; // try again with larger selection buffer
         Next := 0;
         PickList.Clear;
         PickList.Capacity := Hits;
         for I := 0 to Hits-1 do begin
            Current := Next;
            Next := Current + Buffer[Current] + 3;
            szmin := (Buffer[current + 1] shr 1) / MaxInt;
            szmax := (Buffer[current + 2] shr 1) / MaxInt;
            PickList.AddHit(TGLCustomSceneObject(Buffer[Current + 3]), szmin, szmax);
         end;
      finally
         FreeMem(Buffer);
         glMatrixMode(GL_PROJECTION);
         glPopMatrix;
      end;
   finally
      FState := dsNone;
      DeactivateRenderingContext;
   end;
end;


TGLPickList is just a TList with a record as data holding a scene object reference and the limits (as indicated in the PickList.AddHit call above).

Ciao, Mike

Author

Commented:
Thanks I'll let you know how I get on.

ta
Woody.

Author

Commented:
I couldn't seem to get that to work.  I wasn't geting any hits at all.

Any thoughts?

Commented:
mmh, then I need to have a look at your project. There are too many potential problems so can't say from "don't get any hits at all" what's wrong (send it to public@lischke-online.de).

Ciao, Mike

Commented:
PS: Please send only a stripped down version so I can focus on the picking problem.

Author

Commented:
the procedure you sent me...  Commented out some bits...

procedure TForm_Main.PickObjects(var Rect: TRect; PickList: {TGLPickList} Tlist;
                                                                    objectCountGuess: Integer);
type
      { TODO : local type to remove }
      PCardinalVector = ^TCardinalVector;
   TCardinalVector = array[0..0] of Cardinal;
var
   buffer : PCardinalVector;
   hits : Integer;
   i : Integer;
   current, next : Cardinal;
   szmin, szmax : Single;
begin
//   Assert((FState = dsNone));
//   Assert(Assigned(PickList));
      ActivateRenderingContext(Canvas.Handle, FRenderingContext);
try
      glMatrixMode(GL_PROJECTION);
      glPushMatrix;
      buffer := nil;
      try
         glLoadIdentity;
         gluPickMatrix(Rect.Left, Height - Rect.Top,
                       Abs(Rect.Right - Rect.Left), Abs(Rect.Bottom - Rect.Top),
                       TVector4i(FViewport));

                  // check countguess, memory waste is not an issue here
                  if objectCountGuess<8 then objectCountGuess:=8;
                  hits:=-1;
         repeat
            if hits < 0 then begin
               // Allocate 4 integers per row (Egg : dunno why 4)
               // Add 32 integers of slop (an extra cache line) to end for buggy
               // hardware that uses DMA to return select results but that sometimes
               // overrun the buffer.  Yuck.
               ReallocMem(buffer, objectCountGuess * 4 * SizeOf(Integer) + 32 * 4);
               // increase buffer by 50% if we get nothing
               Inc(objectCountGuess, objectCountGuess shr 1);
            end;
            // pass buffer to opengl and prepare render
            glSelectBuffer(objectCountGuess*4, @Buffer^);
            glRenderMode(GL_SELECT);
            glInitNames;
{ TODO : glPushName(0) with no glPopName, bug ? }
            glPushName(0);
            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity;
            // render the scene (in select mode, nothing is drawn)

            glFlush;
            Hits := glRenderMode(GL_RENDER);
         until Hits > -1; // try again with larger selection buffer
         Next := 0;
//         PickList.Clear;
//         PickList.Capacity := Hits;
                  for I := 0 to Hits-1 do begin
                        Current := Next;
                        Next := Current + Buffer[Current] + 3;
                        szmin := (Buffer[current + 1] shr 1) / MaxInt;
                        szmax := (Buffer[current + 2] shr 1) / MaxInt;
                        ShowMessage('john');
//            PickList.AddHit(TGLCustomSceneObject(Buffer[Current + 3]), szmin, szmax);
                  end;
            finally
                  FreeMem(Buffer);
         glMatrixMode(GL_PROJECTION);
         glPopMatrix;
      end;
   finally
//      FState := dsNone;
//      DeactivateRenderingContext;
   end;
end;


the call im using...


procedure TForm_Main.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
Var
a : trect;
begin
      SetFocus;
      FLastX := X;
      FLastY := Y;

      a.Left := 1;
      a.Top := 1;
      a.Bottom := height;
      a.Right := width;
      PickObjects(a, nil, 10);
end;


i think notepad has screwed the indents.  Sorry.

Am I calling this procedure correctly?

Cheers
Woody

Author

Commented:
Sorry, didn't read it correctly.  I'll send the email shortly.

John.
Commented:
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION

Commented:
Oops, FormPaint should actually look so:

procedure TForm_Main.FormPaint(Sender: TObject);

begin
  DoRender;
  // copy back buffer to front
  SwapBuffers(Canvas.Handle);
end;

Ciao, Mike

Author

Commented:
Adjusted points to 385

Author

Commented:
Thanks very much.

I think Im gonna have to buy several books on this openGL stuff.  When I finished this project I'll send it you.

Thanks again.  You can have all of my points.

John.

Commented:
Thank you for the points and the A grading. Well, after you have read all those books you will have gotton lots of new points, I'm sure ;-))

Ciao, Mike

Gain unlimited access to on-demand training courses with an Experts Exchange subscription.

Get Access
Why Experts Exchange?

Experts Exchange always has the answer, or at the least points me in the correct direction! It is like having another employee that is extremely experienced.

Jim Murphy
Programmer at Smart IT Solutions

When asked, what has been your best career decision?

Deciding to stick with EE.

Mohamed Asif
Technical Department Head

Being involved with EE helped me to grow personally and professionally.

Carl Webster
CTP, Sr Infrastructure Consultant
Empower Your Career
Did You Know?

We've partnered with two important charities to provide clean water and computer science education to those who need it most. READ MORE

Ask ANY Question

Connect with Certified Experts to gain insight and support on specific technology challenges including:

  • Troubleshooting
  • Research
  • Professional Opinions
Unlock the solution to this question.
Join our community and discover your potential

Experts Exchange is the only place where you can interact directly with leading experts in the technology field. Become a member today and access the collective knowledge of thousands of technology experts.

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.