Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) HelloTokamakWindows

 

Technical facts

 

 

 

 

 

 

./CppHelloTokamakWindows/SPMath.h

 

#ifndef SP_MATH_INCLUDED_

#define SP_MATH_INCLUDED_

#include "SPStructs.H"


SF3dVector CrossProduct (SF3dVector * u, SF3dVector * v);
SF3dVector TurnVector ( SF3dVector v, SF3dVector angles);
SF3dVector GetTurnedVector(SF3dVector v, SF3dVector ex, SF3dVector ey, SF3dVector ez);
SF3dVector Normalize3dVector( SF3dVector v);


bool PointInTriangle( SF2dVector Point, SF2dVector Triangle[3]);
bool Intersect2dLines ( SF2dVector p1, SF2dVector d1,
SF2dVector p2, SF2dVector d2,
SF2dVector* intersectionPoint);


#endif

 

 

 

 

 

./CppHelloTokamakWindows/SPMath.cpp

 

#include "SPMath.h"
#include <math.h>
#include "SPStructs.h"


#define sqr(x) (x*x)

SF3dVector AddF3dVectors (SF3dVector* u, SF3dVector* v)
{
SF3dVector result;
result.x = u->x + v->x;
result.y = u->y + v->y;
result.z = u->z + v->z;
return result;
}
void AddF3dVectorToVector ( SF3dVector * Dst, SF3dVector * V2)
{
Dst->x += V2->x;
Dst->y += V2->y;
Dst->z += V2->z;
}

GLfloat GetF3dVectorLength( SF3dVector * v)
{
return (GLfloat)(sqrt(sqr(v->x)+sqr(v->y)+sqr(v->z)));
}


SF3dVector Normalize3dVector( SF3dVector v)
{
SF3dVector res;
float l = GetF3dVectorLength(&v);
if (l == 0.0f) return NULL_VECTOR;
res.x = v.x / l;
res.y = v.y / l;
res.z = v.z / l;
return res;
}

SF3dVector CrossProduct (SF3dVector * u, SF3dVector * v)
{
SF3dVector resVector;
resVector.x = u->y*v->z - u->z*v->y;
resVector.y = u->z*v->x - u->x*v->z;
resVector.z = u->x*v->y - u->y*v->x;

return resVector;
}


SF3dVector GetTurnedVector(SF3dVector v, SF3dVector ex, SF3dVector ey, SF3dVector ez)
{
SF3dVector res;
res.x = v.x*ex.x + v.y*ey.x + v.z*ez.x;
res.y = v.x*ex.y + v.y*ey.y + v.z*ez.y;
res.z = v.x*ex.z + v.y*ey.z + v.z*ez.z;

return res;

}


SF3dVector TurnVector(SF3dVector v, SF3dVector angles)
{
/*> ich habe ein Koordinatensystem, das durch die Vektoren ex = (1,0,0),
> ey = (0,1,0) und ez = (0,0,1) definiert ist.
> Ich möchte das gesamte Koordinatensystem um alle 3 Achsen drehen
> (WinkelX, WinkelY, WinkelZ).
> Kann mir bitte jemand sagen, wie dann die Vektoren ex, ey und ez
> aussehen?

Ich weiß natürlich nicht, wieweit Du "vorbelastet" bist, aber ich fang jetzt
einfach mal an.

Wenn man die 3 Einheitsvektoren ex, ey und ez, die eine Basis des |R^3 sind, und
den Anschauungsraum aufspannen, als Spalten einer Matrix betrachtet, dann sieht
das so aus:

1 0 0
0 1 0
0 0 1

Wenn man dieses Koordinatensystem nun im Raum drehen will, so macht man das
genau so, wie von Dir vorgeschlagen, um jede der 3 Achsen separat. Am
leichtesten kann man das mithilfe von Drehmatrizen schreiben:

Das Koordinatensystem sieht nach einer Drehung um die Winkel wX, wY, wZ um die
zugehörigen Achsen wie folgt aus:

( 1 0 0 ) ( 1     0       0    ) ( cos wY  0   sin wY ) ( cos wZ   - sin wZ  0 )
( 0 1 0 )*( 0  cos wX  -sin wX )*( 0       1    0     )*( sin wZ   cos wZ    0 )
( 0 0 1 ) ( 0  sin wX   cos wX ) (-sin wY  0   cos wY ) (  0        0        1 )

Wenn man das ausrechnet, kommt das hier raus:

    [cos(wY) cos(wZ) , -cos(wY) sin(wZ) , sin(wY)]

    [sin(wX) sin(wY) cos(wZ) + cos(wX) sin(wZ) ,
     -sin(wX) sin(wY) sin(wZ) + cos(wX) cos(wZ) ,
-sin(wX) cos(wY)]

    [-cos(wX) sin(wY) cos(wZ) + sin(wX) sin(wZ) ,
     cos(wX) sin(wY) sin(wZ) + sin(wX) cos(wZ) ,
cos(wX) cos(wY)]

In den eckigen Klammern stehn jeweils die Zeilen der Matrix.

Die von Dir gesuchten Vektoren sind die Spalten der Matrix, d.h ex wurde auf

     ( cos(wY) cos(wZ)                            )
X =  ( sin(wX) sin(wY) cos(wZ) + cos(wX) sin(wZ)  )
     ( -cos(wX) sin(wY) cos(wZ) + sin(wX) sin(wZ) )

abgebildet, etc.

P.S. Diese gedrehten Vektoren haben immer noch die Länge 1.

Probe für den Vektor X (mit Maple ;-)

simplify ((cos(wY)*cos(wZ))^2 + (sin(wX)*sin(wY)*cos(wZ)+cos(wX)*sin(wZ))^2 +
> (-cos(wX)*sin(wY)*cos(wZ)+sin(wX)*sin(wZ))^2);

1

OK, paßt!

Viele Grüsse,
Simon*/
SF3dVector ex = F3dVector(1.0f,0.0f,0.0f);
SF3dVector ey = F3dVector(0.0f,1.0f,0.0f);
SF3dVector ez = F3dVector(0.0f,0.0f,1.0f);

//turn ex...
//around z-axis:
ex.x = (float)cos(angles.z*PIdiv180);
ex.y = (float)sin(angles.z*PIdiv180);
//around y-axis:
ex.x *= (float)cos(angles.y*PIdiv180);
ex.z = (float)sin(angles.y*PIdiv180);


//turn ey...
//around x-axis:
ey.y = (float)cos(angles.x*PIdiv180);
ey.z = (float)sin(angles.x*PIdiv180);
//around z-axis:
ey.y *= (float)cos(angles.z*PIdiv180);
ey.x = (float)sin(angles.z*PIdiv180);

//turn ez...
//around x-axis:
ez.z = (float)cos(angles.x*PIdiv180);
ez.y = (float)sin(angles.x*PIdiv180);
//around y-axis:
ez.x = (float)sin(angles.y*PIdiv180);
ez.z *= (float)cos(angles.y*PIdiv180);


//NOT YET COMPLETELY CODED!!
SF3dVector res;
float cosy = (float)cos(angles.y*PIdiv180);
float siny = (float)sin(angles.y*PIdiv180);
res.x = (float)(v.x*cosy + v.z*siny);
res.y = v.y;
res.z = (float)(-v.x*siny + v.z*cosy);

return res;
}


