/******************************************************************************
file: main.cpp
created: 12.4.2004
******************************************************************************/
#include <Windows.h>
#include <Opcode.h>
#include "box.h"
// Prototypes:
bool collide( Box *box1, Box *box2 );
bool SaveAsBitmap( char *szFile, BYTE **array, int width, int height );
// Global Vars
const int nHind = 10; // Anzahl der Hindernisse
const int nRob = 1; // Anzahl der Roboterglieder
int nTests = 0;
Box aHindernis[nHind]; // Unsere Hindernise
Box aRoboter[nRob]; // Roboterteile
int setCellColisionIndex(int width, int height, BYTE ** cspace){
for (int j = 0; j < nHind; j++){
bool isCollided = collide(&aRoboter[0], &aHindernis[j]);
nTests++;
if (isCollided){
cspace[width][height] = j + 1;
return j + 1;
}
}
return 0;
}
/*
* main
*/
int main( )
{
// Breite und Höhe des Konfigurationsraumes
int width = 1000;
int height = 1000;
int x, y = 0;
// Konfigurationsraum initialisieren ( Dynamische Größe )
// gleiche wie cpace[height][width]
BYTE **cspace = new BYTE*[width];
for ( x=0; x<width; x++ )
{
cspace[x] = new BYTE[height];
for ( y = 0; y<height; y++ )
cspace[x][y] = 0;
}
// Hindernisse initialisieren
// Hierbei wird für jedes Hinderniss die Größe ( Skalierung ) und
// die Position im Raum gesetzt
aHindernis[0].Scale( 0.30f, 0.05f, 0.10f ); // QUADER1 0.30000 0.05000 0.10000
aHindernis[0].Translate( -0.7f, -0.4f, 0.0f ); // REFPOS -0.7000000 -0.4000000 0.0000000 0.0000000 0.0000000 0.0000000
aHindernis[1].Scale( 0.05f, 0.60f, 0.10f ); // QUADER2 0.05000 0.60000 0.10000
aHindernis[1].Translate( -0.25f, -0.30f, 0.0f );// REFPOS -0.2500000 -0.3000000 0.0000000 0.0000000 0.0000000 0.0000000
aHindernis[2].Scale( 0.25f, 0.05f, 0.10f ); // QUADER3 0.25000 0.05000 0.10000
aHindernis[2].Translate( -0.2f, 0.45f, 0.0f ); // REFPOS -0.2000000 0.4500000 0.0000000 0.0000000 0.0000000 0.0000000
aHindernis[3].Scale( 0.55f, 0.05f, 0.10f ); // QUADER4 0.55000 0.05000 0.10000
aHindernis[3].Translate( -0.15f, -0.25f, 0.0f );// REFPOS -0.1500000 -0.2500000 0.0000000 0.0000000 0.0000000 0.0000000
aHindernis[4].Scale( 0.1f, 0.05f, 0.10f ); // QUADER5 0.10000 0.05000 0.10000
aHindernis[4].Translate( -0.05f, 0.20f, 0.0f ); // REFPOS -0.0500000 0.2000000 0.0000000 0.0000000 0.0000000 0.0000000
aHindernis[5].Scale( 0.05f, 0.2f, 0.10f ); // QUADER6 0.05000 0.20000 0.10000
aHindernis[5].Translate( 0.05f, -0.6f, 0.0f ); // REFPOS 0.0500000 -0.6000000 0.0000000 0.0000000 0.0000000 0.0000000
aHindernis[6].Scale( 0.05f, 0.25f, 0.10f ); // QUADER7 0.05000 0.25000 0.10000
aHindernis[6].Translate( 0.25f, 0.25f, 0.0f ); // REFPOS 0.2500000 0.2500000 0.0000000 0.0000000 0.0000000 0.0000000
aHindernis[7].Scale( 0.05f, 0.25f, 0.10f ); // QUADER8 0.05000 0.25000 0.10000
aHindernis[7].Translate( 0.35f, -0.5f, 0.0f ); // REFPOS 0.3500000 -0.5000000 0.0000000 0.0000000 0.0000000 0.0000000
aHindernis[8].Scale( 0.2f, 0.05f, 0.10f ); // QUADER9 0.20000 0.05000 0.10000
aHindernis[8].Translate( 0.45f, 0.15f, 0.0f ); // REFPOS 0.4500000 0.1500000 0.0000000 0.0000000 0.0000000 0.0000000
aHindernis[9].Scale( 0.05f, 0.3f, 0.1f ); // QUADER10 0.05000 0.30000 0.10000
aHindernis[9].Translate( 0.2f, -0.15f, 0.0f ); // REFPOS 0.2000000 -0.1500000 0.0000000 0.0000000 0.0000000 0.0000000
// Roboterglieder initialisieren
aRoboter[0].Scale( 0.07f, 0.07f, 0.20f ); // QUADER 0.07000 0.07000 0.20000
aRoboter[0].Translate( -0.05f, -0.05f, 0.0f ); // REFPOS -0.0500000 -0.0500000 0.0000000 0.0000000 0.0000000 0.0000000
// Startzeit
DWORD dwStart = GetTickCount();
printf("Starting the Calculation...\n");
// Konfigurationsraum aufbauen
// Ihr Code ...
int cellCount = width * height;
for (int i = 0; i < cellCount; i++){
int cWidth = i % width;
int cHeight = (int)(i / width);
float xIndex = cWidth - (width / 2);
float yIndex = cHeight - (height / 2);
aRoboter[0].Translate(xIndex / 1000, yIndex / 1000, 0.0f);
setCellColisionIndex(cWidth, cHeight, cspace);
}
// Zeit für das Aufstellen des Konfigurationsraumes ausgeben ( in ms )
DWORD dwElapsed = GetTickCount() - dwStart;
printf( "\nBerechnung dauerte %d ms\n", dwElapsed );
printf( "Anzahl Kollisionstests: %d\n", nTests ); // Anzahl Kollitionstests
// Konfigurationsraum als Bitmap speichern
SaveAsBitmap( "cspace_prismatic.bmp", cspace, width, height );
system("pause");
return 0;
}
/*
* collide
* Diese Funktion prüft ob die zwei Objekte, box1 und box2 kollidieren
* Wenn sie kollidieren, wird true zurückgegeben, sonst false
*/
bool collide( Box *box1, Box *box2 )
{
// Build a quantized no-leaf tree
Opcode::AABBTreeCollider TC;
Opcode::BVTCache ColCache;
// Create a tree collider and setup it:
TC.SetFirstContact(true);
TC.SetFullBoxBoxTest(false); // use coarse BV-BV tests
TC.SetFullPrimBoxTest(false); // use coarse primitive-BV tests
TC.SetTemporalCoherence(false); // don't use temporal coherence
// Setup BVTCache
ColCache.Model0 = &box1->m_OpModel;
ColCache.Model1 = &box2->m_OpModel;
// Collision query
bool IsOk = TC.Collide( ColCache, &box1->m_Matrix, &box2->m_Matrix );
// Get collision status => if true, objects overlap
bool Status = TC.GetContactStatus() != FALSE;
return Status;
}
/*
* SaveAsBitmap
* Speichert den Konfigurationsraum als Bitmap.
* Parameter:
* szFile - Dateiname
* array - Das 2D Array mit dem Konfigurationsraum
* width - Breite des Konfigurationsraum
* height - Höhe des Konfigrationsraum
*/
bool SaveAsBitmap( char *szFile, BYTE **array, int width, int height )
{
BITMAPFILEHEADER bmpFileHeader;
bmpFileHeader.bfType = *((int*)("BM")); // Muss BM sein
bmpFileHeader.bfSize = 0; // Größe der Bitmap Datei
bmpFileHeader.bfReserved1 = 0; // Muss 0 sein
bmpFileHeader.bfReserved2 = 0; // Muss 0 sein
bmpFileHeader.bfOffBits = 0; // Offset, in Bytes, zwischen BITMAPFILEHEADE und den Bits
BITMAPINFOHEADER bmpInfoHeader;
bmpInfoHeader.biSize = sizeof( BITMAPINFOHEADER );
bmpInfoHeader.biWidth = width;
bmpInfoHeader.biHeight = height;
bmpInfoHeader.biPlanes = 1;
bmpInfoHeader.biBitCount = 8;
bmpInfoHeader.biCompression = BI_RGB;
bmpInfoHeader.biSizeImage = width * height * 1;
bmpInfoHeader.biXPelsPerMeter = 2834;
bmpInfoHeader.biYPelsPerMeter = 2834;
bmpInfoHeader.biClrUsed = 256;
bmpInfoHeader.biClrImportant = 256;
FILE *pFile = fopen( szFile, "wb" );
if ( pFile == NULL )
{
printf( "Konnte Datei '%s' nicht erzeugen.\n", szFile );
return false;
}
fwrite( &bmpFileHeader, sizeof( BITMAPFILEHEADER ), 1, pFile );
fwrite( &bmpInfoHeader, sizeof( BITMAPINFOHEADER ), 1, pFile );
// Farbpalette zum Bild hinzufügen
static RGBQUAD colortable[] =
{
// B G R 0
{ 255, 255, 255, 0},
{ 0, 0, 255, 0}, // Rot
{ 0, 255, 0, 0}, // Grün
{ 255, 0, 0, 0}, // Blau
{ 0, 255, 255, 0}, // Gelb
{ 255, 0, 255, 0}, // Magenta
{ 255, 255, 0, 0}, // Cyan
{ 0, 128, 255, 0}, // Oragne
{ 255, 0, 128, 0}, // Weinrot
{ 128, 255, 0, 0}, // Hell Grün
{ 0, 255, 128, 0} // Gift Grün
// Wenn die Farben nicht reichen, hier neue hinzufügen
};
int nCol = sizeof(colortable) / sizeof(RGBQUAD);
fwrite( colortable, sizeof(RGBQUAD), sizeof(colortable), pFile );
// Alle restlichen Farben auf Schwarz setzen
for ( int i=nCol; i<256; i++ )
{
RGBQUAD rgb;
rgb.rgbRed = 0;
rgb.rgbGreen = 0;
rgb.rgbBlue = 0;
rgb.rgbReserved = 0;
fwrite( &rgb, sizeof( RGBQUAD), 1, pFile );
}
// Bits schreiben
bmpFileHeader.bfOffBits = ftell( pFile );
for ( int y=height-1; y>=0; y-- )
{
for ( int x=0; x<width; x++ )
{
putc( array[x][y], pFile );
}
}
bmpFileHeader.bfSize = ftell( pFile );
// File Header nochmal mit neuen Werten überschreiben
fseek( pFile, 0L, SEEK_SET );
fwrite( &bmpFileHeader, sizeof( BITMAPFILEHEADER ), 1, pFile );
fclose( pFile );
return true;
}