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 );
810 QCoreApplication::postEvent(
this,
new ForceRenderWorldUpdateEvent());
813 void RenderWorld::drawDOF(
PhyDOF* dof,
bool drawAxes ) {
816 if ( dof->
joint() == NULL )
return;
822 mat.x_ax = dof->
xAxis();
823 mat.y_ax = dof->
yAxis();
824 mat.z_ax = dof->
axis();
825 mat.w_pos = dof->
centre();
834 rw[ child ]->calculateOBB( dims, minP, maxP );
835 real cube = (dims[0]+dims[1]+dims[2])/3.0;
837 rw[ parent ]->calculateOBB( dims, minP, maxP );
838 real cube2 = (dims[0]+dims[1]+dims[2])/3.0;
839 cube =
min( cube2, cube );
841 real len = cube * 0.70;
842 real rad = len * 0.25;
851 mat.w_pos = wVector(0,0,0);
852 mat = mat * wMatrix( wQuaternion( dof->
axis(), lo ), wVector(0,0,0) );
860 mat.x_ax = dof->
xAxis();
861 mat.y_ax = dof->
yAxis();
862 mat.z_ax = dof->
axis();
863 mat.w_pos = wVector(0,0,0);
865 mat = mat * wMatrix( wQuaternion( dof->
axis(), dof->
position()-0.05 ), wVector(0,0,0) );
867 drawTorus( rad, rad*0.55f, mat, 0.1f, Qt::green );
875 void RenderWorld::drawKineChains() {
878 if (
world() == NULL) {
882 foreach( PhyJoint* jn,
world()->joints()) {
884 float dist1 = 0.0f, dist2 = 0.0f;
885 wVector start = jn->centre();
886 wVector end1 = jn->child()->matrix().w_pos;
887 wVector end2 = start;
889 if ( jn->parent() ) {
890 end2 = jn->parent()->matrix().w_pos;
893 real rad = (dist1 + dist2) * 0.04;
897 QVector<PhyDOF*> ds = jn->dofs();
898 for(
int k=0; k<ds.size(); k++ ) {
899 drawDOF( ds[k],
true );
904 void RenderWorld::customEvent(QEvent* event)
906 if (event->type() == QEvent::User) {
916 glShadeModel( GL_SMOOTH );
917 glColor4f( 0.0f, 1.0f, 0.0f, 1.0f );
921 mat.x_ax = mat.x_ax.
scale( radius );
922 mat.y_ax = mat.y_ax.
scale( radius );
923 mat.z_ax = mat.z_ax.
scale( radius );
925 GLMultMatrix(&mat[0][0]);
928 pObj = gluNewQuadric();
930 gluQuadricTexture(pObj,
true);
931 gluSphere(pObj, 1.0f, 20, 20);
933 gluDeleteQuadric(pObj);
943 glShadeModel( GL_SMOOTH );
944 glColor4f( c.redF(), c.greenF(), c.blueF(), c.alphaF() );
947 glTranslatef( recentre[0], recentre[1], recentre[2] );
950 Vec ax( axis[0], axis[1], axis[2] );
952 glMultMatrixd( quad.
matrix() );
955 pObj = gluNewQuadric();
956 gluQuadricTexture(pObj,
true);
957 gluCylinder(pObj, rad, rad, h, 20, 2);
960 gluQuadricOrientation(pObj, GLU_INSIDE);
961 gluDisk(pObj, 0.0f, rad, 20, 1);
963 glTranslatef (0.0f, 0.0f, h);
964 gluQuadricOrientation(pObj, GLU_OUTSIDE);
965 gluDisk(pObj, 0.0f, rad, 20, 1);
967 gluDeleteQuadric(pObj);
973 if ( h < 0.0001 )
return;
980 glShadeModel( GL_SMOOTH );
981 glColor4f( c.redF(), c.greenF(), c.blueF(), c.alphaF() );
987 GLMultMatrix( &tm[0][0] );
990 pObj = gluNewQuadric();
991 gluQuadricTexture(pObj,
true);
992 gluCylinder(pObj, rad, rad, h, 20, 2);
995 gluQuadricOrientation(pObj, GLU_INSIDE);
996 gluDisk(pObj, 0.0f, rad, 20, 1);
998 glTranslatef (0.0f, 0.0f, h);
999 gluQuadricOrientation(pObj, GLU_OUTSIDE);
1000 gluDisk(pObj, 0.0f, rad, 20, 1);
1002 gluDeleteQuadric(pObj);
1007 GLUquadricObj *pObj;
1012 glShadeModel( GL_SMOOTH );
1013 glColor4f( c.redF(), c.greenF(), c.blueF(), c.alphaF() );
1015 GLMultMatrix(&mat[0][0]);
1018 pObj = gluNewQuadric();
1019 gluQuadricTexture(pObj,
true);
1020 gluCylinder(pObj, rad, rad, h, 20, 2);
1023 gluQuadricOrientation(pObj, GLU_INSIDE);
1024 gluDisk(pObj, 0.0f, rad, 20, 1);
1026 glTranslatef (0.0f, 0.0f, h);
1027 gluQuadricOrientation(pObj, GLU_OUTSIDE);
1028 gluDisk(pObj, 0.0f, rad, 20, 1);
1030 gluDeleteQuadric(pObj);
1035 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1039 glShadeModel( GL_SMOOTH );
1040 glColor4f( 1.0f, 1.0f, 0.0f, 1.0f );
1042 float hdx = (dims[0]/2.0);
1043 float hdy = (dims[1]/2.0);
1044 float hdz = (dims[2]/2.0);
1045 GLMultMatrix(&matrix[0][0]);
1052 glNormal3f(0.0, 0.0, 1.0);
1053 glVertex3f(-hdx, -hdy, hdz);
1054 glVertex3f( hdx, -hdy, hdz);
1055 glVertex3f( hdx, hdy, hdz);
1056 glVertex3f(-hdx, hdy, hdz);
1059 glNormal3f(0.0, 0.0, -1.0);
1060 glVertex3f( hdx, -hdy, -hdz);
1061 glVertex3f(-hdx, -hdy, -hdz);
1062 glVertex3f(-hdx, hdy, -hdz);
1063 glVertex3f( hdx, hdy, -hdz);
1066 glNormal3f(0.0, 1.0, 0.0);
1067 glVertex3f(-hdx, hdy, hdz);
1068 glVertex3f( hdx, hdy, hdz);
1069 glVertex3f( hdx, hdy, -hdz);
1070 glVertex3f(-hdx, hdy, -hdz);
1073 glNormal3f(0.0, -1.0, 0.0);
1074 glVertex3f(-hdx, -hdy, -hdz);
1075 glVertex3f( hdx, -hdy, -hdz);
1076 glVertex3f( hdx, -hdy, hdz);
1077 glVertex3f(-hdx, -hdy, hdz);
1080 glNormal3f(-1.0, 0.0, 0.0);
1081 glVertex3f(-hdx, -hdy, -hdz);
1082 glVertex3f(-hdx, -hdy, hdz);
1083 glVertex3f(-hdx, hdy, hdz);
1084 glVertex3f(-hdx, hdy, -hdz);
1087 glNormal3f(1.0, 0.0, 0.0);
1088 glVertex3f(hdx, -hdy, hdz);
1089 glVertex3f(hdx, -hdy, -hdz);
1090 glVertex3f(hdx, hdy, -hdz);
1091 glVertex3f(hdx, hdy, hdz);
1099 GLMultMatrix(&matrix[0][0]);
1105 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1109 glShadeModel( GL_SMOOTH );
1110 glColor4f( 1.0f, 1.0f, 0.0f, 1.0f );
1112 float dx = fabs( max[0]-min[0] );
1113 float dy = fabs( max[1]-min[1] );
1114 float dz = fabs( max[2]-min[2] );
1115 float hdx = (dx/2.0);
1116 float hdy = (dy/2.0);
1117 float hdz = (dz/2.0);
1118 float minX = qMin(min[0], max[0]);
1119 float minY = qMin(min[1], max[1]);
1120 float minZ = qMin(min[2], max[2]);
1121 glTranslatef( minX+hdx, minY+hdy, minZ+hdz );
1128 glNormal3f(0.0, 0.0, 1.0);
1129 glVertex3f(-hdx, -hdy, hdz);
1130 glVertex3f( hdx, -hdy, hdz);
1131 glVertex3f( hdx, hdy, hdz);
1132 glVertex3f(-hdx, hdy, hdz);
1135 glNormal3f(0.0, 0.0, -1.0);
1136 glVertex3f( hdx, -hdy, -hdz);
1137 glVertex3f(-hdx, -hdy, -hdz);
1138 glVertex3f(-hdx, hdy, -hdz);
1139 glVertex3f( hdx, hdy, -hdz);
1142 glNormal3f(0.0, 1.0, 0.0);
1143 glVertex3f(-hdx, hdy, hdz);
1144 glVertex3f( hdx, hdy, hdz);
1145 glVertex3f( hdx, hdy, -hdz);
1146 glVertex3f(-hdx, hdy, -hdz);
1149 glNormal3f(0.0, -1.0, 0.0);
1150 glVertex3f(-hdx, -hdy, -hdz);
1151 glVertex3f( hdx, -hdy, -hdz);
1152 glVertex3f( hdx, -hdy, hdz);
1153 glVertex3f(-hdx, -hdy, hdz);
1156 glNormal3f(-1.0, 0.0, 0.0);
1157 glVertex3f(-hdx, -hdy, -hdz);
1158 glVertex3f(-hdx, -hdy, hdz);
1159 glVertex3f(-hdx, hdy, hdz);
1160 glVertex3f(-hdx, hdy, -hdz);
1163 glNormal3f(1.0, 0.0, 0.0);
1164 glVertex3f(hdx, -hdy, hdz);
1165 glVertex3f(hdx, -hdy, -hdz);
1166 glVertex3f(hdx, hdy, -hdz);
1167 glVertex3f(hdx, hdy, hdz);
1177 glShadeModel( GL_SMOOTH );
1178 glColor4f( c.redF(), c.greenF(), c.blueF(), c.alphaF() );
1180 GLMultMatrix(&matrix[0][0]);
1185 double s, t, x, y, z, twopi;
1186 real tubeRad = (outRad-innRad)/2.0;
1187 real toruRad = outRad - tubeRad;
1188 twopi = 2 * PI_GRECO;
1189 for (i = 0; i < numc; i++) {
1190 glBegin(GL_QUAD_STRIP);
1191 for (j = 0; j <= numt; j++) {
1192 for (k = 1; k >= 0; k--) {
1193 s = (i + k) % numc + 0.5;
1196 x = (toruRad+tubeRad*cos(s*twopi/numc))*cos(t*(angle)/numt);
1197 y = (toruRad+tubeRad*cos(s*twopi/numc))*sin(t*(angle)/numt);
1198 z = tubeRad * sin(s * twopi / numc);
1199 glVertex3f(x, y, z);
1212 glShadeModel( GL_SMOOTH );
1213 glColor4f( 1.0f, 0.0f, 0.0f, 1.0f );
1217 GLMultMatrix( &tm[0][0] );
1222 double s, t, x, y, z, twopi;
1223 real tubeRad = (outRad-innRad)/2.0;
1224 real toruRad = outRad - tubeRad;
1225 twopi = 2 * PI_GRECO;
1226 for (i = 0; i < numc; i++) {
1227 glBegin(GL_QUAD_STRIP);
1228 for (j = 0; j <= numt; j++) {
1229 for (k = 1; k >= 0; k--) {
1230 s = (i + k) % numc + 0.5;
1233 x = (toruRad+tubeRad*cos(s*twopi/numc))*cos(t*(angle)/numt);
1234 y = (toruRad+tubeRad*cos(s*twopi/numc))*sin(t*(angle)/numt);
1235 z = tubeRad * sin(s * twopi / numc);
1236 glVertex3f(x, y, z);
1247 glColor4f( c.redF(), c.greenF(), c.blueF(), c.alphaF() );
1250 real len = zaxis.
norm();
1254 GLMultMatrix( &tm[0][0] );