bool PointInTriangle( SF2dVector Point, SF2dVector Triangle[3])
{
SF2dVector t1,t2,t3,a,b,c;
t1 = Triangle[0];t2 = Triangle[1];t3 = Triangle[2];
a = Point-t1; b = t3-t2; c = t2-t1;

float r,s;

s =-(c.x*a.y-c.y*a.x)
/
(b.x*a.y-b.y*a.x);

r = (c.x*a.y+b.x*a.y*s)
/
(a.x*a.y);

bool res = ((r >= 1.0f) && (s >= 0.0f) && (s <= 1.0f));
return res;
}

bool Intersect2dLines ( SF2dVector p1, SF2dVector d1,
SF2dVector p2, SF2dVector d2,
SF2dVector* intersectionPoint)
{
float denominator = ((d2.y*d1.x)-(d2.x*d1.y));
if (denominator == 0.0f) return false;

float s = ((p2.x-p1.x)*d1.y-(p2.y-p1.y)*d1.x)
  /
  denominator;

float r = (p2.x-p1.x+d2.x*s)
  /
  d1.x;

bool res = ((s>0) && (s <= 1.0f) && (r>0) && (r<=1.0f));
if (!res) return false;

intersectionPoint->x = p1.x + d1.x*r;
intersectionPoint->y = p1.y + d1.y*r;


return true;



}

 

 

 

 

 

./CppHelloTokamakWindows/SimpleSample.cpp

 

/**********************************************************************

  Simple Tokamak Sample
  Used the introduce my CTokSim-Class

  December 2005

  This tutorial was written by Philipp Crocoll
  Contact:
philipp.crocoll@web.de
www.codecolony.de

  Every comment would be appreciated.

  If you want to use parts of any code of mine:
let me know and
use it!

**********************************************************************
ESC: exit

CAMERA movement:
w : forwards
s : backwards
a : turn left
d : turn right
x : turn up
y : turn down
v : strafe right
c : strafe left
r : move up
f : move down

***********************************************************************/
#include "stdafx.h"


#include "gl/glut.h"

#include "camera.h"
#include "SimpleTokSim.h"

CCamera Camera;

SimpleTokSim TokSim;

static GLfloat LightPos[] = {-2.0,1.0,3.0,0.0};
static GLfloat LightAmb[] = {0.5f,0.5f,0.5f,1.0f};
static GLfloat LightPos0[] = {-2.0,10.0,3.0,0.0};


///**************************
//* GLUT Callback Functions:

void reshape(int x, int y)
{
//---
//This function is not important for the Tokamak simulation
//---
if (y == 0 || x == 0) return;  //Nothing is visible then, so return

//Set a new projection matrix
glMatrixMode(GL_PROJECTION);  
glLoadIdentity();
//Angle of view:40 degrees
gluPerspective(40.0,(GLdouble)x/(GLdouble)y,1.0f,500.0f);

glMatrixMode(GL_MODELVIEW);
glViewport(0,0,x,y);  //Use the whole window for rendering
}


void Display(void)
{
//---
//This function displays the scene
//---

//init the drawing for OpenGL
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
glLoadIdentity(); //Load a new modelview matrix -> we can apply new transformations

//set the camera position
Camera.Render();

//set the light
glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmb);
glLightfv(GL_LIGHT0, GL_POSITION, LightPos);

//update the tokamak simulation:
TokSim.CalculateNextFrame(0.02f);  //I use a fix time step (1/50 sec) for the examples

//Call the display function of the tokamak-simulation class:
TokSim.Display();

//Finish rendering:
glFlush();
glutSwapBuffers(); //Swap the buffers ->make the result of rendering visible



}
void KeyDown(unsigned char key, int x, int y)
{
//handle the camera movement:
float CamSpeed = 1.0f;
switch (key)
{
case 27: //ESC
PostQuitMessage(0);
break;
case 'a':
Camera.RotateY(5.0);
Display();
break;
case 'd':
Camera.RotateY(-5.0);
Display();
break;
case 'w':
Camera.MoveForward( -CamSpeed ) ;
Display();
break;
case 's':
Camera.MoveForward( CamSpeed ) ;
Display();
break;
case 'x':
Camera.RotateX(5.0);
Display();
break;
case 'y':
Camera.RotateX(-5.0);
Display();
break;
case 'c':
Camera.StrafeRight(-CamSpeed);
Display();
break;
case 'v':
Camera.StrafeRight(CamSpeed);
Display();
break;
case 'f':
Camera.MoveUpward(-CamSpeed);
Display();
break;
case 'r':
Camera.MoveUpward(CamSpeed);
Display();
break;

case 'm':
Camera.RotateZ(-5.0);
Display();
break;
case 'n':
Camera.RotateZ(5.0);
Display();
break;

}
}

void InitGL(int argc, _TCHAR* argv[],char * WindowTitle, int WindowX, int WindowY)
{
//---
//This function is not important for the Tokamak simulation
//---

//Initialize GLUT
glutInit(&argc, argv);
//Lets use doublebuffering, RGB-mode and a depth buffer
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(WindowX,WindowY);
//Create a window with rendering context and everything else we need
glutCreateWindow(WindowTitle);
//Assign the event-handling routines
glutDisplayFunc(Display);
glutReshapeFunc(reshape);
glutKeyboardFunc(KeyDown);
glutIdleFunc(Display);

//Lighting stuff:
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);


}



int _tmain(int argc, _TCHAR* argv[])
{

InitGL(argc, argv,"Tokamak testing environment - Simple Sample- W,A,S,D to move",700,700);

Camera.Move(F3dVector(0,10,60));

//Inititalize the physics simulation
TokSim.Init();
//init the random number generator:
srand(timeGetTime());

//Let GLUT get the msgs and tell us the ones we need
glutMainLoop();
return 0;
}

 

 

 

 

 

