Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

DirectX floating point errors

Posted on 1998-03-14
8
Medium Priority
?
491 Views
Last Modified: 2008-02-01
I've got a problem using DirectX3D.  I've copied an example from the help and transformed it a little to work in c++builder.  And when running the program I occassionaly get an Invalid Floating point operation error or a divide by zero error.  The time it happens depends on the type of object I load in my 3d space, and the position of the objects.  With a cube it doesn't happen, with a sphere it most of the time does.

I had exactly the same problem when I tried this with OpenGL.

With OpenGL I could see (by debugging) that the error occurs inside the OpenGL a function call (for rendering I think - can't remember).

Any suggestions would be appreciated,
Thx

Odie
0
Comment
Question by:Odie
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
8 Comments
 
LVL 10

Expert Comment

by:rbr
ID: 1183464
Pls send some code!!!
0
 
LVL 1

Author Comment

by:Odie
ID: 1183465
I thought you would be little with just a part of the code, but I didn't want to force anyone into it from the beginning.  Anyway: here's the whole stuff:

#define INITGUID           // Must precede other defines and includes
//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop

#include "MainUnit.h"
//---------------------------------------------------------------------------
#pragma resource "*.dfm"
TForm1 *Form1;

#include <math.h>
#include <windows.h>
#include <malloc.h>
#include <d3drmwin.h>

#define MAX_DRIVERS 5           // Maximum D3D drivers expected

// Global variables
LPDIRECT3DRM D3DRM;
LPDIRECTDRAWCLIPPER lpDDClipper;
struct {
  LPDIRECT3DRMDEVICE Device;
  LPDIRECT3DRMVIEWPORT ViewPort;
  LPDIRECT3DRMFRAME FrameScene;
  LPDIRECT3DRMFRAME FrameCamera;

  GUID DriverGUID[MAX_DRIVERS];
  char DriverName[MAX_DRIVERS][50];
  int  NumDrivers;
  int  CurrDriver;

  BOOL bQuit;
  BOOL bMinimized;

  int BPP;

  // Non 3d-data
  LPDIRECT3DRMFRAME FrameBol1;
  LPDIRECT3DRMFRAME FrameBol2;
  double Bol1X, Bol2X;
  double Org1X, Org2X;
  double Mass1, Mass2;
  double Charge1, Charge2;
  double MassMid;
  double ChargeMid;
  double ForceMid;
  double RXOrg;
  double Grav, TimeScale, Elec;

  long Precision;

//  double Radia

} ProgramData;
//----------------------------------------------------------------------------
static DWORD BPPToDDBD(int bpp) {
  switch(bpp) {
    case  1: return DDBD_1;
    case  2: return DDBD_2;
    case  4: return DDBD_4;
    case  8: return DDBD_8;
    case 16: return DDBD_16;
    case 24: return DDBD_24;
    case 32: return DDBD_32;
    default: return 0;
  }
}
//---------------------------------------------------------------------------
static HRESULT WINAPI enumDeviceFunc(LPGUID lpGuid, LPSTR lpDeviceDescription,
                                      LPSTR lpDeviceName, LPD3DDEVICEDESC lpHWDesc,
                                       LPD3DDEVICEDESC lpHELDesc, LPVOID lpContext)
{
  static BOOL hardware = FALSE; // Current start driver is hardware
  static BOOL mono = FALSE;     // Current start driver is mono light
  LPD3DDEVICEDESC lpDesc;
  int *lpStartDriver = (int *)lpContext;

  lpDesc = lpHWDesc->dcmColorModel ? lpHWDesc : lpHELDesc;

  if (!(lpDesc->dwDeviceRenderBitDepth & BPPToDDBD(ProgramData.BPP)))
    return D3DENUMRET_OK;

  memcpy(&ProgramData.DriverGUID[ProgramData.NumDrivers], lpGuid, sizeof(GUID));
  lstrcpy(&ProgramData.DriverName[ProgramData.NumDrivers][0], lpDeviceName);

  if (*lpStartDriver == -1) {
    *lpStartDriver = ProgramData.NumDrivers;
    hardware = lpDesc == lpHWDesc ? TRUE : FALSE;
    mono = lpDesc->dcmColorModel & D3DCOLOR_MONO ? TRUE : FALSE;
  } else if (lpDesc == lpHWDesc && !hardware) {
    *lpStartDriver = ProgramData.NumDrivers;
    hardware = lpDesc == lpHWDesc ? TRUE : FALSE;
    mono = lpDesc->dcmColorModel & D3DCOLOR_MONO ? TRUE : FALSE;
  } else if ((lpDesc == lpHWDesc && hardware ) || (lpDesc == lpHELDesc && !hardware)) {
    if (lpDesc->dcmColorModel == D3DCOLOR_MONO && !mono) {
      *lpStartDriver = ProgramData.NumDrivers;
      hardware = lpDesc == lpHWDesc ? TRUE : FALSE;
      mono = lpDesc->dcmColorModel & D3DCOLOR_MONO ? TRUE : FALSE;
    }
  }
  ProgramData.NumDrivers++;

  if (ProgramData.NumDrivers == MAX_DRIVERS) return (D3DENUMRET_CANCEL);
  return (D3DENUMRET_OK);
}
//---------------------------------------------------------------------------
static BOOL EnumDrivers(HWND win)
{
  LPDIRECTDRAW DD;
  LPDIRECT3D D3D;
  HRESULT rval;

  DirectDrawCreate(NULL, &DD, NULL);
  rval = DD->QueryInterface(IID_IDirect3D, (void **) &D3D);
  if (rval != DD_OK) {
    DD->Release();
    return FALSE;
  }

  ProgramData.CurrDriver = -1;
  D3D->EnumDevices(enumDeviceFunc, &ProgramData.CurrDriver);

  if (ProgramData.NumDrivers == 0) {
    return FALSE;
  }
  D3D->Release();
  DD->Release();

  return TRUE;
}
//---------------------------------------------------------------------------
BOOL SetRenderState(void) {
  HRESULT rval;

  rval = ProgramData.Device->SetQuality(D3DRMLIGHT_ON | D3DRMFILL_SOLID | D3DRMSHADE_GOURAUD);
  if (rval != D3DRM_OK) {
    return FALSE;
  }

  // If you want to change the dithering mode, call SetDither here.
  ProgramData.Device->SetDither(false);

  // If you want a texture quality other than D3DRMTEXTURE_NEAREST
  // (the default value), call SetTextureQuality here.
  return TRUE;
}
//----------------------------------------------------------------------------
static BOOL CreateDevAndView(LPDIRECTDRAWCLIPPER lpDDClipper, int driver,
                              int width, int height)
{
  HRESULT rval;

  D3DRM->CreateDeviceFromClipper(lpDDClipper, &ProgramData.DriverGUID[driver],
                                  width, height, &ProgramData.Device);
  width = ProgramData.Device->GetWidth();
  height = ProgramData.Device->GetHeight();

  rval = D3DRM->CreateViewport(ProgramData.Device, ProgramData.FrameCamera, 0, 0,
                                width, height, &ProgramData.ViewPort);
  if (rval != D3DRM_OK) {
    ProgramData.Device->Release();
    return FALSE;
  }
  rval = ProgramData.ViewPort->SetBack(D3DVAL(5000.0));
  if (rval != D3DRM_OK) {
    ProgramData.Device->Release();
    ProgramData.ViewPort->Release();
    return FALSE;
  }

  if (!SetRenderState()) return FALSE;
  return TRUE;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
      : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
  HRESULT rval;

  Timer1->Tag += Timer1->Interval;

  // Tick the scene.
  ProgramData.FrameBol1
   ->SetPosition(ProgramData.FrameScene,
                  D3DVAL(ProgramData.Bol1X + Timer1->Tag/1000.0), 0.0, D3DVAL(15));
  ProgramData.FrameBol2
   ->SetPosition(ProgramData.FrameScene,
                  D3DVAL(ProgramData.Bol2X + Timer1->Tag/1000.0), D3DVAL(0.0), D3DVAL(15));

  // Clear the viewport.
  rval = ProgramData.ViewPort->Clear();
  if (rval != D3DRM_OK) {
    // Error
  }

  // Render the scene to the viewport.
  rval = ProgramData.ViewPort->Render(ProgramData.FrameScene);
  if (rval != D3DRM_OK) {
    // Error
  }

  // Update the window.
  rval = ProgramData.Device->Update();
  if (rval != D3DRM_OK) {
    // Error
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  // Initialise non-3D program data .........................................
  // Set bols position
  ProgramData.Bol1X = StrToInt(EditBol1PosX->Text);
  ProgramData.Bol2X = StrToInt(EditBol2PosX->Text);
  ProgramData.Org1X = ProgramData.Bol1X;
  ProgramData.Org2X = ProgramData.Bol2X;
  ProgramData.Mass1 = StrToInt(EditBol1Mass->Text);
  ProgramData.Mass2 = StrToInt(EditBol2Mass->Text);
  ProgramData.Charge1 = StrToInt(EditCharge1->Text);
  ProgramData.Charge2 = StrToInt(EditCharge2->Text);
  ProgramData.ChargeMid = (ProgramData.Charge1*ProgramData.Bol1X + ProgramData.Charge2*ProgramData.Bol2X)
                          / (ProgramData.Charge1 + ProgramData.Charge2);
  ProgramData.Grav = StrToInt(EditGravitationBase->Text)*pow(10, StrToInt(EditGravitationExponent->Text));
  ProgramData.ForceMid
   = (ProgramData.Elec*(ProgramData.Charge2*ProgramData.Bol2X + ProgramData.Charge2*ProgramData.Bol2X) - ProgramData.Grav*(ProgramData.Mass1*ProgramData.Bol1X + ProgramData.Mass2*ProgramData.Bol2X))
     /(ProgramData.Elec*(ProgramData.Charge1 + ProgramData.Charge2) - ProgramData.Grav*(ProgramData.Mass1 + ProgramData.Mass2));
  ProgramData.RXOrg = abs(ProgramData.Bol2X - ProgramData.Bol1X);
  ProgramData.MassMid = (ProgramData.Mass1*ProgramData.Bol1X + ProgramData.Mass2*ProgramData.Bol2X)
                        / (ProgramData.Mass1 + ProgramData.Mass2);
  ProgramData.Precision = StrToInt(EditPrecision->Text);
  ProgramData.TimeScale = StrToInt(EditTimeScaleBase->Text)*pow(10, StrToInt(EditTimeScaleExponent->Text));
  //........................................................................

  // Initialize and run
  ProgramData.BPP = 16;
  if (!EnumDrivers(Handle)) {
    // Error
  }

  D3DRM = NULL;
  Direct3DRMCreate(&D3DRM);

  // Create the master scene frame and camera frame.
  D3DRM->CreateFrame(NULL, &ProgramData.FrameScene);
  D3DRM->CreateFrame(ProgramData.FrameScene, &ProgramData.FrameCamera);
  ProgramData.FrameCamera->SetPosition(ProgramData.FrameScene,
                                        D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0));

  // Create a DirectDrawClipper object and associate the window with it.
  DirectDrawCreateClipper(0, &lpDDClipper, NULL);
  lpDDClipper->SetHWnd(0, Handle);

  // Create the D3DRM device by using the selected D3D driver.
  if (!CreateDevAndView(lpDDClipper, ProgramData.CurrDriver, ClientWidth, ClientHeight)) {
    // Fatal error 35
  }

  // Begin creating the Scene
  LPDIRECT3DRMFRAME LightFrame = NULL;

  LPDIRECT3DRMLIGHT Light1 = NULL;
  LPDIRECT3DRMLIGHT LightAmbient = NULL;
  LPDIRECT3DRMTEXTURE Texture = NULL;
  LPDIRECT3DRMWRAP Wrap = NULL;
  LPDIRECT3DRMMESHBUILDER MeshBuilder = NULL;
  LPDIRECT3DRMMESHBUILDER MeshBuilder2 = NULL;

  // Create Frames
  D3DRM->CreateFrame(ProgramData.FrameScene, &LightFrame);
  D3DRM->CreateFrame(ProgramData.FrameScene, &ProgramData.FrameBol1);
  D3DRM->CreateFrame(ProgramData.FrameScene, &ProgramData.FrameBol2);

  // Create Lights
  D3DRM->CreateLightRGB(D3DRMLIGHT_DIRECTIONAL, D3DVAL(0.9), D3DVAL(0.9), D3DVAL(0.9),
                         &Light1);
  LightFrame->AddLight(Light1);

  D3DRM->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVAL(0.75), D3DVAL(0.75), D3DVAL(0.75),
                         &LightAmbient);
  ProgramData.FrameScene->AddLight(LightAmbient);

  // Set the positions
  LightFrame->SetPosition(ProgramData.FrameScene, D3DVAL(2), D3DVAL(0.0), D3DVAL(22));
  ProgramData.FrameCamera->SetPosition(ProgramData.FrameScene,
                                        D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0));
  ProgramData.FrameCamera->SetOrientation(ProgramData.FrameScene,
                                           D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1),
                                            D3DVAL(0.0), D3DVAL(1), D3DVAL(0.0));
  ProgramData.FrameBol1->SetOrientation(ProgramData.FrameScene,
                                         D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1),
                                          D3DVAL(0.0), D3DVAL(1), D3DVAL(0.0));
  ProgramData.FrameBol1->SetRotation(ProgramData.FrameScene,
                                      D3DVAL(0.0), D3DVAL(0.1), D3DVAL(0.0), D3DVAL(0.05));
  ProgramData.FrameBol2->SetOrientation(ProgramData.FrameScene,
                                         D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1),
                                          D3DVAL(0.0), D3DVAL(1), D3DVAL(0.0));
  ProgramData.FrameBol2->SetRotation(ProgramData.FrameScene,
                                      D3DVAL(0.0), D3DVAL(0.1), D3DVAL(0.0), D3DVAL(0.05));

  // Make the Mesh
  D3DRM->CreateMeshBuilder(&MeshBuilder);
  D3DRM->CreateMeshBuilder(&MeshBuilder2);
  MeshBuilder->Load("sphere0.x", NULL, D3DRMLOAD_FROMFILE, NULL, NULL);
  MeshBuilder2->Load("sphere0.x", NULL, D3DRMLOAD_FROMFILE, NULL, NULL);
  if (ProgramData.Charge1 > 0) {
    MeshBuilder->SetColorRGB(1, 0, 0);
  } else {
    MeshBuilder->SetColorRGB(0, 1, 0);
  }

  if (ProgramData.Charge2 > 0) {
    MeshBuilder2->SetColorRGB(1, 0, 0);
  } else {
    MeshBuilder2->SetColorRGB(0, 1, 0);
  }

  // Create the Texture
  D3DVALUE Miny, Maxy, Heighty;
  D3DRMBOX D3DRMBox;

  MeshBuilder->GetBox(&D3DRMBox);
  Maxy = D3DRMBox.max.y;
  Miny = D3DRMBox.min.y;
  Heighty = Maxy - Miny;

  D3DRM->CreateWrap(D3DRMWRAP_CYLINDER, NULL,
                     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0),
                      D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0),
                       D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0),
                        D3DVAL(0.0), D3DDivide(Miny, Heighty),
                         D3DVAL(1.0), D3DDivide(-D3DVAL(1.0), Heighty),
                          &Wrap);
  Wrap->Apply((LPDIRECT3DRMOBJECT) MeshBuilder);
  Wrap->Apply((LPDIRECT3DRMOBJECT) MeshBuilder2);

  // Add the Texture
  D3DRM->LoadTexture("tutor.bmp", &Texture);

     // If you need a color depth other than the default (16), call IDirect3DRMTexture::SetShades here.
  MeshBuilder->SetTexture(Texture);
  MeshBuilder2->SetTexture(Texture);

     // If you need to create a material (for example, to create a shiny surface), call CreateMaterial and SetMaterial here.

  // Welcome to the world, objects!
  MeshBuilder->Scale(ProgramData.Mass1/5.0, ProgramData.Mass1/5.0, ProgramData.Mass1/5.0);
  ProgramData.FrameBol1->AddVisual((LPDIRECT3DRMVISUAL) MeshBuilder);

  MeshBuilder2->Scale(ProgramData.Mass2/5.0, ProgramData.Mass2/5.0, ProgramData.Mass2/5.0);
  ProgramData.FrameBol2->AddVisual((LPDIRECT3DRMVISUAL) MeshBuilder2);

  // Release all
  LightFrame->Release();
  MeshBuilder->Release();
  MeshBuilder2->Release();
  Light1->Release();
  LightAmbient->Release();
  Texture->Release();
  Wrap->Release();

  // Activate the rendering loop
  Panel1->Visible = false;
  Timer1->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
  Timer1->Enabled = false;

  ProgramData.FrameScene->Release();
  ProgramData.FrameCamera->Release();
  ProgramData.ViewPort->Release();
  ProgramData.Device->Release();

  D3DRM->Release();
  lpDDClipper->Release();

  ProgramData.bQuit = true;
}
//---------------------------------------------------------------------------

