Flat functions |
exitfunc | void exitfunc() |
SelectTrack | void SelectTrack(cstring name) |
GetIndex | static int GetIndex(cstring text,int maxIndex) Request an index between 0 and maxIndex Returns -1 if the action was cancelled. |
SetupMenus | void SetupMenus() |
apperr | void apperr(string s) |
cbProgress | static bool cbProgress(int cur,int total,cstring text) |
LoadTrack | void LoadTrack() |
SaveTrack | void SaveTrack() |
event | bool event(QEvent *e) |
DbgPrj | void DbgPrj(cstring s) |
SetupViewport | void SetupViewport(int w,int h) |
DbgPrj | DbgPrj("SetupViewport"); #ifdef OBS matPrj.DbgPrint("Projection"); qdbg("glCtx: %p\n",glXGetCurrentContext()); #endif #ifdef OBS float d=1000.0f; glFrustum(-w/d/2,w/d/2,-h/d/2,h/d/2,1,100000); #endif glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //glTranslatef(0,0,-d); fSetup=TRUE; } |
GGetDrawable | QDraw *GGetDrawable() |
GGetCV | QCanvas *GGetCV() |
GSwap | void GSwap() |
SetGLColor | static void SetGLColor(QColor *color) Local function to convert rgba to float |
PaintRope | static void PaintRope(DVector3 *v1,DVector3 *v2,QColor *col) Paint rope with poles |
PaintTrack | void PaintTrack(int flags) Paint the entire track flags&1; output on debug the timing results |
glShadeModel | glShadeModel(GL_FLAT); glDisable(GL_LIGHTING); glDisable(GL_CULL_FACE); glDisable(GL_NORMALIZE); glDisable(GL_DEPTH_TEST); #endif |
glDisable | glDisable(GL_LIGHTING); glDisable(GL_CULL_FACE); lDisable(GL_DEPTH_TEST); glDisable(GL_TEXTURE_2D); endif glColor3f(1,1,1); glBegin(GL_LINES); glVertex3f(vPick.x,vPick.y,vPick.z); glVertex3f(vPick.x,vPick.y+1.0f,vPick.z); glColor3f(1,1,0); glVertex3f(vPickEnd.x,vPickEnd.y,vPickEnd.z); glVertex3f(vPickEnd.x,vPickEnd.y+1.0f,vPickEnd.z); // Connect the two glColor3f(1,1,.5); glVertex3f(vPick.x,vPick.y+1.0f,vPick.z); glVertex3f(vPickEnd.x,vPickEnd.y+1.0f,vPickEnd.z); glEnd(); } t[2]=tmr->GetMilliSeconds(); // 2D stats; remember matrices for picking glMatrixMode(GL_PROJECTION); glPushMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); // Stats fps->FrameRendered(); x=20; y=20; QCV->Set2D(); QCV->SetColor(255,255,255); QCV->SetFont(app->GetSystemFont()); sprintf(buf,"FPS: %.2f",fps->GetFPS()); QCV->Text(buf,x,y); y+=20; if(flags&1)qdbg(" t1: %d ms\n",t[1]); PROFILE(RProfile::PROF_SWAP); GSwap(); |
idlefunc | void idlefunc() |
Setup | void Setup() |
Run | void Run() |
/*
* TrackEd - editor for VRML-type tracks
* 12-11-00: Created!
* NOTES:
* (C) MarketGraph/RvG
*/
#include "main.h"
#pragma hdrstop
#ifdef WIN32
#include <direct.h>
#include <stdlib.h>
#include <stdio.h>
#endif
#include <d3/fps.h>
#include <d3/global.h>
#include <qlib/debug.h>
DEBUG_ENABLE
#define APP_TITLE "Racer TrackEd v1.2"
#define DRW Q_BC
#define CAR_FNAME "data/cars/devtest/car.ini"
#define CONTROLS_FILE "controls.ini"
#define DEBUG_INI "debug.ini"
// Use infinite grid? (throws car back in place when too far out of line)
//#define USE_INF_GRID
#define PROFILE(n)
// Maximum time to emulate per gfx frame
// If this limit would not exist, you could get a frequency of
// simulation that will NEVER draw a frame. (seems like it crashes)
// However, IF this limit is exceeded, slomo will occur. On the other
// hand, it will run at such a low framerate you will not play it at all.
#define MAX_SIMTIME_PER_FRAME 1000
QTimer *tmr;
// Debugging
RDebugInfo *rdbg;
// Controller info
int ctlSteer;
int ctlThrottle;
int ctlBrakes;
// TrackEd vars
// GUI
QTitleBar *title;
// Menu
enum { MAX_IO=3 };
cstring ioName[MAX_IO]={ "Select track","Load track","Save track" };
QButton *butIO[MAX_IO];
enum { MAX_MODIFY=6 };
cstring modifyName[MAX_MODIFY]=
{ "Convert SCGT wrl's","(I)mport DOF models",
// Line operations
"Goto line start","Declare grid pos","Declare pits pos",
"Declare timeline"
};
QButton *butModify[MAX_MODIFY];
// Graphics
DGlobal dglobal;
DGeode *model;
RTrackVRML *track;
DFPS *fps;
static DTransformation aTF,*tf;
bool fFog=TRUE;
// Picking
DVector3 vPick,vPickEnd;
// Errors
QMessageHandler defQErr;
cstring sError="Error";
void exitfunc()
{
int i;
for(i=0;i<MAX_IO;i++)delete butIO[i];
for(i=0;i<MAX_MODIFY;i++)delete butModify[i];
//if(rJoy)delete rJoy;
if(RMGR)delete RMGR;
if(model)delete model;
if(track)delete track;
delete info;
}
/**********
* Helpers *
**********/
void SelectTrack(cstring name)
{
char buf[256];
qdbg("SelecTrack(%s)\n",name);
track->SetName(name);
sprintf(buf,"%s - %s",APP_TITLE,name);
title->SetTitle(buf);
}
static int GetIndex(cstring text,int maxIndex)
// Request an index between 0 and maxIndex
// Returns -1 if the action was cancelled.
{
char buf[256],buf2[128];
int n;
sprintf(buf,"%s (0..%d)",text,maxIndex);
sprintf(buf2,"%d",maxIndex);
retry:
if(!QDlgString("Enter an index",buf,buf2,sizeof(buf2)))
return -1;
n=atoi(buf2);
if(n<0||n>maxIndex)
{
if(!QMessageBox("Error","Value out of range."))
return -1;
else goto retry;
}
return n;
}
/********
* MENUS *
********/
void SetupMenus()
{
QRect r;
int i;
// IO
r.x=Q_BC->GetX()-2; r.y=Q_BC->GetHeight()+Q_BC->GetY()+10;
r.wid=150; r.hgt=35;
for(i=0;i<MAX_IO;i++)
{
butIO[i]=new QButton(QSHELL,&r,ioName[i]);
r.x+=r.wid+10;
}
// Modify
r.x=Q_BC->GetX()+Q_BC->GetWidth()+10; r.y=Q_BC->GetY()-2;
for(i=0;i<MAX_MODIFY;i++)
{
butModify[i]=new QButton(QSHELL,&r,modifyName[i]);
r.y+=r.hgt+10;
// Seperators
if(i==1)
{
// Line ops coming up
new QLabel(QSHELL,&r,"Line operations");
r.y+=30;
}
}
}
/*********
* ERRORS *
*********/
void apperr(string s)
{
qdbg("Error '%s'\n",s);
QMessageBox("Error",s);
if(defQErr)defQErr(s);
}
/******
* I/O *
******/
static QProgressDialog *dlgProgress;
static bool cbProgress(int cur,int total,cstring text)
{
dlgProgress->SetProgressText(text);
dlgProgress->SetProgress(cur,total);
return dlgProgress->Poll();
}
void LoadTrack()
{
QRect r(100,100,400,150);
dlgProgress=new QProgressDialog(QSHELL,&r,"Loading","Loading models.");
//QProgressDialog::NO_CANCEL);
dlgProgress->Create();
track->SetLoadCallback(cbProgress);
if(!track->Load())
QMessageBox(sError,"Can't load track!");
track->SetLoadCallback(0);
delete dlgProgress; dlgProgress=0;
}
void SaveTrack()
{
QRect r(100,100,400,100);
dlgProgress=new QProgressDialog(QSHELL,&r,"Saving",
"Saving track definition.",QProgressDialog::NO_CANCEL);
dlgProgress->Create();
if(!track->Save())
QMessageBox(sError,"Can't load track!");
delete dlgProgress; dlgProgress=0;
}
/*********
* EVENTS *
*********/
bool event(QEvent *e)
{
int gear,n;
PROFILE(RProfile::PROF_EVENTS);
static int drag,dragX,dragY;
#ifdef OBS
if(model)tf=model->GetTransformation();
else tf=0;
#endif
if(e->type==QEvent::BUTTONPRESS)
{
//if(!drag)
if(e->win==Q_BC)
{ drag|=(1<<(e->n-1));
dragX=e->x; dragY=e->y;
if(e->n==1)
{
PickTest(e->x,DRW->GetHeight()-e->y,tf,&vPick);
vPickEnd=vPick;
}
}
} else if(e->type==QEvent::BUTTONRELEASE)
{
drag&=~(1<<(e->n-1));
} else if(e->type==QEvent::MOTIONNOTIFY)
{
if(!tf)return FALSE;
// 2 mouse button version
if((drag&(1|4))==(1|4))
{ tf->x+=(e->x-dragX)*400./720.;
tf->y-=(e->y-dragY)*400./576.;
} else if(drag&1)
{
// if(mode==PICK)
PickTest(e->x,DRW->GetHeight()-e->y,tf,&vPickEnd);
// else if(mode==CAMERA)
// { tf->xa+=((float)(e->y-dragY))*300./576.;
// tf->ya+=((float)(e->x-dragX))*300./720.;
// }
} else if(drag&4)
{
// Rotate camera
tf->xa+=((float)(e->y-dragY))*300./576.;
tf->ya+=((float)(e->x-dragX))*300./720.;
//tf->za+=(e->y-dragY)*300./576.;
//tf->z+=(e->x-dragX);
}
dragX=e->x; dragY=e->y;
#ifdef OBS
qdbg("Camera location=(%.2f,%.2f,%.2f)\n",tf->x,tf->y,tf->z);
qdbg(" direction=(%.2f,%.2f,%.2f)\n",tf->xa,tf->ya,tf->za);
#endif
return TRUE;
}
if(e->type==QEvent::CLICK)
{
if(e->win==butIO[0])
{
// SelectTrack();
} else if(e->win==butIO[1])
{
LoadTrack();
} else if(e->win==butIO[2])
{
SaveTrack();
} else if(e->win==butModify[0])
{
ConvertSCGTwrl();
} else if(e->win==butModify[1])
{
ImportDOFs();
} else if(e->win==butModify[2])
{
// Goto start pos
tf->x=vPick.x;
tf->y=vPick.y;
tf->z=vPick.z;
// Float above the pick point
tf->y+=4.0f;
} else if(e->win==butModify[3])
{
// Declare grid position
n=GetIndex("Select grid position index",
track->GetGridPosCount()<RTrackVRML::MAX_GRID_POS?
track->GetGridPosCount():RTrackVRML::MAX_GRID_POS-1);
if(n!=-1)
{
RCarPos *pos;
pos=&track->gridPos[n]; //GetGridPos(n);
pos->from=vPick;
pos->to=vPickEnd;
if(n==track->GetGridPosCount())track->gridPosCount++;
}
} else if(e->win==butModify[4])
{
// Declare pit position
n=GetIndex("Select pit position index",
track->GetPitPosCount()<RTrackVRML::MAX_GRID_POS?
track->GetPitPosCount():RTrackVRML::MAX_GRID_POS-1);
if(n!=-1)
{
RCarPos *pos;
pos=&track->pitPos[n]; //GetPitPos(n);
pos->from=vPick;
pos->to=vPickEnd;
if(n==track->GetPitPosCount())track->pitPosCount++;
}
} else if(e->win==butModify[5])
{
// Declare time line
n=GetIndex("Select timeline index",
track->GetTimeLines()<RTrackVRML::MAX_GRID_POS?
track->GetTimeLines():RTrackVRML::MAX_GRID_POS-1);
if(n!=-1)
{
if(n<track->GetTimeLines())
{ delete track->GetTimeLine(n);
} else track->timeLines++;
// Install new timeline
track->timeLine[n]=new RTimeLine(&vPick,&vPickEnd);
#ifdef OBS
RTimeLine *tl;
tl=track->timeLine[n]; //GetTimeLine(n);
tl->from=vPick;
tl->to=vPickEnd;
#endif
//if(n==track->GetTimeLines())track->timeLines++;
}
}
}
if(e->type==QEvent::MOTIONNOTIFY)
{
//MapXYtoCtl(e->x,e->y);
} else if(e->type==QEvent::KEYPRESS)
{
if(e->n==QK_ESC)
app->Exit(0);
else
if(e->n==QK_I)
{ ImportDOFs();
} else if(e->n==QK_S)
{
// Start position
tf->x=tf->y=tf->z=0;
tf->xa=tf->ya=tf->za=0;
//tf->xa=15;
tf->y=1.0f;
//tf->ya=-90;
}
}
// Return to other stuff
PROFILE(RProfile::PROF_OTHER);
return FALSE;
}
/***********
* Painting *
***********/
void DbgPrj(cstring s)
{
DMatrix4 matPrj;
glGetFloatv(GL_PROJECTION_MATRIX,matPrj.GetM());
matPrj.DbgPrint(s);
//qdbg("glCtx: %p\n",glXGetCurrentContext());
}
void SetupViewport(int w,int h)
{
static bool fSetup=FALSE;
static DMatrix4 matPrj;
if(fSetup)
{
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(matPrj.GetM());
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
return;
}
// Calculate projection
//qdbg("w=%d, h=%d\n",w,h);
//glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(50.0,(GLfloat)w/(GLfloat)h,1.0,
info->GetFloat("gfx.visibility",300.f));
// Remember for later faster projection
glGetFloatv(GL_PROJECTION_MATRIX,matPrj.GetM());
DbgPrj("SetupViewport");
#ifdef OBS
matPrj.DbgPrint("Projection");
qdbg("glCtx: %p\n",glXGetCurrentContext());
#endif
#ifdef OBS
float d=1000.0f;
glFrustum(-w/d/2,w/d/2,-h/d/2,h/d/2,1,100000);
#endif
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//glTranslatef(0,0,-d);
fSetup=TRUE;
}
QDraw *GGetDrawable()
{
return DRW;
}
QCanvas *GGetCV()
{
return DRW->GetCanvas();
}
void GSwap()
{ DRW->Swap();
}
#ifdef OBS
static void SetGLColor(QColor *color)
// Local function to convert rgba to float
{
GLfloat cr,cg,cb,ca;
cr=(GLfloat)color->GetR()/255;
cg=(GLfloat)color->GetG()/255;
cb=(GLfloat)color->GetB()/255;
ca=(GLfloat)color->GetA()/255;
glColor4f(cr,cg,cb,ca);
}
#endif
#ifdef OBS
static void PaintRope(DVector3 *v1,DVector3 *v2,QColor *col)
// Paint rope with poles
{
SetGLColor(col);
glBegin(GL_LINES);
// Both
glVertex3f(v1->x,v1->y,v1->z);
glVertex3f(v1->x,v1->y+1,v1->z);
glVertex3f(v2->x,v2->y,v2->z);
glVertex3f(v2->x,v2->y+1,v2->z);
// Connection
glVertex3f(v1->x,v1->y+1,v1->z);
glVertex3f(v2->x,v2->y+1,v2->z);
glEnd();
}
#endif
void PaintTrack(int flags)
// Paint the entire track
// flags&1; output on debug the timing results
{
QVector3 *v;
static QTimer *tmr;
int t[10];
int i,x,y;
char buf[256];
if(!tmr)tmr=new QTimer();
tmr->Reset();
tmr->Start();
GGetCV()->Select();
GGetCV()->Enable(QCanvas::IS3D);
SetupViewport(DRW->GetWidth(),DRW->GetHeight());
t[0]=tmr->GetMilliSeconds();
// Fog
if(fFog)
{
GLfloat density;
GLfloat fogColor[4]={ 0.5,0.5,0.5,1.0 };
glEnable(GL_FOG);
glFogi(GL_FOG_MODE,GL_LINEAR);
glFogfv(GL_FOG_COLOR,fogColor);
glFogf(GL_FOG_DENSITY,0.35);
glFogf(GL_FOG_END,300.0f);
glHint(GL_FOG_HINT,GL_DONT_CARE);
glClearColor(.5,.5,.5,0);
} else
{
glClearColor(51.f/255.f,93.f/255.f,165.f/255.f,0);
}
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//glClear(GL_DEPTH_BUFFER_BIT);
#ifdef ND_DEV
glEnable(GL_CULL_FACE);
//glCullFace(GL_FRONT);
//glFrontFace(GL_CW);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
float lightDir[3]={ 0,-.1,-1 };
float lightPos[4]={ 1,1,1,0 };
//glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,lightDir);
glEnable(GL_DEPTH_TEST);
//glShadeModel(GL_FLAT);
glShadeModel(GL_SMOOTH);
// Camera
//Camera();
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
//glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,lightDir);
#endif
#ifdef OBS
// Speed test
glShadeModel(GL_FLAT);
glDisable(GL_LIGHTING);
glDisable(GL_CULL_FACE);
glDisable(GL_NORMALIZE);
glDisable(GL_DEPTH_TEST);
#endif
t[1]=tmr->GetMilliSeconds();
// Paint track
if(track)
{
// Camera is negated, angles should be negative
glRotatef(tf->za,0,0,1);
glRotatef(tf->xa,1,0,0);
glRotatef(tf->ya,0,1,0);
glTranslatef(-tf->x,-tf->y,-tf->z);
track->GetCuller()->CalcFrustumEquations();
track->Paint();
track->PaintHidden();
// Paint pick vectors
//#ifdef OBS
glDisable(GL_LIGHTING);
glDisable(GL_CULL_FACE);
//glDisable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
//#endif
glColor3f(1,1,1);
glBegin(GL_LINES);
glVertex3f(vPick.x,vPick.y,vPick.z);
glVertex3f(vPick.x,vPick.y+1.0f,vPick.z);
glColor3f(1,1,0);
glVertex3f(vPickEnd.x,vPickEnd.y,vPickEnd.z);
glVertex3f(vPickEnd.x,vPickEnd.y+1.0f,vPickEnd.z);
// Connect the two
glColor3f(1,1,.5);
glVertex3f(vPick.x,vPick.y+1.0f,vPick.z);
glVertex3f(vPickEnd.x,vPickEnd.y+1.0f,vPickEnd.z);
glEnd();
}
t[2]=tmr->GetMilliSeconds();
// 2D stats; remember matrices for picking
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
// Stats
fps->FrameRendered();
x=20; y=20;
QCV->Set2D();
QCV->SetColor(255,255,255);
QCV->SetFont(app->GetSystemFont());
sprintf(buf,"FPS: %.2f",fps->GetFPS());
QCV->Text(buf,x,y); y+=20;
if(flags&1)qdbg(" t1: %d ms\n",t[1]);
PROFILE(RProfile::PROF_SWAP);
GSwap();
PROFILE(RProfile::PROF_OTHER);
// Restore matrices
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
//DbgPrj("PaintTrack1");
}
void idlefunc()
{
PaintTrack();
}
void Setup()
{
float v;
// D3
// Use texture pool to save image memory
dglobal.flags|=DGlobal::USE_TEXTURE_POOL;
// GUI
title=new QTitleBar(QSHELL,APP_TITLE);
defQErr=QSetErrorHandler(apperr);
// Create a track and use the latest loaded track as its name
track=new RTrackVRML();
SelectTrack(info->GetStringDirect("track.lasttrack"));
// Track FPS
fps=new DFPS();
fFog=info->GetInt("gfx.fog");
// Setup transformation
tf=&aTF;
// Give it an initial tilt and distance
tf->xa=90;
tf->z=-700;
// Start pos
tf->x=tf->y=tf->z=0;
tf->xa=tf->ya=tf->za=0;
// GUI
SetupMenus();
// Get window up
app->RunPoll();
app->SetIdleProc(idlefunc);
app->SetExitProc(exitfunc);
app->SetEventProc(event);
}
void Run()
{
Setup();
app->Run();
}