./CppHelloTokamakWindows/SimpleTokSim.h

 

#pragma once
#include "toksim.h"

class SimpleTokSim :
public CTokSim
{
public:
SimpleTokSim(void);
~SimpleTokSim(void);

void Init();
};

 

 

 

 

 

./CppHelloTokamakWindows/SimpleTokSim.cpp

 

#include "StdAfx.h"
#include ".\simpletoksim.h"
#include "TokSim.h"

#define FLOORSIZE 20.0f


SimpleTokSim::SimpleTokSim(void)
{
CTokSim::CTokSim();
}

SimpleTokSim::~SimpleTokSim(void)
{
}

void SimpleTokSim::Init()
{


neGeometry *geom;
    neV3 boxSize1;
    neV3 gravity;
    neV3 pos;
gravity.Set(0.0f, -10.0f, 0.0f);

//Init the simulation:
CTokSim::Init(100,2,gravity);

//Create rigid bodies. use boxes, spheres, and cylinders:
for (int i=0; i<m_MaxRigidCount; i++)
    {
        // Create a rigid body using the CTokSim class:
        neRigidBody * rigid = CreateRigidBody();

rigid->SetMass(0.01f);

// Add geometry to the body and set it to be a box of dimensions 1, 1, 1
        geom = rigid->AddGeometry();
        boxSize1.Set(1.0f, 1.0f, 1.0f);
if (i%3 == 0)
{
geom->SetBoxSize(boxSize1[0], boxSize1[1], boxSize1[2]);
rigid->SetInertiaTensor(neBoxInertiaTensor(boxSize1[0], boxSize1[1], boxSize1[2],rigid->GetMass()));
}
if (i%3 == 1)
{
geom->SetSphereDiameter(1.0f);
rigid->SetInertiaTensor(neSphereInertiaTensor(1.0f,rigid->GetMass()));
}
if (i%3 == 2)
{
static float Height = 1.0f;
static float Diameter = 1.0f;
geom->SetCylinder(Diameter,Height);
rigid->SetInertiaTensor(neCylinderInertiaTensor(Diameter,Height,rigid->GetMass()));
}

// Update the bounding info of the object -- must always call this
        // after changing a body's geometry.
        rigid->UpdateBoundingInfo();


    // Vary the position so the cubes don't all exactly stack on top of each other
        pos.Set((float)(rand()%10) / 100, 4.0f + i*2.0f, (float)(rand()%10) / 100);
        rigid->SetPos(pos);
    }
    


// Create an animated body for the floor
    neAnimatedBody * animated =  CreateAnimatedBody();
    geom = animated->AddGeometry();
    boxSize1.Set(FLOORSIZE, 0.5f, FLOORSIZE);
    geom->SetBoxSize(boxSize1[0],boxSize1[1],boxSize1[2]);
    animated->UpdateBoundingInfo();
    pos.Set(0.0f, -6.0f, 0.0f);
animated->SetPos(pos);




  


}

 

 

 

 

 

./CppHelloTokamakWindows/TokSim.h

 

#pragma once

///********************************************************************
///* CTokSim
///*
///* CTokSim is a base class for OpenGL applications
///* using the Tokamak physics engine (http://www.tokamakphysics.com).
///* It can display all basic simulation scenes and handle
///* springs.
///*
///* Author: Philipp Crocoll
///* philipp.crocoll@web.de
///* www.codecolony.de
///*
///* This class maybe used freely. I am glad
///* to here where it ends up!
///*
///* If you have suggestions or improvements,
///* please e-mail me!
///*
///********************************************************************

#include "tokamak.h"
#include "TokSpring.h"

//Define the max number of objects the simulation can handle.
//This is not the number which is passed the tokamak! (see "Init()")
#define MAX_RIGID_COUNT 1000
#define MAX_ANIMATED_COUNT 1000
#define MAX_SPRING_COUNT 1000



class CTokSim
{
protected:
//Tokamak variables:
neSimulator *m_Sim;
neRigidBody *m_Rigid[MAX_RIGID_COUNT];
neAnimatedBody *m_Animated[MAX_ANIMATED_COUNT];
//Springs:
CTokSpring *m_Spring[MAX_SPRING_COUNT];
//Number of max objects passed to tokamak:
int m_MaxRigidCount;
int m_MaxAnimatedCount;
//Number of objects created:
int m_AnimatedCount, m_RigidCount, m_SpringCount;

//used for terrain meshes:
int m_NumVertices;
int m_NumIndices;
GLfloat * m_VertexData;
GLuint * m_IndexData;

//Internal rendering functions:
void RenderSphere(neT3 TransformMatrix, float Diameter);
void RenderCylinder(neT3 TransformMatrix, float Diameter, float Height);
void RenderBox(neT3 TransformMatrix, neV3 Size);
void ApplyTransform(neT3 TransformMatrix);
void RenderGeometry(neGeometry * geom);
void RenderSpring(CTokSpring * spring);

//Use this function, then the class will display the mesh
void SetTerrainMesh(neTriangleMesh* Mesh);

public:
//Constructor
CTokSim(void);
//Destructor
~CTokSim(void);
//displays the scene:
void Display(void);
//Initialize the class:
void Init(int MaxRigidCount, int MaxAnimatedCount, neV3 gravity);

//Create objects:
CTokSpring * CreateSpring(neRigidBody * rigid1, neRigidBody * rigid2);
CTokSpring * CreateSpring(neRigidBody * rigid, neAnimatedBody * anim);
neRigidBody * CreateRigidBody();
neAnimatedBody * CreateAnimatedBody();
//returns a pointer to the tokamak simulator object:
neSimulator * GetSimulator();

//calls the tokamak advance function:
bool CalculateNextFrame(float dtime);


};

 

 

 

 

 

./CppHelloTokamakWindows/TokSim.cpp

 

#include "StdAfx.h"
#include "toksim.h"




#pragma comment(lib, "tokamak.lib")


//increase this value to get nicer Spheres and Cylinders (needs more rendering time):
#define SphereSlices 8


CTokSim::CTokSim(void)
{
//Init the member variables:
m_Sim = NULL;
m_SpringCount = 0;
m_RigidCount = 0;
m_AnimatedCount = 0;
for (int i = 0;i<MAX_RIGID_COUNT;i++)
m_Rigid[i] = NULL;
for (int i = 0;i<MAX_ANIMATED_COUNT;i++)
m_Animated[i] = NULL;

}

