yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #06645
[Branch ~yade-dev/yade/trunk] Rev 2630: - Fix stripes display
------------------------------------------------------------
revno: 2630
committer: Bruno Chareyre <bruno.chareyre@xxxxxxxxxxx>
branch nick: yade
timestamp: Tue 2010-12-28 17:01:44 +0100
message:
- Fix stripes display
- Add secondary light and register light parameters
- define specular exponent for smoother display
- define and use GL display lists
modified:
pkg/common/Gl1_Sphere.cpp
pkg/common/Gl1_Sphere.hpp
pkg/common/OpenGLRenderer.cpp
pkg/common/OpenGLRenderer.hpp
--
lp:yade
https://code.launchpad.net/~yade-dev/yade/trunk
Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-dev/yade/trunk/+edit-subscription
=== modified file 'pkg/common/Gl1_Sphere.cpp'
--- pkg/common/Gl1_Sphere.cpp 2010-11-19 12:30:08 +0000
+++ pkg/common/Gl1_Sphere.cpp 2010-12-28 16:01:44 +0000
@@ -1,6 +1,7 @@
/*************************************************************************
-* Copyright (C) 2004 by Olivier Galizzi *
-* olivier.galizzi@xxxxxxx *
+* © 2004 Olivier Galizzi <olivier.galizzi@xxxxxxx> *
+* © 2008 Václav Šmilauer <eudoxos@xxxxxxxx> *
+* © 2008 Bruno Chareyre <bruno.chareyre@xxxxxxxxxxx> *
* *
* This program is free software; it is licensed under the terms of the *
* GNU General Public License v2 or later. See file LICENSE for details. *
@@ -14,61 +15,55 @@
bool Gl1_Sphere::wire;
bool Gl1_Sphere::stripes;
-bool Gl1_Sphere::glutNormalize;
int Gl1_Sphere::glutSlices;
int Gl1_Sphere::glutStacks;
-
+Real Gl1_Sphere::quality;
+bool Gl1_Sphere::localSpecView;
vector<Vector3r> Gl1_Sphere::vertices, Gl1_Sphere::faces;
int Gl1_Sphere::glSphereList=-1;
+int Gl1_Sphere::glGlutSphereList=-1;
+Real Gl1_Sphere::prevQuality=0;
void Gl1_Sphere::go(const shared_ptr<Shape>& cm, const shared_ptr<State>& ,bool wire2, const GLViewInfo&)
{
+ glClearDepth(1.0f);
+ glEnable(GL_NORMALIZE);
+ GLfloat glutMatSpecular[4]={0.5,0.5,0.5,1.0};
+ GLfloat glutMatEmit[4]={0.2,0.2,0.2,1.0};
+ glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,glutMatSpecular);
+ glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,glutMatEmit);
+ glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 80);
Real r=(static_cast<Sphere*>(cm.get()))->radius;
- //glMaterialv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, Vector3f(cm->color[0],cm->color[1],cm->color[2]));
+
glColor3v(cm->color);
- if(glutNormalize) glPushAttrib(GL_NORMALIZE); // as per http://lists.apple.com/archives/Mac-opengl/2002/Jul/msg00085.html
- if (wire || wire2) glutWireSphere(r,glutSlices,glutStacks);
- else {
- if(stripes) { glScalef(r,r,r); drawSphere();}
- else { glutSolidSphere(r,glutSlices,glutStacks);}
- }
- if(glutNormalize) glPopAttrib();
+ if (wire || wire2) glutWireSphere(r,glutSlices,glutStacks);
+ else {
+ initGlLists();
+ glScalef(r,r,r);
+ if(stripes) glCallList(glSphereList);
+ else glCallList(glGlutSphereList);
+ }
return;
}
YADE_PLUGIN((Gl1_Sphere));
-
-/***************************** WARNING *********************
-***** The following code was written by Olivier Galizzi ****
-************ and hasn't been properly reviewed *************/
-
-// https://blueprints.launchpad.net/yade/+spec/sphere-gl-stripes
-
-void Gl1_Sphere::drawSphere(){
- if(glSphereList<0) initGlLists();
- glShadeModel(GL_SMOOTH);
- //glScalef(radius,radius,radius);
- glCallList(glSphereList);
-}
-
void Gl1_Sphere::subdivideTriangle(Vector3r& v1,Vector3r& v2,Vector3r& v3, int depth){
- Vector3r v12,v23,v31;
if (depth==0){
Vector3r v = (v1+v2+v3)/3.0;
Real angle = atan(v[2]/v[0])/v.norm();
- GLfloat matAmbient[4];
+ GLfloat matEmit[4];
if (angle>-Mathr::PI/6.0 && angle<=Mathr::PI/6.0){
- matAmbient[0] = .3;
- matAmbient[1] = .3;
- matAmbient[2] = .3;
- matAmbient[3] = 1;
+ matEmit[0] = 0.4;
+ matEmit[1] = 0.4;
+ matEmit[2] = 0.4;
+ matEmit[3] = 1.f;
}else{
- matAmbient[0] = 0.0;
- matAmbient[1] = 0.0;
- matAmbient[2] = 0.0;
- matAmbient[3] = 0;
+ matEmit[0] = 0.2;
+ matEmit[1] = 0.2;
+ matEmit[2] = 0.2;
+ matEmit[3] = 1.f;
}
- glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,matAmbient);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, matEmit);
glBegin(GL_TRIANGLES);
glNormal3v(v3); glVertex3v(v3);
glNormal3v(v2); glVertex3v(v2);
@@ -76,9 +71,9 @@
glEnd();
return;
}
- v12 = v1+v2;
- v23 = v2+v3;
- v31 = v3+v1;
+ Vector3r v12 = v1+v2;
+ Vector3r v23 = v2+v3;
+ Vector3r v31 = v3+v1;
v12.normalize();
v23.normalize();
v31.normalize();
@@ -88,52 +83,64 @@
subdivideTriangle(v12,v23,v31,depth-1);
}
-void Gl1_Sphere::initGlLists(void){
- Real X = 0.525731112119133606;
- Real Z = 0.850650808352039932;
- vertices.push_back(Vector3r(-X,0,Z));
- vertices.push_back(Vector3r(X,0,Z));
- vertices.push_back(Vector3r(-X,0,-Z));
- vertices.push_back(Vector3r(X,0,-Z));
- vertices.push_back(Vector3r(0,Z,X));
- vertices.push_back(Vector3r(0,Z,-X));
- vertices.push_back(Vector3r(0,-Z,X));
- vertices.push_back(Vector3r(0,-Z,-X));
- vertices.push_back(Vector3r(Z,X,0));
- vertices.push_back(Vector3r(-Z,X,0));
- vertices.push_back(Vector3r(Z,-X,0));
- vertices.push_back(Vector3r(-Z,-X,0));
-
- faces.push_back(Vector3r(0,4,1));
- faces.push_back(Vector3r(0,9,4));
- faces.push_back(Vector3r(9,5,4));
- faces.push_back(Vector3r(4,5,8));
- faces.push_back(Vector3r(4,8,1));
- faces.push_back(Vector3r(8,10,1));
- faces.push_back(Vector3r(8,3,10));
- faces.push_back(Vector3r(5,3,8));
- faces.push_back(Vector3r(5,2,3));
- faces.push_back(Vector3r(2,7,3));
- faces.push_back(Vector3r(7,10,3));
- faces.push_back(Vector3r(7,6,10));
- faces.push_back(Vector3r(7,11,6));
- faces.push_back(Vector3r(11,0,6));
- faces.push_back(Vector3r(0,1,6));
- faces.push_back(Vector3r(6,1,10));
- faces.push_back(Vector3r(9,0,11));
- faces.push_back(Vector3r(9,11,2));
- faces.push_back(Vector3r(9,2,5));
- faces.push_back(Vector3r(7,2,11));
-
- glSphereList = glGenLists(1);
- glNewList(glSphereList,GL_COMPILE);
- glEnable(GL_LIGHTING);
- glShadeModel(GL_SMOOTH);
- // render the sphere now
- for(int i=0;i<20;i++)
- subdivideTriangle(vertices[(unsigned int)faces[i][0]],vertices[(unsigned int)faces[i][1]],vertices[(unsigned int)faces[i][2]],1);
- //drawSphere();
- glEndList();
+void Gl1_Sphere::initGlLists(){
+ //Generate the "stripes" dislpay list, only once
+ if (glSphereList<0) {
+ Real X = 0.525731112119133606;
+ Real Z = 0.850650808352039932;
+ vertices.push_back(Vector3r(-X,0,Z));
+ vertices.push_back(Vector3r(X,0,Z));
+ vertices.push_back(Vector3r(-X,0,-Z));
+ vertices.push_back(Vector3r(X,0,-Z));
+ vertices.push_back(Vector3r(0,Z,X));
+ vertices.push_back(Vector3r(0,Z,-X));
+ vertices.push_back(Vector3r(0,-Z,X));
+ vertices.push_back(Vector3r(0,-Z,-X));
+ vertices.push_back(Vector3r(Z,X,0));
+ vertices.push_back(Vector3r(-Z,X,0));
+ vertices.push_back(Vector3r(Z,-X,0));
+ vertices.push_back(Vector3r(-Z,-X,0));
+
+ faces.push_back(Vector3r(0,4,1));
+ faces.push_back(Vector3r(0,9,4));
+ faces.push_back(Vector3r(9,5,4));
+ faces.push_back(Vector3r(4,5,8));
+ faces.push_back(Vector3r(4,8,1));
+ faces.push_back(Vector3r(8,10,1));
+ faces.push_back(Vector3r(8,3,10));
+ faces.push_back(Vector3r(5,3,8));
+ faces.push_back(Vector3r(5,2,3));
+ faces.push_back(Vector3r(2,7,3));
+ faces.push_back(Vector3r(7,10,3));
+ faces.push_back(Vector3r(7,6,10));
+ faces.push_back(Vector3r(7,11,6));
+ faces.push_back(Vector3r(11,0,6));
+ faces.push_back(Vector3r(0,1,6));
+ faces.push_back(Vector3r(6,1,10));
+ faces.push_back(Vector3r(9,0,11));
+ faces.push_back(Vector3r(9,11,2));
+ faces.push_back(Vector3r(9,2,5));
+ faces.push_back(Vector3r(7,2,11));
+
+ glSphereList = glGenLists(1);
+ glNewList(glSphereList,GL_COMPILE);
+ glEnable(GL_LIGHTING);
+ glShadeModel(GL_SMOOTH);
+ // render the sphere now
+ for(int i=0;i<20;i++)
+ subdivideTriangle(vertices[(unsigned int)faces[i][0]],vertices[(unsigned int)faces[i][1]],vertices[(unsigned int)faces[i][2]],1);
+ glEndList();
+ }
+ //Generate the "no-stripes" display list, each time quality is modified
+ if (glGlutSphereList<0 || abs(quality-prevQuality)>0.001 /*detect any meaningfull change in quality to regenerate GL primitives*/) {
+ glGlutSphereList = glGenLists(1);
+ glNewList(glGlutSphereList,GL_COMPILE);
+ glEnable(GL_LIGHTING);
+ glShadeModel(GL_SMOOTH);
+ glutSolidSphere(1.0,quality*glutSlices,quality*glutStacks);
+ glEndList();
+ prevQuality=quality;
+ }
}
#endif /* YADE_OPENGL */
=== modified file 'pkg/common/Gl1_Sphere.hpp'
--- pkg/common/Gl1_Sphere.hpp 2010-11-07 11:46:20 +0000
+++ pkg/common/Gl1_Sphere.hpp 2010-12-28 16:01:44 +0000
@@ -1,6 +1,7 @@
/*************************************************************************
-* Copyright (C) 2004 by Olivier Galizzi *
-* olivier.galizzi@xxxxxxx *
+* © 2004 Olivier Galizzi <olivier.galizzi@xxxxxxx> *
+* © 2008 Václav Šmilauer <eudoxos@xxxxxxxx> *
+* © 2008 Bruno Chareyre <bruno.chareyre@xxxxxxxxxxx> *
* *
* This program is free software; it is licensed under the terms of the *
* GNU General Public License v2 or later. See file LICENSE for details. *
@@ -10,22 +11,26 @@
#include<yade/pkg/common/GLDrawFunctors.hpp>
-class Gl1_Sphere : public GlShapeFunctor{
+class Gl1_Sphere : public GlShapeFunctor{
private:
// for stripes
static vector<Vector3r> vertices, faces;
static int glSphereList;
+ static int glGlutSphereList;
void subdivideTriangle(Vector3r& v1,Vector3r& v2,Vector3r& v3, int depth);
- void drawSphere(void);
- void initGlLists(void);
+// void drawSphere(const Vector3r& color);
+ void initGlLists();
+ //for regenerating glutSphere list if needed
+ static Real prevQuality;
public:
virtual void go(const shared_ptr<Shape>&, const shared_ptr<State>&,bool,const GLViewInfo&);
YADE_CLASS_BASE_DOC_STATICATTRS(Gl1_Sphere,GlShapeFunctor,"Renders :yref:`Sphere` object",
+ ((Real,quality,1.0,,"Change discretization level of spheres. quality>1 for better image quality, at the price of more cpu/gpu usage, 0<quality<1 for faster rendering. This unique factor mutiplies :yref:`Gl1_Sphere::glutSlices` and :yref:`Gl1_Sphere::glutStacks`"))
((bool,wire,false,,"Only show wireframe (controlled by ``glutSlices`` and ``glutStacks``."))
((bool,stripes,false,,"In non-wire rendering, show stripes clearly showing particle rotation."))
- ((bool,glutNormalize,true,,"Fix normals for non-wire rendering; see http://lists.apple.com/archives/Mac-opengl/2002/Jul/msg00085.html"))
- ((int,glutSlices,12,,"Number of sphere slices; not used with ``stripes`` (see `glut{Solid,Wire}Sphere reference <http://www.opengl.org/documentation/specs/glut/spec3/node81.html>`_)"))
- ((int,glutStacks,6,,"Number of sphere stacks; not used with ``stripes`` (see `glut{Solid,Wire}Sphere reference <http://www.opengl.org/documentation/specs/glut/spec3/node81.html>`_)"))
+ ((bool,localSpecView,true,,"Compute specular light in local eye coordinate system."))
+ ((int,glutSlices,12,(Attr::noSave | Attr::readonly),"Base number of sphere slices, multiplied by :yref:`Gl1_Sphere::quality` before use); not used with ``stripes`` (see `glut{Solid,Wire}Sphere reference <http://www.opengl.org/documentation/specs/glut/spec3/node81.html>`_)"))
+ ((int,glutStacks,6,(Attr::noSave | Attr::readonly),"Base number of sphere stacks, multiplied by :yref:`Gl1_Sphere::quality` before use; not used with ``stripes`` (see `glut{Solid,Wire}Sphere reference <http://www.opengl.org/documentation/specs/glut/spec3/node81.html>`_)"))
);
RENDERS(Sphere);
};
=== modified file 'pkg/common/OpenGLRenderer.cpp'
--- pkg/common/OpenGLRenderer.cpp 2010-11-30 13:51:41 +0000
+++ pkg/common/OpenGLRenderer.cpp 2010-12-28 16:01:44 +0000
@@ -98,7 +98,7 @@
#ifdef YADE_SUBDOMAINS
int subDom; Body::id_t localId;
boost::tie(subDom,localId)=scene->bodies->subDomId2domNumLocalId(b->subDomId);
- if(subDomMask!=0 && (((1<<subDom) & subDomMask)==0)) bodyDisp[id].isDisplayed=false;
+ if(subDomMask!=0 && (((1<<subDom) & subDomMask)==0)) bodyDisp[id].isDisplayed=false;
#endif
// if no scaling and no periodic, return quickly
if(!(scaleDisplacements||scaleRotations||scene->isPeriodic)){ bodyDisp[id].pos=pos; bodyDisp[id].ori=ori; continue; }
@@ -130,10 +130,11 @@
}
void OpenGLRenderer::resetSpecularEmission(){
- const GLfloat specular[4]={.3,.3,.3,1};
+ const GLfloat specular[4]={.3,.03,.03,0.1};
const GLfloat emission[4]={0,0,0,0};
glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,specular);
glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,emission);
+ glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0);
}
void OpenGLRenderer::render(const shared_ptr<Scene>& _scene,Body::id_t selection){
@@ -158,7 +159,7 @@
Real now=TimingInfo::getNow(/*even if timing is disabled*/true)*1e-9;
highlightEmission0[0]=highlightEmission0[1]=highlightEmission0[2]=.8*normSquare(now,1);
highlightEmission1[0]=highlightEmission1[1]=highlightEmission0[2]=.5*normSaw(now,2);
-
+
// clipping
assert(clipPlaneNormals.size()==(size_t)numClipPlanes);
for(size_t i=0;i<(size_t)numClipPlanes; i++){
@@ -170,26 +171,42 @@
if(clipPlaneActive[i]) clipPlaneNormals[i]=clipPlaneSe3[i].orientation*Vector3r(0,0,1);
/* glBegin(GL_LINES);glVertex3v(clipPlaneSe3[i].position);glVertex3v(clipPlaneSe3[i].position+clipPlaneNormals[i]);glEnd(); */
}
-
// set displayed Se3 of body (scaling) and isDisplayed (clipping)
setBodiesDispInfo();
- // set light source
+ glClearColor(bgColor[0],bgColor[1],bgColor[2],1.0);
+
+ // set light sources
+ glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,1); // important: do lighting calculations on both sides of polygons
+
const GLfloat pos[4] = {lightPos[0],lightPos[1],lightPos[2],1.0};
- const GLfloat ambientColor[4]={0.5,0.5,0.5,1.0};
- //const GLfloat specularColor[4]={0.5,0.5,0.5,1.0};
- glClearColor(bgColor[0],bgColor[1],bgColor[2],1.0);
+ const GLfloat ambientColor[4]={0.2,0.2,0.2,1.0};
+ const GLfloat specularColor[4]={1,1,1,1.f};
+ const GLfloat diffuseLight[4] = { lightColor[0], lightColor[1], lightColor[2], 1.0f };
glLightfv(GL_LIGHT0, GL_POSITION,pos);
- glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambientColor);
- glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,1); // important: do lighting calculations on both sides of polygons
- //glLightfv(GL_LIGHT0, GL_SPECULAR, specularColor);
- glEnable(GL_LIGHT0);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, specularColor);
+ glLightfv(GL_LIGHT0, GL_AMBIENT, ambientColor);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
+ if (light1) glEnable(GL_LIGHT0); else glDisable(GL_LIGHT0);
+
+ const GLfloat pos2[4] = {light2Pos[0],light2Pos[1],light2Pos[2],1.0};
+ const GLfloat ambientColor2[4]={0.0,0.0,0.0,1.0};
+ const GLfloat specularColor2[4]={1,1,0.6,1.f};
+ const GLfloat diffuseLight2[4] = { light2Color[0], light2Color[1], light2Color[2], 1.0f };
+ glLightfv(GL_LIGHT1, GL_POSITION,pos2);
+ glLightfv(GL_LIGHT1, GL_SPECULAR, specularColor2);
+ glLightfv(GL_LIGHT1, GL_AMBIENT, ambientColor2);
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuseLight2);
+ if (light2) glEnable(GL_LIGHT1); else glDisable(GL_LIGHT1);
+
glEnable(GL_LIGHTING);
glEnable(GL_CULL_FACE);
// http://www.sjbaker.org/steve/omniv/opengl_lighting.html
+ glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
- glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
+ //Shared material settings
+ glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 40);
resetSpecularEmission();
@@ -203,7 +220,7 @@
if (intrPhys) renderIPhys();
FOREACH(const shared_ptr<GlExtraDrawer> d, extraDrawers){
- if(d->dead) continue;
+ if(d->dead) continue;
glPushMatrix();
d->scene=scene.get();
d->render();
@@ -228,9 +245,9 @@
}
}
-void OpenGLRenderer::renderDOF_ID(){
- const GLfloat ambientColorSelected[4]={10.0,0.0,0.0,1.0};
- const GLfloat ambientColorUnselected[4]={0.5,0.5,0.5,1.0};
+void OpenGLRenderer::renderDOF_ID(){
+ const GLfloat ambientColorSelected[4]={10.0,0.0,0.0,1.0};
+ const GLfloat ambientColorUnselected[4]={0.5,0.5,0.5,1.0};
FOREACH(const shared_ptr<Body> b, *scene->bodies){
if(!b) continue;
if(b->shape && ((b->getGroupMask() & mask) || b->getGroupMask()==0)){
@@ -254,7 +271,7 @@
}
}
-void OpenGLRenderer::renderIGeom(){
+void OpenGLRenderer::renderIGeom(){
geomDispatcher.scene=scene.get(); geomDispatcher.updateScenePtr();
{
boost::mutex::scoped_lock lock(scene->interactions->drawloopmutex);
@@ -268,7 +285,7 @@
}
-void OpenGLRenderer::renderIPhys(){
+void OpenGLRenderer::renderIPhys(){
physDispatcher.scene=scene.get(); physDispatcher.updateScenePtr();
{
boost::mutex::scoped_lock lock(scene->interactions->drawloopmutex);
@@ -283,7 +300,7 @@
}
}
-void OpenGLRenderer::renderBound(){
+void OpenGLRenderer::renderBound(){
boundDispatcher.scene=scene.get(); boundDispatcher.updateScenePtr();
FOREACH(const shared_ptr<Body>& b, *scene->bodies){
@@ -332,7 +349,7 @@
bool highlight=(b->id==selId || (b->clumpId>=0 && b->clumpId==selId) || b->shape->highlight);
glPushMatrix();
- AngleAxisr aa(ori);
+ AngleAxisr aa(ori);
glTranslatef(pos[0],pos[1],pos[2]);
glRotatef(aa.angle()*Mathr::RAD_TO_DEG,aa.axis()[0],aa.axis()[1],aa.axis()[2]);
if(highlight){
=== modified file 'pkg/common/OpenGLRenderer.hpp'
--- pkg/common/OpenGLRenderer.hpp 2010-12-10 15:07:56 +0000
+++ pkg/common/OpenGLRenderer.hpp 2010-12-28 16:01:44 +0000
@@ -63,7 +63,7 @@
vector<string>
// stateFunctorNames,
boundFunctorNames,
- shapeFunctorNames,
+ shapeFunctorNames,
geomFunctorNames,
physFunctorNames;
@@ -71,13 +71,13 @@
public :
// updated after every call to render
- shared_ptr<Scene> scene;
+ shared_ptr<Scene> scene;
void init();
void initgl();
void render(const shared_ptr<Scene>& scene, Body::id_t selection=Body::id_t(-1));
void pyRender(){render(Omega::instance().getScene());}
-
+
void renderDOF_ID();
void renderIPhys();
void renderIGeom();
@@ -90,8 +90,13 @@
((Vector3r,dispScale,((void)"disable scaling",Vector3r::Ones()),,"Artificially enlarge (scale) dispalcements from bodies' :yref:`reference positions<State.refPos>` by this relative amount, so that they become better visible (independently in 3 dimensions). Disbled if (1,1,1)."))
((Real,rotScale,((void)"disable scaling",1.),,"Artificially enlarge (scale) rotations of bodies relative to their :yref:`reference orientation<State.refOri>`, so the they are better visible."))
((Vector3r,lightPos,Vector3r(75,130,0),,"Position of OpenGL light source in the scene."))
+ ((Vector3r,light2Pos,Vector3r(-130,75,30),,"Position of secondary OpenGL light source in the scene."))
+ ((Vector3r,lightColor,Vector3r(0.8,0.8,0.8),,"Per-color intensity of primary light (RGB)."))
+ ((Vector3r,light2Color,Vector3r(0.5,0.5,0.1),,"Per-color intensity of secondary light (RGB)."))
((Vector3r,bgColor,Vector3r(.2,.2,.2),,"Color of the backgroud canvas (RGB)"))
((bool,wire,false,,"Render all bodies with wire only (faster)"))
+ ((bool,light1,true,,"Turn light 1 on."))
+ ((bool,light2,true,,"Turn light 2 on."))
((bool,dof,false,,"Show which degrees of freedom are blocked for each body"))
((bool,id,false,,"Show body id's"))
((bool,bound,false,,"Render body :yref:`Bound`"))