20 #include "renderworld.h"
31 #include <QLinkedList>
32 #include <QMutexLocker>
38 # include <GLUT/glut.h>
43 using namespace qglviewer;
45 #define GLMultMatrix glMultMatrixf
48 #include "qglviewer/camera.h"
49 #if QT_VERSION >= 0x040000
50 # include <QWheelEvent>
55 QMap<QString, QImage>* RenderWObjectContainer::textmap = NULL;
56 unsigned int RenderWObjectContainer::textmapRefCounter = 0;
58 RenderWObjectContainer::RenderWObjectContainer( QString wResName ) :
59 worldResourceName(wResName),
61 mutex(QMutex::Recursive)
63 if ( textmap == NULL ) {
64 textmap =
new QMap<QString, QImage>();
65 (*textmap)[
"tile1"].load(
":/tiles/16tile10.jpg" );
66 (*textmap)[
"tile2"].load(
":/tiles/16tile07.jpg" );
67 (*textmap)[
"white"].load(
":/white.jpg" );
68 (*textmap)[
"tile3"].load(
":/tiles/16tile11.jpg" );
69 (*textmap)[
"tile4"].load(
":/tiles/16tile-B.jpg" );
70 (*textmap)[
"tile5"].load(
":/tiles/16tile12.jpg" );
71 (*textmap)[
"tile6"].load(
":/tiles/16tile04.jpg" );
72 (*textmap)[
"tile7"].load(
":/tiles/tile01.jpg" );
73 (*textmap)[
"tile8"].load(
":/tiles/16tile02.jpg" );
74 (*textmap)[
"tile9"].load(
":/tiles/16tile05.jpg" );
75 (*textmap)[
"tile10"].load(
":/tiles/16tile08.jpg" );
76 (*textmap)[
"icub"].load(
":/tiles/16tile11.jpg" );
77 (*textmap)[
"icubFace"].load(
":/covers/face.jpg" );
78 (*textmap)[
"blueye"].load(
":/covers/eyep2_b.jpg" );
79 (*textmap)[
"metal"].load(
":/metal/iron05.jpg" );
80 (*textmap)[
"marXbot_12leds"].load(
":/covers/marxbot_12leds.jpg" );
94 (*textmap)[
"skyb0"].load(
":/skybox/sb2_top.jpg" );
95 (*textmap)[
"skyb1"].load(
":/skybox/sb2_back.jpg" );
96 (*textmap)[
"skyb2"].load(
":/skybox/sb2_front.jpg" );
97 (*textmap)[
"skyb3"].load(
":/ground/cobbles01.jpg" );
98 (*textmap)[
"skyb4"].load(
":/skybox/sb2_right.jpg" );
99 (*textmap)[
"skyb5"].load(
":/skybox/sb2_left.jpg" );
111 if (textmapRefCounter == 0) {
118 QMutexLocker locker(&
mutex);
120 return ((*textmap)[texturename].load( filename ));
129 QMutexLocker locker(&
mutex);
132 for(
int i=0; i<graphs.size(); i++ ) {
133 if ( graphs[i]->
object() == obj ) {
142 const QMetaObject* metaObj = obj->metaObject();
144 QString classname = metaObj->className();
145 if (fac->contains(classname)) {
146 return (*fac)[classname]->create( (
WObject*)obj, container );
148 metaObj = metaObj->superClass();
153 return (*fac)[
"farsa::WObject"]->create( (
WObject*)obj, container );
159 QMutexLocker locker(&
mutex);
167 QMutexLocker locker(&
mutex);
169 for(
int i=0; i<graphs.size(); i++ ) {
170 if ( graphs[i]->
object() == wobj ) {
182 QMutexLocker locker(&
mutex);
185 if (name != worldResourceName) {
197 if (changeType == Deleted) {
200 worldv = getResource<World>();
204 if (worldv != NULL) {
212 QMutexLocker locker(&
mutex);
214 if ( textmap->contains( texts ) ) {
215 if ( !textGLId.contains( texts ) ) {
216 textGLId[texts] = gw->bindTexture( (*textmap)[texts], GL_TEXTURE_2D, GL_RGB );
218 glBindTexture( GL_TEXTURE_2D, textGLId[texts] );
219 glEnable( GL_TEXTURE_2D );
228 QMutexLocker locker(&
mutex);
231 glShadeModel( GL_SMOOTH );
232 glEnable( GL_BLEND );
233 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
237 if ( owner != NULL ) {
243 QColor colorv = obj->
color();
244 glColor4f( colorv.redF(), colorv.greenF(), colorv.blueF(), colorv.alphaF() );
251 QMutexLocker locker(&
mutex);
253 if (worldv == NULL) {
257 worldv->
size( min, max );
258 wVector m_size =
wVector( fabs(max[0]-min[0]), fabs(max[1]-min[1]), fabs(max[1]-min[1]) );
262 glDisable( GL_LIGHTING );
263 glShadeModel( GL_FLAT );
264 glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
275 glTexCoord2f(0.0, 1.0); glVertex3f( min.x, max.y, max.z);
276 glTexCoord2f(0.0, 0.0); glVertex3f( max.x, max.y, max.z);
277 glTexCoord2f(1.0, 0.0); glVertex3f( max.x, min.y, max.z);
278 glTexCoord2f(1.0, 1.0); glVertex3f( min.x, min.y, max.z);
283 glTexCoord2f(1.0, 0.0); glVertex3f( min.x, max.y, min.z);
284 glTexCoord2f(1.0, 1.0); glVertex3f( min.x, max.y, max.z);
285 glTexCoord2f(0.0, 1.0); glVertex3f( min.x, min.y, max.z);
286 glTexCoord2f(0.0, 0.0); glVertex3f( min.x, min.y, min.z);
291 glTexCoord2f(0.0, 1.0); glVertex3f(max.x, max.y, max.z);
292 glTexCoord2f(0.0, 0.0); glVertex3f(max.x, max.y, min.z);
293 glTexCoord2f(1.0, 0.0); glVertex3f(max.x, min.y, min.z);
294 glTexCoord2f(1.0, 1.0); glVertex3f(max.x, min.y, max.z);
300 float bfs = m_size[1]/0.4;
301 float bft = m_size[0]/0.4;
303 glTexCoord2f(0.0, bft); glVertex3f( max.x, max.y, min.z);
304 glTexCoord2f(0.0, 0.0); glVertex3f( min.x, max.y, min.z);
305 glTexCoord2f(bfs, 0.0); glVertex3f( min.x, min.y, min.z);
306 glTexCoord2f(bfs, bft); glVertex3f( max.x, min.y, min.z);
311 glTexCoord2f(1.0, 1.0); glVertex3f( min.x, min.y, max.z);
312 glTexCoord2f(0.0, 1.0); glVertex3f( max.x, min.y, max.z);
313 glTexCoord2f(0.0, 0.0); glVertex3f( max.x, min.y, min.z);
314 glTexCoord2f(1.0, 0.0); glVertex3f( min.x, min.y, min.z);
319 glTexCoord2f(0.0, 0.0); glVertex3f( min.x, max.y, min.z);
320 glTexCoord2f(1.0, 0.0); glVertex3f( max.x, max.y, min.z);
321 glTexCoord2f(1.0, 1.0); glVertex3f( max.x, max.y, max.z);
322 glTexCoord2f(0.0, 1.0); glVertex3f( min.x, max.y, max.z);
337 void changeOrthoFrustumSize(
int delta) {
345 halfHeight = orthoSize;
365 qDebug() <<
"Using Reference";
371 if ( (pos.x + tw.x > maxP.x && t.x > 0) || (pos.x + tw.x < minP.x && t.x < 0) ||
372 (pos.y + tw.y > maxP.y && t.y > 0) || (pos.y + tw.y < minP.y && t.y < 0) ||
373 (pos.z + tw.z > maxP.z && t.z > 0) || (pos.z + tw.z < minP.z && t.z < 0) ) {
386 class ForceRenderWorldUpdateEvent :
public QEvent
389 ForceRenderWorldUpdateEvent() :
394 virtual ~ForceRenderWorldUpdateEvent()
404 showskygroundbox =
true;
410 currentSelected = -1;
416 setContextMenuPolicy( Qt::CustomContextMenu );
425 void RenderWorld::slotRemoveObject(
WObject* w ) {
430 void RenderWorld::slotAddObject( WObject* w ) {
435 void RenderWorld::onWorldResize() {
438 QMutexLocker locker(&
mutex);
440 if (
world() == NULL) {
456 QMutexLocker locker(&
mutex);
461 QMutexLocker locker(&
mutex);
462 showskygroundbox = b;
466 QMutexLocker locker(&
mutex);
471 QMutexLocker locker(&
mutex);
476 QMutexLocker locker(&
mutex);
481 QMutexLocker locker(&
mutex);
486 QMutexLocker locker(&
mutex);
492 QList<QAction*> acts;
494 if ( showskygroundbox ) {
495 act =
new QAction(
"Hide Sky-Ground",
this );
497 act =
new QAction(
"Show Sky-Ground",
this );
499 act->setCheckable(
true );
500 act->setChecked( showskygroundbox );
501 connect( act, SIGNAL( toggled(
bool) ),
505 act =
new QAction(
"Hide Wireframe",
this );
507 act =
new QAction(
"Show Wireframe",
this );
509 act->setCheckable(
true );
510 act->setChecked( wiref );
511 connect( act, SIGNAL( toggled(
bool) ),
516 act =
new QAction(
"Hide Objects",
this );
518 act =
new QAction(
"Show Objects",
this );
520 act->setCheckable(
true );
521 act->setChecked( showobjs );
522 connect( act, SIGNAL( toggled(
bool) ),
527 act =
new QAction(
"Hide Joints",
this );
529 act =
new QAction(
"Show Joints",
this );
531 act->setCheckable(
true );
532 act->setChecked( showjoints );
533 connect( act, SIGNAL( toggled(
bool) ),
538 act =
new QAction(
"Hide AABBs",
this );
540 act =
new QAction(
"Show AABBs",
this );
542 act->setCheckable(
true );
543 act->setChecked( showaabbs );
544 connect( act, SIGNAL( toggled(
bool) ),
548 if ( showcontacts ) {
549 act =
new QAction(
"Hide Contacts",
this );
551 act =
new QAction(
"Show Contacts",
this );
553 act->setCheckable(
true );
554 act->setChecked( showcontacts );
555 connect( act, SIGNAL( toggled(
bool) ),
560 act =
new QAction(
"Hide Forces",
this );
562 act =
new QAction(
"Show Forces",
this );
564 act->setCheckable(
true );
565 act->setChecked( showforces );
566 connect( act, SIGNAL( toggled(
bool) ),
570 QMenu::exec( acts, pos );
576 QMutexLocker locker(&
mutex);
578 if (
world() == NULL) {
596 QMutexLocker locker(&
mutex);
598 if (
world() == NULL) {
602 if ( showskygroundbox ) {
603 glPushAttrib( GL_ALL_ATTRIB_BITS );
611 float pos[4] = {1.0, 0.5, 1.0, 0.0};
614 glLightfv( GL_LIGHT0, GL_POSITION, pos );
617 if ( showcontacts ) {
618 glPushAttrib( GL_ALL_ATTRIB_BITS );
620 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
621 glDisable( GL_LIGHTING );
623 contactMapIterator itera(
world()->contacts() );
624 while( itera.hasNext() ) {
626 const contactVec& vec = itera.value();
627 for(
int i=0; i<vec.size(); i++ ) {
636 glPushAttrib( GL_ALL_ATTRIB_BITS );
638 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
639 glDisable( GL_LIGHTING );
646 glPushAttrib( GL_ALL_ATTRIB_BITS );
649 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
651 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
653 glEnable( GL_LIGHTING );
655 for(
int i=0; i<
graphics().size(); i++ ) {
658 if ( showforces && ( pr=dynamic_cast<PhyObject*>(r->
object()) ) ) {
659 glPushAttrib( GL_ALL_ATTRIB_BITS );
660 glColor4f( 1.0, 0.0, 0.0, 1.0 );
662 glColor4f( 0.0, 1.0, 0.0, 1.0 );
668 glPushAttrib( GL_ALL_ATTRIB_BITS );
669 r->render( (QGLContext*)( QGLContext::currentContext() ) );
671 if ( showaabbs && currentSelected == i ) {
672 glPushAttrib( GL_ALL_ATTRIB_BITS );
675 wVector dims, minPoint, maxPoint;
677 glPushAttrib( GL_ALL_ATTRIB_BITS );
685 glPushAttrib( GL_ALL_ATTRIB_BITS );
686 glColor4f( 1.0, 0.0, 0.0, 1.0 );
687 drawText( 80, 15, QString(
"time: %1 step: %2")
688 .arg(
world()->elapsedTime())
689 .arg((
int)(
world()->elapsedTime()/
world()->timeStep()))
695 QMutexLocker locker(&
mutex);
697 for(
int i=0; i<
graphics().size(); i++ ) {
699 graphics()[i]->render( (QGLContext*)( QGLContext::currentContext() ) );
705 QMutexLocker locker(&
mutex);
707 UNUSED_PARAM( point );
709 if ( i != -1 && i != currentSelected ) {
710 graphics()[qMax(0,currentSelected)]->object()->setColor( Qt::white );
711 graphics()[i]->object()->setColor( Qt::yellow );
717 QMutexLocker locker(&
mutex);
720 #if QT_VERSION < 0x040000
722 const Qt::ButtonState modifiers = (Qt::ButtonState)(e->state() & Qt::KeyButtonMask);
724 const Qt::KeyboardModifiers modifiers = e->modifiers();
730 bool handled =
false;
731 if ((e->key()==Qt::Key_Left) && (modifiers==Qt::NoButton)) {
738 }
else if ((e->key()==Qt::Key_Right) && (modifiers==Qt::NoButton)) {
746 if ((e->key()==Qt::Key_Up) && (modifiers==Qt::NoButton)) {
753 }
else if ((e->key()==Qt::Key_Down) && (modifiers==Qt::NoButton)) {
762 if ((e->key()==Qt::Key_M) && (modifiers==Qt::NoButton)) {
774 QMutexLocker locker(&
mutex);
779 if (
world() == NULL) {
787 this, SLOT( slotRemoveObject(
WObject* ) ), Qt::DirectConnection );
789 this, SLOT( slotAddObject(
WObject* ) ), Qt::DirectConnection );
790 connect(
world(), SIGNAL( resized() ),
791 this, SLOT( onWorldResize() ), Qt::DirectConnection );
793 connect(
world(), SIGNAL( advanced() ),
794 this, SLOT( update() ) );
808 QCoreApplication::postEvent(
this,
new ForceRenderWorldUpdateEvent());
811 void RenderWorld::drawDOF(
PhyDOF* dof,
bool drawAxes ) {
814 if ( dof->
joint() == NULL )
return;
820 mat.x_ax = dof->
xAxis();
821 mat.y_ax = dof->
yAxis();
822 mat.z_ax = dof->
axis();
823 mat.w_pos = dof->
centre();
832 rw[ child ]->calculateOBB( dims, minP, maxP );
833 real cube = (dims[0]+dims[1]+dims[2])/3.0;
835 rw[ parent ]->calculateOBB( dims, minP, maxP );
836 real cube2 = (dims[0]+dims[1]+dims[2])/3.0;
837 cube =
min( cube2, cube );
839 real len = cube * 0.70;
840 real rad = len * 0.25;
849 mat.w_pos = wVector(0,0,0);
850 mat = mat * wMatrix( wQuaternion( dof->
axis(), lo ), wVector(0,0,0) );
858 mat.x_ax = dof->
xAxis();
859 mat.y_ax = dof->
yAxis();
860 mat.z_ax = dof->
axis();
861 mat.w_pos = wVector(0,0,0);
863 mat = mat * wMatrix( wQuaternion( dof->
axis(), dof->
position()-0.05 ), wVector(0,0,0) );
865 drawTorus( rad, rad*0.55f, mat, 0.1f, Qt::green );
873 void RenderWorld::drawKineChains() {
876 if (
world() == NULL) {
880 foreach( PhyJoint* jn,
world()->joints()) {
882 float dist1 = 0.0f, dist2 = 0.0f;
883 wVector start = jn->centre();
884 wVector end1 = jn->child()->matrix().w_pos;
885 wVector end2 = start;
887 if ( jn->parent() ) {
888 end2 = jn->parent()->matrix().w_pos;
891 real rad = (dist1 + dist2) * 0.04;
895 QVector<PhyDOF*> ds = jn->dofs();
896 for(
int k=0; k<ds.size(); k++ ) {
897 drawDOF( ds[k],
true );
902 void RenderWorld::customEvent(QEvent* event)
904 if (event->type() == QEvent::User) {
914 glShadeModel( GL_SMOOTH );
915 glColor4f( 0.0f, 1.0f, 0.0f, 1.0f );
919 mat.x_ax = mat.x_ax.
scale( radius );
920 mat.y_ax = mat.y_ax.
scale( radius );
921 mat.z_ax = mat.z_ax.
scale( radius );
923 GLMultMatrix(&mat[0][0]);
926 pObj = gluNewQuadric();
928 gluQuadricTexture(pObj,
true);
929 gluSphere(pObj, 1.0f, 20, 20);
931 gluDeleteQuadric(pObj);
941 glShadeModel( GL_SMOOTH );
942 glColor4f( c.redF(), c.greenF(), c.blueF(), c.alphaF() );
945 glTranslatef( recentre[0], recentre[1], recentre[2] );
948 Vec ax( axis[0], axis[1], axis[2] );
950 glMultMatrixd( quad.
matrix() );
953 pObj = gluNewQuadric();
954 gluQuadricTexture(pObj,
true);
955 gluCylinder(pObj, rad, rad, h, 20, 2);
958 gluQuadricOrientation(pObj, GLU_INSIDE);
959 gluDisk(pObj, 0.0f, rad, 20, 1);
961 glTranslatef (0.0f, 0.0f, h);
962 gluQuadricOrientation(pObj, GLU_OUTSIDE);
963 gluDisk(pObj, 0.0f, rad, 20, 1);
965 gluDeleteQuadric(pObj);
971 if ( h < 0.0001 )
return;
978 glShadeModel( GL_SMOOTH );
979 glColor4f( c.redF(), c.greenF(), c.blueF(), c.alphaF() );
985 GLMultMatrix( &tm[0][0] );
988 pObj = gluNewQuadric();
989 gluQuadricTexture(pObj,
true);
990 gluCylinder(pObj, rad, rad, h, 20, 2);
993 gluQuadricOrientation(pObj, GLU_INSIDE);
994 gluDisk(pObj, 0.0f, rad, 20, 1);
996 glTranslatef (0.0f, 0.0f, h);
997 gluQuadricOrientation(pObj, GLU_OUTSIDE);
998 gluDisk(pObj, 0.0f, rad, 20, 1);
1000 gluDeleteQuadric(pObj);
1005 GLUquadricObj *pObj;
1010 glShadeModel( GL_SMOOTH );
1011 glColor4f( c.redF(), c.greenF(), c.blueF(), c.alphaF() );
1013 GLMultMatrix(&mat[0][0]);
1016 pObj = gluNewQuadric();
1017 gluQuadricTexture(pObj,
true);
1018 gluCylinder(pObj, rad, rad, h, 20, 2);
1021 gluQuadricOrientation(pObj, GLU_INSIDE);
1022 gluDisk(pObj, 0.0f, rad, 20, 1);
1024 glTranslatef (0.0f, 0.0f, h);
1025 gluQuadricOrientation(pObj, GLU_OUTSIDE);
1026 gluDisk(pObj, 0.0f, rad, 20, 1);
1028 gluDeleteQuadric(pObj);
1033 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1037 glShadeModel( GL_SMOOTH );
1038 glColor4f( 1.0f, 1.0f, 0.0f, 1.0f );
1040 float hdx = (dims[0]/2.0);
1041 float hdy = (dims[1]/2.0);
1042 float hdz = (dims[2]/2.0);
1043 GLMultMatrix(&matrix[0][0]);
1050 glNormal3f(0.0, 0.0, 1.0);
1051 glVertex3f(-hdx, -hdy, hdz);
1052 glVertex3f( hdx, -hdy, hdz);
1053 glVertex3f( hdx, hdy, hdz);
1054 glVertex3f(-hdx, hdy, hdz);
1057 glNormal3f(0.0, 0.0, -1.0);
1058 glVertex3f( hdx, -hdy, -hdz);
1059 glVertex3f(-hdx, -hdy, -hdz);
1060 glVertex3f(-hdx, hdy, -hdz);
1061 glVertex3f( hdx, hdy, -hdz);
1064 glNormal3f(0.0, 1.0, 0.0);
1065 glVertex3f(-hdx, hdy, hdz);
1066 glVertex3f( hdx, hdy, hdz);
1067 glVertex3f( hdx, hdy, -hdz);
1068 glVertex3f(-hdx, hdy, -hdz);
1071 glNormal3f(0.0, -1.0, 0.0);
1072 glVertex3f(-hdx, -hdy, -hdz);
1073 glVertex3f( hdx, -hdy, -hdz);
1074 glVertex3f( hdx, -hdy, hdz);
1075 glVertex3f(-hdx, -hdy, hdz);
1078 glNormal3f(-1.0, 0.0, 0.0);
1079 glVertex3f(-hdx, -hdy, -hdz);
1080 glVertex3f(-hdx, -hdy, hdz);
1081 glVertex3f(-hdx, hdy, hdz);
1082 glVertex3f(-hdx, hdy, -hdz);
1085 glNormal3f(1.0, 0.0, 0.0);
1086 glVertex3f(hdx, -hdy, hdz);
1087 glVertex3f(hdx, -hdy, -hdz);
1088 glVertex3f(hdx, hdy, -hdz);
1089 glVertex3f(hdx, hdy, hdz);
1097 GLMultMatrix(&matrix[0][0]);
1103 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1107 glShadeModel( GL_SMOOTH );
1108 glColor4f( 1.0f, 1.0f, 0.0f, 1.0f );
1110 float dx = fabs( max[0]-min[0] );
1111 float dy = fabs( max[1]-min[1] );
1112 float dz = fabs( max[2]-min[2] );
1113 float hdx = (dx/2.0);
1114 float hdy = (dy/2.0);
1115 float hdz = (dz/2.0);
1116 float minX = qMin(min[0], max[0]);
1117 float minY = qMin(min[1], max[1]);
1118 float minZ = qMin(min[2], max[2]);
1119 glTranslatef( minX+hdx, minY+hdy, minZ+hdz );
1126 glNormal3f(0.0, 0.0, 1.0);
1127 glVertex3f(-hdx, -hdy, hdz);
1128 glVertex3f( hdx, -hdy, hdz);
1129 glVertex3f( hdx, hdy, hdz);
1130 glVertex3f(-hdx, hdy, hdz);
1133 glNormal3f(0.0, 0.0, -1.0);
1134 glVertex3f( hdx, -hdy, -hdz);
1135 glVertex3f(-hdx, -hdy, -hdz);
1136 glVertex3f(-hdx, hdy, -hdz);
1137 glVertex3f( hdx, hdy, -hdz);
1140 glNormal3f(0.0, 1.0, 0.0);
1141 glVertex3f(-hdx, hdy, hdz);
1142 glVertex3f( hdx, hdy, hdz);
1143 glVertex3f( hdx, hdy, -hdz);
1144 glVertex3f(-hdx, hdy, -hdz);
1147 glNormal3f(0.0, -1.0, 0.0);
1148 glVertex3f(-hdx, -hdy, -hdz);
1149 glVertex3f( hdx, -hdy, -hdz);
1150 glVertex3f( hdx, -hdy, hdz);
1151 glVertex3f(-hdx, -hdy, hdz);
1154 glNormal3f(-1.0, 0.0, 0.0);
1155 glVertex3f(-hdx, -hdy, -hdz);
1156 glVertex3f(-hdx, -hdy, hdz);
1157 glVertex3f(-hdx, hdy, hdz);
1158 glVertex3f(-hdx, hdy, -hdz);
1161 glNormal3f(1.0, 0.0, 0.0);
1162 glVertex3f(hdx, -hdy, hdz);
1163 glVertex3f(hdx, -hdy, -hdz);
1164 glVertex3f(hdx, hdy, -hdz);
1165 glVertex3f(hdx, hdy, hdz);
1175 glShadeModel( GL_SMOOTH );
1176 glColor4f( c.redF(), c.greenF(), c.blueF(), c.alphaF() );
1178 GLMultMatrix(&matrix[0][0]);
1183 double s, t, x, y, z, twopi;
1184 real tubeRad = (outRad-innRad)/2.0;
1185 real toruRad = outRad - tubeRad;
1186 twopi = 2 * PI_GRECO;
1187 for (i = 0; i < numc; i++) {
1188 glBegin(GL_QUAD_STRIP);
1189 for (j = 0; j <= numt; j++) {
1190 for (k = 1; k >= 0; k--) {
1191 s = (i + k) % numc + 0.5;
1194 x = (toruRad+tubeRad*cos(s*twopi/numc))*cos(t*(angle)/numt);
1195 y = (toruRad+tubeRad*cos(s*twopi/numc))*sin(t*(angle)/numt);
1196 z = tubeRad * sin(s * twopi / numc);
1197 glVertex3f(x, y, z);
1210 glShadeModel( GL_SMOOTH );
1211 glColor4f( 1.0f, 0.0f, 0.0f, 1.0f );
1215 GLMultMatrix( &tm[0][0] );
1220 double s, t, x, y, z, twopi;
1221 real tubeRad = (outRad-innRad)/2.0;
1222 real toruRad = outRad - tubeRad;
1223 twopi = 2 * PI_GRECO;
1224 for (i = 0; i < numc; i++) {
1225 glBegin(GL_QUAD_STRIP);
1226 for (j = 0; j <= numt; j++) {
1227 for (k = 1; k >= 0; k--) {
1228 s = (i + k) % numc + 0.5;
1231 x = (toruRad+tubeRad*cos(s*twopi/numc))*cos(t*(angle)/numt);
1232 y = (toruRad+tubeRad*cos(s*twopi/numc))*sin(t*(angle)/numt);
1233 z = tubeRad * sin(s * twopi / numc);
1234 glVertex3f(x, y, z);
1245 glColor4f( c.redF(), c.greenF(), c.blueF(), c.alphaF() );
1248 real len = zaxis.
norm();
1252 GLMultMatrix( &tm[0][0] );