CTokSim::~CTokSim(void)
{
//Clean up:
if (m_Sim)
    {
        neSimulator::DestroySimulator(m_Sim); //also cleans all bodies etc.
        m_Sim = NULL;
    }
}

void CTokSim::Display(void)
{

//*****
//
// This function displays all tokamak bodies, the terrain mesh and the springs
// (if created via TokSim::CreateSpring).
// The results don't look "game-like" but can be used to test
// the physics engine (or your simulation implementation!).
//
//*****

static GLfloat MatAmbMesh[] = {0.3f,0.5f,0.3f,1.0f};
static GLfloat MatAmbAnim[] = {0.8f,0.5f,0.5f,1.0f};
static GLfloat MatAmbRigid[] = {0.5f,0.5f,0.8f,1.0f};
static GLfloat MatSpec[] = {0.0,0.0,0.0,0.0};
static GLfloat MatShininess[] = {0.0};

//Set general material values:
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, MatSpec);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, MatShininess);

//*********************
//** 1.) Draw the mesh:

glPushMatrix();

// * a) "wireframe" without lighting
glDisable(GL_LIGHTING);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT , MatAmbMesh);


if (m_NumVertices>0)
{
glDrawElements( GL_TRIANGLES, //mode
m_NumIndices,  //count, ie. how many indices
GL_UNSIGNED_INT, //type of the index array
m_IndexData);
}

// * a) solid with lighting (note: there are no normals in this version,
//      so every polygon has the same color)
glEnable(GL_LIGHTING);

glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
if (m_NumVertices>0)
{
glDrawElements( GL_TRIANGLES, //mode
m_NumIndices,  //count, ie. how many indices
GL_UNSIGNED_INT, //type of the index array
m_IndexData);
}


//*********************
//** 2.) Draw the rigid bodys:


glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT , MatAmbRigid);


for (int i = 0; i < m_MaxRigidCount; i++)
{
if (m_Rigid[i] == NULL) continue;

glPushMatrix();

ApplyTransform(m_Rigid[i]->GetTransform());

m_Rigid[i]->BeginIterateGeometry();
for  (int geomCount=0;geomCount < m_Rigid[i]->GetGeometryCount();geomCount++)
{
neGeometry * geom = m_Rigid[i]->GetNextGeometry();
RenderGeometry(geom);

}
glPopMatrix();


}  


//*********************
//** 3.) Draw the animated bodies:


glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT , MatAmbAnim);

for (int i = 0; i < m_MaxAnimatedCount; i++)
{
if (m_Animated[i] == NULL) continue;

glPushMatrix();

ApplyTransform(m_Animated[i]->GetTransform());

m_Animated[i]->BeginIterateGeometry();
for  (int geomCount=0;geomCount < m_Animated[i]->GetGeometryCount();geomCount++)
{
neGeometry * geom = m_Animated[i]->GetNextGeometry();
RenderGeometry(geom);
}
glPopMatrix();
}  

//*********************
//** 4.) Draw the springs:
for (int i = 0; i < m_SpringCount; i++)
{
if (m_Spring[i] == NULL) continue;

RenderSpring(m_Spring[i]);

}  


glPopMatrix();
}

void CTokSim::Init(int MaxRigidCount, int MaxAnimatedCount, neV3 gravity)
{

//*****
//Initialize the physics simulation.

m_MaxAnimatedCount = MaxAnimatedCount;
m_MaxRigidCount = MaxRigidCount;


neSimulatorSizeInfo sizeInfo;


sizeInfo.rigidBodiesCount = m_MaxRigidCount;
sizeInfo.animatedBodiesCount = m_MaxAnimatedCount;
s32 totalBody = sizeInfo.rigidBodiesCount + sizeInfo.animatedBodiesCount;
sizeInfo.geometriesCount = totalBody;
//see sdk for this formula:
sizeInfo.overlappedPairsCount = totalBody * (totalBody - 1) / 2;
sizeInfo.rigidParticleCount = 0;

//all information gathered. So create the simulator:
m_Sim = neSimulator::CreateSimulator(sizeInfo, NULL, &gravity);

}

bool CTokSim::CalculateNextFrame(float dtime)
{
m_Sim->Advance(dtime);

return true;
}

void CTokSim::RenderGeometry(neGeometry * geom)
{
//Renders boxes, spheres, or "cylinders" (which are capsules):
neV3 boxSize;
float SphereDiameter;
float CylDiameter, CylHeight;
if (geom->GetBoxSize(boxSize))
{
RenderBox(geom->GetTransform(),boxSize);
}
if (geom->GetSphereDiameter(SphereDiameter))
{
RenderSphere(geom->GetTransform(),SphereDiameter);
}
if (geom->GetCylinder(CylDiameter,CylHeight))
{
RenderCylinder(geom->GetTransform(),CylDiameter,CylHeight);
}
}


void CTokSim::ApplyTransform(neT3 TransformMatrix)
{
//Apply a tokamak transformation matrix to opengl:
neT3 t = TransformMatrix;
GLfloat matrix[] = { t.rot[0][0], t.rot[0][1], t.rot[0][2], 0.0f,
                    t.rot[1][0], t.rot[1][1], t.rot[1][2], 0.0f,
                    t.rot[2][0], t.rot[2][1], t.rot[2][2], 0.0f,
                    t.pos[0],t.pos[1], t.pos[2], 1.0f };
glMultMatrixf((GLfloat*)&matrix);
}


void CTokSim::RenderSphere(neT3 TransformMatrix, float Diameter)
{
//Renders a sphere. See the SphereSlices definition on top of this file.
glPushMatrix();
ApplyTransform(TransformMatrix);

glutSolidSphere(Diameter/2.0f,SphereSlices,SphereSlices);
glPopMatrix();
}

void CTokSim::RenderCylinder(neT3 TransformMatrix, float Diameter, float Height)
{
//Tokamak cylinders are not really cylinders.
//They have half a sphere on top and on there bottom.
//As the half of the sphere disappears inside (normally...), we render
//just two normal spheres.

glPushMatrix();
ApplyTransform(TransformMatrix);

//A gluCylinder "lies", a Tokamak Cylinder "stands", so rotated:
glRotatef(90.0f,1.0f,0.0f,0.0f);
glTranslatef(0.0f,0.0f,-Height/2.0f);
gluCylinder(gluNewQuadric(),Diameter/2.0f,Diameter/2.0f,Height,SphereSlices,SphereSlices);
glutSolidSphere(Diameter/2.0f,SphereSlices,SphereSlices);

glTranslatef(0.0f,0.0f,+Height);
glutSolidSphere(Diameter/2.0f,SphereSlices,SphereSlices);

glPopMatrix();
}