0
 

Expert Comment

by:azar
ID: 1183466
Without being able to get ALL of your code, it is tough to see anything obvious.   The code is quite simple and looks correct at first glance - it seems you most likely have a data error in your buttonclick methods data values.

ff you want, please send my the WHOLE project (you did not include the 'MainUnit' file included in the code above, etc.) zipped up and I'll debug it for you.  Give a written description of when the error occurs AND send the object files with the zipped MSVC++ project, C++/H files, etc.

I have a D3D book out, so I know this area well and I'd be happy to help  (I just joined this exchange, but it looks like a great resource/idea)

If you want to send the code, place a comment back with your E-mail and I'll send you a response there so you can E-mail to the address I send from
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 1

Author Comment

by:Odie
ID: 1183467
OK, great - smathsoft@geocities.com
0
 

Accepted Solution

by:
Ant031898 earned 200 total points
ID: 1183468
Add the following line:

_control87(MCW_EM,MCW_EM);

as the first line in the try block of your WinMain function and see if the problem goes away - worth a try.

i.e.

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
      try
      {
            _control87(MCW_EM,MCW_EM);
                Application->Initialize();
                ...
                ...
0
 
LVL 1

Author Comment

by:Odie
ID: 1183469
OK - I'm going to try it.

Could you tell me what it is?
Does this change the rounding mode?
(I once had a problem using arithmetic compression - it worked in c++ but not in pascal and it was all solved by just doing something (via assembler) with that control word, but I don't understand what exactly happened)
0
 
LVL 1

Author Comment

by:Odie
ID: 1183470
Incredible - are we supposed to smell that?  Bloody M.
I found what it means now, but am I right when thinking that even when putting of the exception error messages, I might still get bad results?  Not only things that don't look right but maybe a sneaky bug showing up later?

Thanks anyway
0
 

Expert Comment

by:Ant031898
ID: 1183471
That disables the floating point errors that are send by the win32 api, as far as I know.  If for example there is a discontinuity in the object you are drawing - this will filter it out.  I don't think it fixes the problem, but at least it hides it.  Well if you can't fix - f*ck it.
cheers
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
Suggested Courses

610 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question