Table
of Contents
#include "GWin3D.h"
// this function draws one frame.
it is called 20 times per second
void __fastcall UpdateFrameFunction( gwWindow
*Win)
{
// create a 3D object from a
VRML model file
// (since this is static, its
created only the first time this function is called)
static gwSprite
MySprite("MyVrmlFile");
// rotate the object
MySprite.ModifyRotation
(10,17,23);
// draw the object
in the window
MySprite.Draw(Win);
}
void main(void)
{
// initialize the GWin3D library
gwInitLib();
// create a 3D window and
specify the frame-drawing
function
gwWindow
MyWindow(NULL,UpdateFrameFunction,GW_BLOCK);
}
// This is at the top of the gwWindow
's PeriodicFunction:
gwTimer
Elapsed;
// main body of the PeriodicFunction is here
...
...
Universe.Draw(Win);
// This code is at the bottom of the
PeriodicFunction:
// Adjust the period to be a little more than how
long it took this
// function to execute (this assumes Win->MaxElapsedTimeMs
// is very large so that highest LODs
are always used):
Win->RealTimeTask->Period
= Elapsed.Get()/800;
| Level of detail (where 0=highest) | Maximum number of polygons | Actual number of polygons (example) | |
| 0 | 2097152* | 340 | |
| 1 | 524288* | 340 | |
| 2 | 131072* | 340 | |
| 3 | 32768* | 340 | |
| 4 | 8192* | 340 | |
| 5 | 2048 | 340 | |
| 6 | 512 | 340 | |
| 7 | 128 | 340 | |
| 8 | 32 | 40 | |
| 9 | 8 | 8 | |
| 10 | 2 | 0 | |
| (11 and beyond) | 0 | 0 |
gwSprite
MySprite("MyVrmlFile");
MySprite.Flags |= GW_TRANSPARENT;
Universe.AddSubSprite
(&MySprite);
...
...
// first draw non-translucent
sprites
Universe.Draw(Win,0,GW_TRANSPARENT);
// then draw translucent sprites
Universe.Draw(Win,GW_TRANSPARENT,GW_TRANSPARENT);
void main(void)
{
#ifdef _DEBUG
// enable warnings and dbg console
hotkeys
gwSetDebug(GW_ENABLE_GWDP_DBG |
GW_WARN_DBG | GW_FATAL_DBG);
#else
// enable only fatal error messages
gwSetDebug
(GW_FATAL_DBG);
#endif
...
| Command: | Examples: | Meaning: |
| h | H | Help. Displays a list of these commands. |
| g | G | Go. Continue thread execution. |
| s[<n>] | s (run till next msg) s12 (run till 12 msgs display) |
Step. Run the thread until this many debug messages have been displayed, after which execution will stop at the DBG> prompt. |
| sf<HexVal> | sfFFFFFFFFFFFFFFFF
(show all sprites) sf0000004800410600 (show certain sprites) |
When a sprite with any of the specified Flags bits set is drawn, display a line of text describing the sprite. See gwSprite::Flags. Also see NOTE 1. |
| b<HexVal> | b20 (showVRML parsing) b4 (show level of detail statistics) |
Set deBug map to the specified HEX value. See table of bits below. Also see NOTE 1. |
| f<String> | fMySprite (don't show dbg messages unless they contain
the
string "MySprite") f (Remove string filtering and allow all enabled dbg messages to appear) |
Filter messages. Display only messages that contain the specified string (Message must still have been enabled with the 'b' command) |
| w<String> | wMySprite (Stop execution when a dbg message
containing the
string "MySprite" appears) w (disable watch mode) |
Watch. If <String> is present in a displayed message, then pause execution at the DBG> prompt. |
| x | X | eXit the program. NOTE: This forces an ungraceful exit and will likely cause program errors to occur. |
| Bit map: | Preprocessor Symbol (if gwSetDebug is used): | Message Type: |
| 1 | GW_FATAL_DBG | Really bad errors |
| 2 | GW_WARN_DBG | Non-fatal, possible programming mistakes |
| 4 | GW_LOD_STATS_DBG | Dynamic level-of-detail statistics (not yet implemented) |
| 0x20 | GW_VRML_DBG | High-level VRML parsing (by gwSprite::Load ) |
| 0x40 | GW_VRML_PARAMETERS_DBG VRML | keyword parameters (by gwSprite::Load) |
| 0x80 | GW_VRML_TOKENS_DBG | VRML keywords (by gwSprite::Load ) |
| 0x400 | GW_SCANCODE_DBG | Keystrokes in a 3D window. |
| 0x800 | GW_VIEWPOINT_DBG | Camera position and orientation. |
| 0x1000 | GW_OPENGL_DBG | OpenGL calls |
| 0x2000 | GW_TASK_DBG | Show thread IDs |
| 0x4000 | GW_SOUND_DBG | Sound commands |
| 0x8000 | GW_CHECK_MATRIX_STACK_DBG | Checks for invalid elements in the OpenGL modelview and projection matrix stacks. NOTE: This checks the stack by emptying it and then refilling it. If another thread needs the matrix stack during this time, a failure will occur. In other words, use this only in applications that have only one thread. |
| 0x10000 | GW_NET_DBG | Network activity ( gwNetPackets and gwNetData ) |
printf("Press x to terminate.\n");
// we do it this way so the GWin3D debug prompt can
be used if desired
while(1)
{
Sleep(500);
if(kbhit())
if(getchar() == 'x')
break;
}
Win->BackClip
= 10000000;
Win->FrontClip
= .001;
Win->BottomBorder
=0;
Win->LeftBorder
= 0;
Win->LodFactor
=100;
Win->MaxElapsedTimeMs
=0;
Win->RightBorder
= 0;
Win->TopBorder
= 0;
Win->ApertureAngle
=150;
Sprite->Emission[0]=1;
Sprite->Emission[1]=1;
Sprite->Emission[2]=1;
Sprite->Emission[3]=1;
if(Win->KeyStatus
[GW_KEY_DOWN_ARROW] & GW_KEY_DOWN_NOW)
Win->ViewpointSprite
->ModifyRotation
(-2,0,0);
if(Win->KeyStatus
[GW_KEY_UP_ARROW] & GW_KEY_DOWN_NOW)
Win->ViewpointSprite
->ModifyRotation (2,0,0);
if(Win->KeyStatus [GW_KEY_RIGHT_ARROW] &
GW_KEY_DOWN_NOW)
Win->ViewpointSprite
->ModifyRotation
(0,-2,0);
if(Win->KeyStatus
[GW_KEY_LEFT_ARROW] & GW_KEY_DOWN_NOW)
Win->ViewpointSprite
->ModifyRotation (0,2,0);
GW_FUNCTIONPREMOD unsigned int
GW_FUNCTIONINMOD
WrapInitFunc( gwRealTimeTask
*Task)
{
// Get the gwWindow
object
gwWindow *Win=(gwWindow
*)Task->Context;
// Create a window
if no handle was
passed
if(!Win->Wnd)
{
Win->Wnd=CreateWindow
(
"GW3DWIN",
"GWin3D",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
(HMENU)NULL,
0,//hInstance,
NULL
);
if(!Win->Wnd)
SERRCHECK;
Win->MyWindow=1;
}
Win->DC=GetDC(Win->Wnd);
// Initialize the
rendering context
Win->Select();
return 0;
}
Win3D=new gwWindow(m_hWnd,NULL,0);
// disable auto-LOD because we're not drawing at any constant rate
Win3D->MaxElapsedTimeMs=0;
Win3D->LodFactor=1;
Win3D->PrepareForDrawing();
Floor=new gwSprite("floorplan");
Win3D->FinishDrawing();
{
sizeof(PIXELFORMATDESCRIPTOR),
1, // Version
PFD_DRAW_TO_WINDOW|
PFD_SUPPORT_OPENGL|
PFD_DOUBLEBUFFER|
PFD_GENERIC_ACCELERATED, //
dwFlags
PFD_TYPE_RGBA, // iPixelType -
RGBA context
24, // cColorBits - 24 Bit
Color
0, 0, 0, 0, 0, 0, // RGB Bits
& Shifts
0, 0, // Alpha buffer
0, 0, 0, 0, 0, // Accumulator
32, // cDepthBits - Z Buffer
0, // Stencil Bits
1, // Auxiliary Buffers
PFD_MAIN_PLANE, // Layer type
0, // Reserved
0, // Layer Mask
0, // Visible Mask
0 // Damage Mask
}
// the app is allowed to use sprite
flags below bit 32
#define MY_VIEWPOINT_SPRITE 0x10000
// create a spaceship (must be declared within
PeriodicFunction body
// so that the constructor is called in the right thread
context)
static gwSprite
Spaceship(...);
// do stuff that need be done only once
static int FirstTime=1;
If(FirstTime)
{
FirstTime=0;
// put the pilot in
the spaceship
Spaceship.AddSubSprite
(Win->ViewpointSprite
);
// set a flag bit in
the viewpoint so
the Draw function
// can recognize it for
drawing separately
Win->ViewpointSprite
->Flags |= MY_VIEWPOINT_SPRITE;
// Add the spaceship
to the universe.
Universe.AddSubSprite
(&Spaceship);
}
... (update sprite positions as needed here)
// draw the spaceship separately, relative to the origin. This works as long
// as the spaceship is a direct child of the Universe, or
nobody's child.
// This way we don't have to draw the entire universe twice.
Spaceship.Draw(Win, MY_VIEWPOINT_SPRITE,
MY_VIEWPOINT_SPRITE);
// draw all sprites (spaceship is drawn again here
because we didn't
bother
// specifying flags criteria).
Universe.Draw(Win);
// this code is sensitive to the level
(current state) of
the left shift button
if(Win->KeyStatus
[GW_KEY_LEFT_SHIFT] & GW_KEY_DOWN_NOW) Pitch ++;
// this code is sensitive to the down-going edge of
the left mouse
button
if(Win->KeyStatus
[GW_KEY_LBUTTON] & GW_KEY_WAS_DOWN)
{
// clear the history bit
Win->KeyStatus
[GW_KEY_LBUTTON]
&= ~GW_KEY_WAS_DOWN;
printf("LBUTTON %d
%d\n",Win->MouseX,Win->MouseY);
}
gwSprite
MySprite1("MyObjectsDir//spaceship");



// define the callback function
unsigned long MyEnumVerticesFunc
(
int LOD,
gwVertex
& Vertex
)
{
// process this vertex however
we want
...
...
return 0;
}
...
...
...
// create a sprite from VRML files...
gwSprite
MySprite1;
// load the model (and call MyEnumVerticesFunc()
for each vertex )
MySprite1.Load("MyVrmlObjectFile",0,1,1,1,
MyEnumVerticesFunc);
After a call to the Load function, the sprite's NumPolygons member will
contain the number of triangles (each polygon
in the VRML file is
converted to as many triangles as is needed) in the highest level of
detail, and the Radius
member contains the distance to the furthest
vertex from the
origin of the sprite.
gwSprite
MySprite1;
...
...
MySprite1.Load("MyObjectsDir//MyVrmlObjectFile",GW_NO_SMOOTH
|
GW_FLIP_POLYGONS);
// Draw all sprites
Universe.Draw(Win);
// Draw the ViewpointSprite.
// Note: If the viewpoint sprite is a subsprite in a sprite
tree, the
entire
// parent sprite tree of the ViewpointSprite must be drawn so
that its
// position is correct.
Win->ViewPointSprite
->Draw(Win);
// Draw all solid sprites
Universe.Draw(Win,0,GW_TRANSPARENT);
// Draw all transparent
sprites
Universe.Draw(Win,GW_TRANSPARENT,GW_TRANSPARENT);
Example 3:
// Draw all solid sprites that use depth testing
Universe.Draw(Win,0,GW_TRANSPARENT | GW_NO_DEPTH_TEST);
// Draw all transparent
sprites that use depth
testing
Universe.Draw(Win,GW_TRANSPARENT,GW_TRANSPARENT |
GW_NO_DEPTH_TEST);
// Draw all solid sprites that don't use depth
testing
Universe.Draw(Win,GW_NO_DEPTH_TEST,GW_TRANSPARENT |
GW_NO_DEPTH_TEST);
// Draw all transparent
sprites that don't use
depth testing
Universe.Draw(Win,GW_NO_DEPTH_TEST |
GW_TRANSPARENT,GW_TRANSPARENT | GW_NO_DEPTH_TEST);
// Draw all sprites that have their
flag bit 6 clear and
bit 8 is set
Universe.Draw(Win,0x100,0x140);
MySprite.Light =GL_LIGHT0;
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_AMBIENT, gwColorGrey.a);
glLightfv(GL_LIGHT0, GL_DIFFUSE, gwColorGrey.a);
glLightfv(GL_LIGHT0, GL_SPECULAR, gwColorGrey.a);
...
...
glDisable(GL_LIGHT0);
MySprite.Light =-1;
Mesh.CreateFromHeightField("myimage.jpg");
gwMatrix M;
M.SetRotation
(90,0,0);
Mesh.Multiply(M);
gwSprite Q;
Q.LoadMesh(&Mesh);
MyImage.Save("MyImage.jpg");
MyImage.Save("MyImage.jpeg","quality=60.4","jpg");
MyImage.Save("MyImage.jp2");
MyImage.Save("ImageDirectory//MyImage.jp2","rate=.04");
MyImage.Save("MyImage.bmp");
gwImage
MyImage("flerb.jpg");
if(!MyImage.Valid)
{
printf("Couldn't load
file\n");
return 1;
}
// Below, we could have let CombineComponents
allocate this buffer,
// but one purpose of this example is to show you how
// to do it, yourself, if you have a need.
char *Pixels=(char *)malloc
(
MyImage.GetHeight(0)
*
MyImage.GetWidth(0)
*
Image.GetNumComponents()
// allocate extra
space to
account for a few wasted bytes at end
// of each row
+
3
*
MyImage.GetHeight(0)
);
if(!Pixels)
{
printf("Out of memory\n");
return 1;
}
MyImage.CombineComponents
(Pixels);
gwImage
MyImage("mypicfile.jp2");
double BrightestGreen;
MyImage.GetMinMax(NULL,&BrightestGreen,1);
// Create an image
from a pic file but with 1 extra component for alpha
gwImage
Pic1("MyColorPic.JPG",1);
// make the fourth component an alpha channel which
causes dark
// areas in the original picture to be transparent
Pic1.MathMergComponents
(
4,
-30, // grayscale mags below
30 are transparent, above 30 opaque
1000000, // we want alpha
values of pretty much only 0 or 1
);
| Function Name: | Time to execute on an Athlon 1.7 GHz system (in nanoseconds): | Description: |
| Reset | 20 | Overrides all settings in the matrix and sets it so that it describes no difference from the parent's coordinate system. |
| ResetNoPosition | 10 | Resets the scale, shear, and rotation elements, but leaves the position alone. |
| CopyNoPosition | 20 | Overwrites the current scale, shear, and rotate attributes with those of the specified matrix, but leaves the position elements alone. |
| GetPosition | 10 | Returns the current position relative to the parent's coordinate system. |
| GetScale | 10 | Returns the values of the scale elements. These are meaningful only if there is no rotation . |
| GetShear | 30 | Returns the values of the shear elements. These are meaningful only if there is no rotation. |
| GetRotation | 770 to 1100 | Returns the Euler angles ( roll, pitch, and yaw ) describing the rotation relative to the parent. |
| GetXAxis | 10 | Returns the current X-axis relative to the parent's coordinate system. |
| GetYAxis | 10 | Returns the current Y-axis relative to the parent's coordinate system. |
| GetZAxis | 10 | Returns the current Z-axis relative to the parent's coordinate system. |
| GetXAxisWith | 10 | Returns the current transpose X-axis. |
| GetYAxisWith | 10 | Returns the current transpose Y-axis. |
| GetZAxisWith | 10 | Returns the current transpose Z-axis. |
| GetXAxisWith | 10 | Returns the current transpose X-axis. |
| SetXAxis | 20 | Writes the X-axis vector |
| SetYAxis | 20 | Writes the Y-axis vector |
| SetZAxis | 20 | Writes the Z-axis vector |
| SetXAxisWith | 20 | Writes the X transpose axis vector |
| SetYAxisWith | 20 | Writes the Y transpose axis vector |
| SetZAxisWith | 20 | Writes the Z transpose axis vector |
| SetPosition | 20 | Overwrites the matrix elements that describe position relative to the parent. Writing these does not affect the current settings for shear, rotate, or scale. |
| SetScale | 20 | Overwrites the matrix elements that describe scale. Writing these will have an adverse effect on any current non-zero rotation setting. |
| SetShear | 30 | Overwrites the matrix elements that describe shear. Writing these will have an adverse effect on any current non-zero rotation setting. |
| SetRotation | 270 to 530 | Overwrites the matrix elements that describe rotation. Writing these will override any current scale and shear setting, such that there is no scaling or shearing. |
| ModifyPosition | 270 to 530 | Modifies the position relative to the matrix 's current coordinate system. |
| ModifyScale | 120 to 210 | Modifies the scale relative to the matrix 's current coordinate system. |
| ModifyShear | 140 to 240 | Modifies the shear relative to the matrix 's current coordinate system. |
| ModifyRotation | 390 to 660 | Modifies the rotation relative to the matrix 's current coordinate system. Note:Roll is applied before pitch and yaw with this function. To implement true relative roll, first rotate the matrix with pitch and yaw specified, then call ModifyRotation with the roll value by itself. |
| ModifyWithPosition | 30 | Modifies the current position relative to the parent's coordinate system. |
| ModifyWithScale | 270 to 520 | Modifies the current scale relative to the parent's coordinate system. |
| ModifyWithShear | 240 to 500 | Modifies the current shear relative to the parent's coordinate system. |
| ModifyWithRotation | 530 to 800 | Modifies the current rotation relative to the parent's coordinate system. |
| ModifyWithScaleNoPosition | 160 to 420 | Modifies the current scale relative to the parent's coordinate system. Leaves alone the elements that define position. |
| ModifyWithShearNoPosition | 190 to 370 | Modifies the current shear relative to the parent's coordinate system. Leaves alone the elements that define position. |
| ModifyWithRotationNoPosition | 420 to 690 | Modifies the current rotation relative to the parent's coordinate system. Leaves alone the elements that define position. |
| Rotate | Not measured yet | Rotates around the specified vector. |
| Transpose | Not measured yet | Swaps values of rows and columns |
| TransposeNoPosition | Not measured yet | Swaps values of rows and columns for the first three rows/columns |
| FromQuaternion | Not measured yet | Alters the 3x3 elements given a quaternion |
| operator* | 160 to 260 | Multiplies the left matrix by the right matrix and returns the result. |
| operator*= | 200 to 320 | Multiplies the matrix by another matrix. Specifically, this causes the matrix to be altered relative to its current coordinate system according to the specified matrix. |
| MultiplyWith | 210 to 310 | Multiplies another matrix by this matrix and writes the result to this matrix. Specifically, this causes the matrix to be altered relative to the parent's coordinate system according to the specified matrix. |
| MultiplyNoPosition | 80 to 90 | Same as operator* except leaves position elements alone. |
| MultiplyWithNoPosition | 130 to 240 | Same as MultiplyWith except leaves position elements alone. |
static gwSprite
MySprite("MyVrmlFile");
MySprite.Reset();
MySprite.SetPosition(...)
// we can use SetScale
instead of ModifyScale
because
// the current rotation
is zero
MySprite.SetScale(...)
// we can use SetShear
instead of ModifyShear
because
// the current rotation
is zero
MySprite.SetShear(...)
// We can't use SetRotation
because it would override
// the previous scale
& shear
settings, so we have to
// use ModifyRotation,
instead.
MySprite.ModifyRotation(...)
// set sprite's starting position once,
and change it a
little each frame
// (this code would be in the gwWindow's
PeriodicFunction or WM_TIMER handler)
static gwSprite
MySprite("MyVrmlFile");
static int FirstFrame=1;
if(FirstFrame)
{
FirstFrame=0;
MySprite.Reset();
MySprite.SetPosition(12,-80,17);
}
MySprite.ModifyPosition
(0,2,3);
// Create a sprite
static gwSprite
MySprite("MyVrmlFile");
// and create a matrix
to multiply with the sprite:
static gwMatrix
MyRotMatrix;
static int FirstFrame=1;
if(FirstFrame)
{
// position the sprite once in
the initialization code
MySprite.SetPosition(...);
MySprite.SetRotation
(...);
// and set the rotation
of the modifying matrix
MyRotMatrix.SetRotation
(73,10,32);
}
// now, in the periodic frame
update code, rotate the sprite by multiplying
// it with the rotation
matrix:
MySprite*=MyRotMatrix;
e13=6.2; // fastest
a[7]=6.2; // slow
e[1][3]=6.2; // slower
gwMatrix
NewMatrix = OrigMatrix;
NewMatrix.ModifyRotation
(0,0,90);
NewMatrix.GetRotation
(* Yaw, * Pitch , * Roll
);
gwSprite
MySprite("MyVrmlFile");
MySprite.Texture.Load("myimage.jpg");
gwTexture
MyTex1("tex1.jpg");
gwTexture MyTex2("tex2.jpg");
gwSprite
MySprite("MyVrmlFile");
...
MySprite.Texture
=Tex1;
...
// dynamically change the sprite's texture
MySprite.Texture=Tex2;