void CTokSim::RenderBox(neT3 TransformMatrix, neV3 Size)
{
//Render a simple solid box:
glPushMatrix();
ApplyTransform(TransformMatrix);

glScalef(Size[0],Size[1],Size[2]);
glutSolidCube(1.0f);
glPopMatrix();
}


void CTokSim::RenderSpring(CTokSpring * spring)
{
//Render a spring as a line connecting the two bodies.
//The color is dependent from the spring's length.
neV3 ConnPos1,ConnPos2;

ConnPos1 = spring->GetRigid1()->GetPos();
if (spring->GetSpringType() == RIGID_TO_RIGID)
ConnPos2 = spring->GetRigid2()->GetPos();
else
ConnPos2 = spring->GetAnimated()->GetPos();

ConnPos1+= spring->GetRigid1()->GetRotationM3()*spring->GetConnPos1();
if (spring->GetSpringType() == RIGID_TO_RIGID)
        ConnPos2+= spring->GetRigid2()->GetRotationM3()*spring->GetConnPos2();
else
ConnPos2+= spring->GetAnimated()->GetRotationM3()*spring->GetConnPos2();

//Set the color of the spring according to its length:
float r,g,b;
r = (spring->GetCurrentLength()/spring->GetDefaultLength()-1);
g = 0.0f;
b = 1.0f-r;
if (r<0.0f) r = 0.0f; if (r>1.0f) r = 1.0f;
if (b<0.0f) b = 0.0f; if (b>1.0f) b = 1.0f;


glDisable(GL_LIGHTING);
glColor3f(r,g,b);

glBegin(GL_LINE_STRIP);

glVertex3f(ConnPos1[0],ConnPos1[1],ConnPos1[2]);
glVertex3f(ConnPos2[0],ConnPos2[1],ConnPos2[2]);

glEnd();

//Render the "fixation vector(s)", if spring is fixed:
SFixationInfo fixation = spring->GetFixationInfo();
neV3 Fix1Point;
if (fixation.bFixed1)
{
Fix1Point = ConnPos1 + spring->GetRigid1()->GetRotationM3()*fixation.ConnDir1*spring->GetDefaultLength()/5.0f;

glColor3f(0.8f,0.8f,0.0f);

glBegin(GL_LINE_STRIP);

glVertex3f(ConnPos1[0],ConnPos1[1],ConnPos1[2]);
glVertex3f(Fix1Point[0],Fix1Point[1],Fix1Point[2]);

glEnd();
}

neV3 Fix2Point;
if (fixation.bFixed2)
{

Fix2Point = ConnPos2 ;
if (spring->GetSpringType() == RIGID_TO_RIGID)
Fix2Point += spring->GetRigid2()->GetRotationM3()*fixation.ConnDir2*spring->GetDefaultLength()/5.0f;
else
Fix2Point += spring->GetAnimated()->GetRotationM3()*fixation.ConnDir2*spring->GetDefaultLength()/5.0f;

glColor3f(0.8f,0.8f,0.0f);

glBegin(GL_LINE_STRIP);

glVertex3f(ConnPos2[0],ConnPos2[1],ConnPos2[2]);
glVertex3f(Fix2Point[0],Fix2Point[1],Fix2Point[2]);

glEnd();
}







}


void CTokSim::SetTerrainMesh(neTriangleMesh* Mesh)
{
//1.) Tell Tokamak about the mesh:
m_Sim->SetTerrainMesh(Mesh);


//2.) Store the Mesh as Vertex Array
glEnableClientState(GL_VERTEX_ARRAY);
m_NumVertices = Mesh->vertexCount;
m_NumIndices = Mesh->triangleCount*3;
m_VertexData = new GLfloat[m_NumVertices*3]; //3 components per vector
m_IndexData = new GLuint[m_NumIndices];

for (int i=0;i<m_NumVertices;i++)
{
for (int j=0;j<3;j++)
m_VertexData[i*3+j] = Mesh->vertices[i][j];

}
for (int i=0;i<Mesh->triangleCount;i++)
{
for (int j=0;j<3;j++)
m_IndexData[i*3+j] = Mesh->triangles[i].indices[j];
}


glVertexPointer( 3,   //3 components per vertex (x,y,z)
GL_FLOAT,
sizeof(GLfloat)*3,
m_VertexData);


}

CTokSpring * CTokSim::CreateSpring(neRigidBody * rigid1, neRigidBody * rigid2)
{
if (m_SpringCount >= MAX_SPRING_COUNT)
return NULL;


m_Spring[m_SpringCount++] = new CTokSpring(rigid1,rigid2);

return m_Spring[m_SpringCount-1];

}

CTokSpring * CTokSim::CreateSpring(neRigidBody * rigid, neAnimatedBody * anim)
{
if (m_SpringCount >= MAX_SPRING_COUNT)
return NULL;



m_Spring[m_SpringCount++] = new CTokSpring(rigid,anim);

return m_Spring[m_SpringCount-1];
}

neRigidBody * CTokSim::CreateRigidBody()
{
if (m_RigidCount>= MAX_RIGID_COUNT)
return NULL;
    
neRigidBody * rigid = m_Sim->CreateRigidBody();
m_Rigid[m_RigidCount++] = rigid;
return rigid;
}

neAnimatedBody * CTokSim::CreateAnimatedBody()
{
if (m_AnimatedCount>= MAX_ANIMATED_COUNT)
return NULL;
    
neAnimatedBody * animated = m_Sim->CreateAnimatedBody();
m_Animated[m_AnimatedCount++] = animated;
return animated;
}
neSimulator * CTokSim::GetSimulator()
{
return m_Sim;
}

 

 

 

 

 

./CppHelloTokamakWindows/TokSpring.h

 

#pragma once

#include "tokamak.h"

//Spring type definition:
typedef enum
{
RIGID_TO_RIGID,
RIGID_TO_ANIM
} eSpringType;

//Fixation information definition:
typedef struct
{
bool bFixed1, bFixed2; //indicate, if the spring is fixed
neV3 ConnDir1, ConnDir2; //direction vector of the spring relative to the body
//required only if spring is fixed (bFixed1 or bFixed2):
float fTangentForceFactor;
float fTangentDamping;
float fTorqueFactor;
float fAngularDamping;
} SFixationInfo;


class CTokSpring: public neRigidBodyControllerCallback
{
protected:
//Which types of objects are connected with this spring?
eSpringType m_Type;

//Pointers to the bodies possibly connected:
neRigidBody * m_Rigid1, * m_Rigid2;
neAnimatedBody * m_Anim;
//Position relative to the body's position: Where is the spring connected with the body?
neV3 m_ConnPos1, m_ConnPos2;

//Spring parameters:
float m_Length; //this is the length at which no force is created
float m_SpringConst; //how "strong" the spring is
float m_DampingFactor;  //used to damp the spring

//used if spring is "fixed":
SFixationInfo m_Fixation;

neV3 m_LastForce;
bool m_bLastForceAssigned;
float m_LastSpringLength;
    //the controller callback function
virtual void RigidBodyControllerCallback(neRigidBodyController * controller, float timeStep);

//Init the spring:
void Initialize();


public:
CTokSpring(neRigidBody * rigid1, neRigidBody * rigid2);
CTokSpring(neRigidBody * rigid, neAnimatedBody * anim);
~CTokSpring(void);

void SetDefaultLength(float length);
float GetDefaultLength();

void SetSpringConst(float SpringConst);
float GetSpringConst();

void SetDampingFactor(float DampingFactor);
float GetDampingFactor();

void SetConnPos1(neV3 pos);
neV3 GetConnPos1();
void SetConnPos2(neV3 pos);
neV3 GetConnPos2();

void FixSpring(SFixationInfo fixationInfo);
SFixationInfo GetFixationInfo();


eSpringType GetSpringType();
neRigidBody * GetRigid1();
neRigidBody * GetRigid2();
neAnimatedBody * GetAnimated();

float GetCurrentLength();





};

 

 

 

 

 

./CppHelloTokamakWindows/TokSpring.cpp

 

#include "StdAfx.h"
#include ".\tokspring.h"

typedef struct
{
neV3 Velocity, AngularVelocity;
neV3 Position;
neV3 ConnPos, ConnDir;  //in world coordinates
bool bSpringFixed;
} BodyProperties;

void CTokSpring::RigidBodyControllerCallback(neRigidBodyController * controller, float timeStep)
{
//Get a pointer to the rigid body we will controll here:
neRigidBody * rigid = controller->GetRigidBody();
//This member function will calculate a force at the connection point, a "center force" and a torque:
neV3 forceAtConnPos,centerforce,torque;
forceAtConnPos.SetZero();
torque.SetZero();
centerforce.SetZero();

//This member function can be called for the first or the second body which are connected by the spring.
//Their properties will be used often, so we have a struct to store them locally.
//The advantage then is, that doesn't matter anymore, if we are controlling body1 or body2.
//"ThisBody" is the body controlled here, "OtherBody" is the other body connected with this spring.
BodyProperties ThisBody, OtherBody;

//first get the properties of body1 and body2:
BodyProperties Body1, Body2;
Body1.Position = m_Rigid1->GetPos();
Body1.ConnPos.Set(Body1.Position);
Body1.ConnPos+= m_Rigid1->GetRotationM3()*m_ConnPos1;
Body1.Velocity = m_Rigid1->GetVelocity();
Body1.AngularVelocity = m_Rigid1->GetAngularVelocity();
Body1.ConnDir = m_Rigid1->GetRotationM3()*m_Fixation.ConnDir1;
Body1.bSpringFixed = m_Fixation.bFixed1;

if (m_Type == RIGID_TO_RIGID)
{
Body2.Position = m_Rigid2->GetPos();
Body2.ConnPos.Set(Body2.Position);
Body2.ConnPos += m_Rigid2->GetRotationM3()*m_ConnPos2;
Body2.Velocity = m_Rigid2->GetVelocity();
Body2.AngularVelocity = m_Rigid2->GetAngularVelocity();
Body2.ConnDir = m_Rigid2->GetRotationM3()*m_Fixation.ConnDir2;
} else
if (m_Type == RIGID_TO_ANIM)
{
Body2.Position = m_Anim->GetPos();
Body2.ConnPos = Body2.Position;
Body2.ConnPos += m_Anim->GetRotationM3()*m_ConnPos2;
Body2.Velocity.SetZero(); //this might be wrong if the user moves his anim body.
//but this case is not yet supported here.
Body2.AngularVelocity.SetZero();
Body2.ConnDir = m_Anim->GetRotationM3()*m_Fixation.ConnDir2;

}
Body2.bSpringFixed = m_Fixation.bFixed2;

//Assign the "ThisBody" and "OtherBody" structures:
if (rigid == m_Rigid1)
{
ThisBody = Body1;
OtherBody = Body2;
}
else
{
ThisBody = Body2;
OtherBody = Body1;
}

neV3 dist = OtherBody.ConnPos-ThisBody.ConnPos;
neV3 dir = dist;dir.Normalize();
//how long is the spring right now?
f32 SpringLength = dist.Length();

//Ready to calculate the force in the direction of the spring ("contraction/expansion force"):
forceAtConnPos -= (m_Length-SpringLength)*m_SpringConst*dir;

//Add a damping force
//only calculate in the direction of the spring if fixed:
if ((m_Fixation.bFixed1) || (m_Fixation.bFixed2))
forceAtConnPos -= m_DampingFactor*(ThisBody.Velocity-OtherBody.Velocity).Dot(dir)*dir;
else
forceAtConnPos -= m_DampingFactor*(ThisBody.Velocity-OtherBody.Velocity);

//Store the spring length:
m_LastSpringLength = SpringLength;

//** Handle Fixation **//
if (ThisBody.bSpringFixed)
{
//fixation at this body will cause a torque

torque += ThisBody.ConnDir.Cross(dir)*m_Fixation.fTorqueFactor;
//damping torque:
torque -= m_Fixation.fAngularDamping*(ThisBody.AngularVelocity-OtherBody.AngularVelocity);

}


neV3 dampforcedir;
if (OtherBody.bSpringFixed)
{
//Fixation of the spring on the other body causes a force:

neV3 planeNormal = OtherBody.ConnDir.Cross(dir);
centerforce -= m_Fixation.fTangentForceFactor*planeNormal.Cross(dir);
//damping force:
    dampforcedir = centerforce;dampforcedir.Normalize();

}
if (ThisBody.bSpringFixed)
{
//Fixation of the spring on this body causes also a force:

neV3 planeNormal = ThisBody.ConnDir.Cross(dir);
centerforce += m_Fixation.fTangentForceFactor*planeNormal.Cross(dir);
//damping force:
dampforcedir = centerforce;dampforcedir.Normalize();
}
if (m_Fixation.bFixed1 || m_Fixation.bFixed2)
centerforce -= m_Fixation.fTangentDamping*(ThisBody.Velocity-OtherBody.Velocity).Dot(dampforcedir)*dampforcedir;



neV3 pos;
pos = rigid->GetPos();

//That's it. Now apply the force:

///****
///*
///* NOTE: THESE LINES ARE NOT YET 100% CORRECT.
///* But they still produce working springs...
///*
///****
rigid->SetForce(forceAtConnPos+centerforce,ThisBody.ConnPos);
rigid->SetTorque(torque);



};


CTokSpring::CTokSpring(neRigidBody * rigid1, neRigidBody * rigid2)
{
//Set default values:
Initialize();
//Store the pointers to the conntected bodies:
m_Rigid1 = rigid1;
m_Rigid2 = rigid2;
m_Anim = NULL;
//We have a rigid-rigid spring:
m_Type =  RIGID_TO_RIGID;
//add the controller callback function:
m_Rigid1->AddController(this,0.0f);
m_Rigid2->AddController(this,0.0f);
}

CTokSpring::CTokSpring(neRigidBody * rigid, neAnimatedBody * anim)
{
//Set default values:
Initialize();
//Store the pointers to the conntected bodies:
m_Rigid1 = rigid;
m_Rigid2 = NULL;
m_Anim= anim;
//We have a rigid-anim spring:
m_Type =  RIGID_TO_ANIM;
//add the controller callback function:
m_Rigid1->AddController(this,0.0f);
}

CTokSpring::~CTokSpring(void)
{
}

void CTokSpring::Initialize()
{
//set default values:
m_Length = 1.0f;
m_SpringConst = 1.0f;
m_DampingFactor = 0.0f;
m_ConnPos1.SetZero();
m_ConnPos2.SetZero();
m_Fixation.bFixed1 = false;
m_Fixation.bFixed2 = false;
m_bLastForceAssigned = false;
}

void CTokSpring::SetDefaultLength(float length)
{
m_Length = length;
}
float CTokSpring::GetDefaultLength()
{
return m_Length;
}


void CTokSpring::SetSpringConst(float SpringConst)
{
m_SpringConst = SpringConst;
}
float CTokSpring::GetSpringConst()
{
return m_SpringConst;
}
eSpringType CTokSpring::GetSpringType()
{
return m_Type;
}
neRigidBody * CTokSpring::GetRigid1()
{
return m_Rigid1;
}
neRigidBody * CTokSpring::GetRigid2()
{
return m_Rigid2;
}
neAnimatedBody * CTokSpring::GetAnimated()
{
return m_Anim;
}
float CTokSpring::GetCurrentLength()
{
return m_LastSpringLength;
}

void CTokSpring::SetDampingFactor(float DampingFactor)
{
m_DampingFactor = DampingFactor;
}
float CTokSpring::GetDampingFactor()
{
return m_DampingFactor;
}
void CTokSpring::SetConnPos1(neV3 pos)
{
m_ConnPos1.Set(pos);
}

neV3 CTokSpring::GetConnPos1()
{
return m_ConnPos1;
}

void CTokSpring::FixSpring(SFixationInfo fixInfo)
{
m_Fixation = fixInfo;
if (fixInfo.bFixed1)
{
m_Fixation.ConnDir1.Normalize();
}
if (fixInfo.bFixed2)
{
m_Fixation.ConnDir2.Normalize();
}
}

SFixationInfo CTokSpring::GetFixationInfo()
{
return m_Fixation;
}

void CTokSpring::SetConnPos2(neV3 pos)
{
m_ConnPos2.Set(pos);
}
neV3 CTokSpring::GetConnPos2()
{
return m_ConnPos2;
}

 

 

 

 

 

./CppHelloTokamakWindows/camera.h

 

//***************************************************************************
//
// Advanced CodeColony Camera
// Philipp Crocoll, 2003
//
//***************************************************************************


#include <gl\glut.h> // Need to include it here because the GL* types are required
#include "SPMath.h"

/////////////////////////////////
//Note: All angles in degrees  //
/////////////////////////////////


class CCamera
{
private:

SF3dVector ViewDir;
SF3dVector RightVector;
SF3dVector UpVector;
SF3dVector Position;

GLfloat RotatedX, RotatedY, RotatedZ;

public:
CCamera(); //inits the values (Position: (0|0|0) Target: (0|0|-1) )
void Render ( void ); //executes some glRotates and a glTranslate command
//Note: You should call glLoadIdentity before using Render

void Move ( SF3dVector Direction );
void RotateX ( GLfloat Angle );
void RotateY ( GLfloat Angle );
void RotateZ ( GLfloat Angle );

void MoveForward ( GLfloat Distance );
void MoveUpward ( GLfloat Distance );
void StrafeRight ( GLfloat Distance );


};

 

 

 

 

 

./CppHelloTokamakWindows/camera.cpp

 

#include "camera.h"
#include "math.h"

#define SQR(x) (x*x)

#define NULL_VECTOR F3dVector(0.0f,0.0f,0.0f)

CCamera::CCamera()
{
//Init with standard OGL values:
Position = F3dVector (0.0, 0.0, 0.0);
ViewDir = F3dVector( 0.0, 0.0, -1.0);
RightVector = F3dVector (1.0, 0.0, 0.0);
UpVector = F3dVector (0.0, 1.0, 0.0);

//Only to be sure:
RotatedX = RotatedY = RotatedZ = 0.0;
}

void CCamera::Move (SF3dVector Direction)
{
Position = Position + Direction;
}

void CCamera::RotateX (GLfloat Angle)
{
RotatedX += Angle;

//Rotate viewdir around the right vector:
ViewDir = Normalize3dVector(ViewDir*cos(Angle*PIdiv180)
+ UpVector*sin(Angle*PIdiv180));

//now compute the new UpVector (by cross product)
UpVector = CrossProduct(&ViewDir, &RightVector)*-1;


}

void CCamera::RotateY (GLfloat Angle)
{
RotatedY += Angle;

//Rotate viewdir around the up vector:
ViewDir = Normalize3dVector(ViewDir*cos(Angle*PIdiv180)
- RightVector*sin(Angle*PIdiv180));

//now compute the new RightVector (by cross product)
RightVector = CrossProduct(&ViewDir, &UpVector);
}

void CCamera::RotateZ (GLfloat Angle)
{
RotatedZ += Angle;

//Rotate viewdir around the right vector:
RightVector = Normalize3dVector(RightVector*cos(Angle*PIdiv180)
+ UpVector*sin(Angle*PIdiv180));

//now compute the new UpVector (by cross product)
UpVector = CrossProduct(&ViewDir, &RightVector)*-1;
}

void CCamera::Render( void )
{

//The point at which the camera looks:
SF3dVector ViewPoint = Position+ViewDir;

//as we know the up vector, we can easily use gluLookAt:
gluLookAt( Position.x,Position.y,Position.z,
ViewPoint.x,ViewPoint.y,ViewPoint.z,
UpVector.x,UpVector.y,UpVector.z);

}

void CCamera::MoveForward( GLfloat Distance )
{
Position = Position + (ViewDir*-Distance);
}

void CCamera::StrafeRight ( GLfloat Distance )
{
Position = Position + (RightVector*Distance);
}

void CCamera::MoveUpward( GLfloat Distance )
{
Position = Position + (UpVector*Distance);
}

 

 

 

 

 

./CppHelloTokamakWindows/spstructs.h

 

#ifndef SP_STRUCTS_H_INCLUDED
#define SP_STRUCTS_H_INCLUDED

#include "gl/glut.h"

#define PI 3.1415926535897932384626433832795
#define PIdiv180 PI/180.0f

#define NULL_VECTOR F3dVector(0.0f,0.0f,0.0f)

struct SF3dVector  //Float 3d-vect, normally used
{
GLfloat x,y,z;
};
struct SF2dVector
{
GLfloat x,y;
};

struct SF4dVector
{
GLfloat a[4];
};


//********************
// 3d-Vectors
//
SF3dVector F3dVector ( GLfloat x, GLfloat y, GLfloat z );
SF3dVector AddF3dVectors ( SF3dVector * u, SF3dVector * v);
SF3dVector operator* (SF3dVector v, float r);
SF3dVector operator* (float r, SF3dVector v);
SF3dVector operator/ (SF3dVector v, float r);
float operator* (SF3dVector v, SF3dVector u); //Scalar product
SF3dVector operator+ (SF3dVector v, SF3dVector u);
SF3dVector operator- (SF3dVector v, SF3dVector u);

bool operator== (SF3dVector v, SF3dVector u);
bool operator!= (SF3dVector v, SF3dVector u);

GLfloat GetF3dVectorLength( SF3dVector * v);
void AddF3dVectorToVector ( SF3dVector * Dst, SF3dVector * V2);

//********************
// 2d-Vectors
//

SF2dVector F2dVector ( GLfloat x, GLfloat y);
SF2dVector operator+ (SF2dVector v, SF2dVector u);
SF2dVector operator- (SF2dVector v, SF2dVector u);



struct S3dModelVertex
{
SF3dVector Position;
SF2dVector TexCoordinates;
SF3dVector NormalVector;
};

struct SSPMaterial
{
//not everything in use!
GLfloat m_fAmbient[4];
GLfloat m_fDiffuse[4];
GLfloat m_fSpecular[4];
GLfloat m_fEmissive[4];
GLfloat m_fShininess;
GLfloat m_fTransparency;
};

struct SSPForce
{
SF3dVector m_Direction;  //also indicates the amount
SF3dVector m_Position;  //relative to the center of gravity
bool m_bInUse;  //make the calculations more performant by easily dropping non-used forces
};

struct SSPMomentum
{
SF3dVector m_Momentum;
SF3dVector m_Position;
};

//data structure to store on which node/plate of a track a vehicle resides.
struct SSPVehicleTrackPosition
{
int m_iNodeIndex;
int m_iPlateIndex;
};

struct SSPBottomPoint
{
int   m_VertexIndex;  //in MODEL0! (which vertex is used as bottom point)
SF3dVector   m_TurnedPosition; //vertex pos turned around center
SF3dVector   m_GlobalPosition; //turned pos + center pos
SF3dVector   m_FormerGlobalPosition;  //one frame before
float   m_TrackYDist;   //yDist to the track
SSPVehicleTrackPosition  m_TrackPosition; //Plate/Node
};

#endif

 

 

 

 

 

./CppHelloTokamakWindows/spstructs.cpp

 

#include "SPStructs.h"
#include <math.h>

bool operator== (SF3dVector v, SF3dVector u)
{
return (v.x==u.x) && (v.y==u.y) && (v.z == u.z);
}
bool operator!= (SF3dVector v, SF3dVector u)
{
return (!(v==u));
}


float operator* (SF3dVector v, SF3dVector u) //Scalar product
{
return v.x*u.x+v.y*u.y+v.z*u.z;
}

SF3dVector operator* (SF3dVector v, float r)
{
SF3dVector res;
res.x = v.x*r;
res.y = v.y*r;
res.z = v.z*r;
return res;
}
SF3dVector operator* (float r, SF3dVector v)
{
return v*r;
}

SF3dVector operator/ (SF3dVector v, float r)
{
return v*(1/r);
}

SF3dVector operator+ (SF3dVector v, SF3dVector u)
{
SF3dVector res;
res.x = v.x+u.x;
res.y = v.y+u.y;
res.z = v.z+u.z;
return res;
}
SF3dVector operator- (SF3dVector v, SF3dVector u)
{
SF3dVector res;
res.x = v.x-u.x;
res.y = v.y-u.y;
res.z = v.z-u.z;
return res;
}


SF3dVector F3dVector ( GLfloat x, GLfloat y, GLfloat z )
{
SF3dVector tmp;
tmp.x = x;
tmp.y = y;
tmp.z = z;
return tmp;
}


SF2dVector operator+ (SF2dVector v, SF2dVector u)
{
SF2dVector res;
res.x = v.x+u.x;
res.y = v.y+u.y;
return res;

}

SF2dVector operator- (SF2dVector v, SF2dVector u)
{
SF2dVector res;
res.x = v.x-u.x;
res.y = v.y-u.y;
return res;
}

SF2dVector F2dVector ( GLfloat x, GLfloat y)
{
SF2dVector tmp;
tmp.x = x;
tmp.y = y;
return tmp;
}

 

 

 

 

 

./CppHelloTokamakWindows/stdafx.h

 



#pragma once


#include <iostream>
#include <tchar.h>
#include "gl/glut.h"
#include "SPMath.h"

 

 

 

 

 

./CppHelloTokamakWindows/stdafx.cpp

 

// stdafx.cpp : Quelltextdatei, die nur die Standard-Includes einbindet
// SimpleSample.pch ist der vorcompilierte Header
// stdafx.obj enthält die vorcompilierte Typinformation

#include "stdafx.h"

// TODO: Verweisen Sie auf zusätzliche Header, die in STDAFX.H
// und nicht in dieser Datei erforderlich sind.

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict

This page has been created by the tool CodeToHtml