Author: eudoxos
Date: 2009-08-07 12:27:49 +0200 (Fri, 07 Aug 2009)
New Revision: 1929
Modified:
trunk/extra/PeriodicInsertionSortCollider.cpp
trunk/extra/PeriodicInsertionSortCollider.hpp
trunk/gui/qt3/GLViewer.cpp
trunk/gui/qt3/GLViewer.hpp
trunk/pkg/common/Engine/MetaEngine/InteractionDispatchers.cpp
trunk/pkg/common/Engine/MetaEngine/InteractionGeometryMetaEngine.cpp
trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp
trunk/pkg/common/RenderingEngine/OpenGLRenderingEngine/OpenGLRenderingEngine.cpp
trunk/pkg/common/RenderingEngine/OpenGLRenderingEngine/OpenGLRenderingEngine.hpp
trunk/scripts/test/periodic-simple.py
Log:
1. Beta version of periodic boundary conditions (try
scripts/test/periodic-simple.py
Modified: trunk/extra/PeriodicInsertionSortCollider.cpp
===================================================================
--- trunk/extra/PeriodicInsertionSortCollider.cpp 2009-08-06 22:05:28 UTC
(rev 1928)
+++ trunk/extra/PeriodicInsertionSortCollider.cpp 2009-08-07 10:27:49 UTC
(rev 1929)
@@ -18,34 +18,33 @@
YADE_PLUGIN((PeriodicInsertionSortCollider))
CREATE_LOGGER(PeriodicInsertionSortCollider);
-Real PeriodicInsertionSortCollider::cellWrap(const Real x, const Real x0,
const Real x1, long& period){
+Real PeriodicInsertionSortCollider::cellWrap(const Real x, const Real x0,
const Real x1, int& period){
Real xNorm=(x-x0)/(x1-x0);
- period=(long)floor(xNorm); // FIXME: some people say this is very slow
+ period=(int)floor(xNorm); // FIXME: some people say this is very slow
return x0+(xNorm-period)*(x1-x0);
}
+Real PeriodicInsertionSortCollider::cellWrapRel(const Real x, const Real x0,
const Real x1){
+ Real xNorm=(x-x0)/(x1-x0);
+ return (xNorm-floor(xNorm))*(x1-x0);
+}
+
// return true if bodies bb overlap in all 3 dimensions
bool PeriodicInsertionSortCollider::spatialOverlap(body_id_t id1, body_id_t
id2,MetaBody* rb, Vector3<int>& periods) const {
- assert(id1!=id2) // programming error, or weird bodies (too large?)
+ assert(id1!=id2); // programming error, or weird bodies (too large?)
for(int axis=0; axis<3; axis++){
Real dim=rb->cellMax[axis]-rb->cellMin[axis];
- // wrap all 4 numbers to the period starting and the most
minimal number
- #if 0
- Real
mn=min(minima[3*id1+axis],minima[3*id2+axis])-0.001*dim; // avoid rounding
issues
- Real mx=max(maxima[3*id1+axis],maxima[3*id2+axis]);
- TRVAR2(mn,mx);
- #endif
// too big bodies in interaction
assert(maxima[3*id1+axis]-minima[3*id1+axis]<.99*dim);
assert(maxima[3*id2+axis]-minima[3*id2+axis]<.99*dim);
// different way: find body of which when taken as period start
will make the gap smaller
- long p;
- Real mn1w=cellWrap(minima[3*id1+axis],0,dim,p),
mn2w=cellWrap(minima[3*id2+axis],0,dim,p);
- Real wMn=(abs(mn2w-mn1w)<dim/2 ? mn1w : mn2w) -/*avoid rounding
issues*/1e-4*dim; /* selected wrap base */
+ Real m1=minima[3*id1+axis],m2=minima[3*id2+axis];
+ Real wMn=(cellWrapRel(m1,m2,m2+dim)<cellWrapRel(m2,m1,m1+dim))
? m2 : m1;
//TRVAR3(id1,id2,axis);
//TRVAR4(minima[3*id1+axis],maxima[3*id1+axis],minima[3*id2+axis],maxima[3*id2+axis]);
- //TRVAR3(mn1w,mn2w,wMn);
- long pmn1,pmx1,pmn2,pmx2;
+ //TRVAR2(cellWrapRel(m1,m2,m2+dim),cellWrapRel(m2,m1,m1+dim));
+ //TRVAR3(m1,m2,wMn);
+ int pmn1,pmx1,pmn2,pmx2;
Real mn1=cellWrap(minima[3*id1+axis],wMn,wMn+dim,pmn1),
mx1=cellWrap(maxima[3*id1+axis],wMn,wMn+dim,pmx1);
Real mn2=cellWrap(minima[3*id2+axis],wMn,wMn+dim,pmn2),
mx2=cellWrap(maxima[3*id2+axis],wMn,wMn+dim,pmx2);
//TRVAR4(mn1,mx1,mn2,mx2);
@@ -93,16 +92,17 @@
long i_1=v.norm(i-1), loIdx_1=v.norm(loIdx-1);
// fast test, if the first pair is inverted
if(v[i].coord<v[i_1].coord-(i_1==loIdx_1 ? v.cellDim :
0) ){
- // v.dump(cerr);
+ //v.dump(cerr);
+ if(i==loIdx && v[i].coord<v.cellMin){
v[i].period-=1; v[i].coord+=v.cellDim; loIdx=v.norm(loIdx+1); }
hadInversion=true; Bound vi=v[i]; int j; const
bool viBB=vi.flags.hasBB;
for(j=i_1;
vi.coord<v[j].coord-(j==v.norm(loIdx-1) ? v.cellDim : 0); j=v.norm(j-1)) {
//{ Bound vj1=v[v.norm(j+1)];
v[v.norm(j+1)]=vi;
//v[v.norm(j+1)]=vj1; }
- long j1=v.norm(j+1); // j2=v.norm(j+2);
- //LOG_TRACE("Inversion of
i="<<i<<"(#"<<vi.id<<" @ "<<vi.coord<<") j="<<j<<"(#"<<v[j].id<<" @
"<<v[j].coord<<"); j1="<<j1<<", j2="<<j2); v.dump(cerr);
+ long j1=v.norm(j+1);
+ //LOG_TRACE("Inversion of
i="<<i<<"(#"<<vi.id<<" @ "<<vi.coord<<") j="<<j<<"(#"<<v[j].id<<" @
"<<v[j].coord<<"); j1="<<j1); v.dump(cerr);
v[j1]=v[j];
//if(v[j1].coord>v.cellMax &&
j2==loIdx){ v[j1].period+=1; v[j1].coord-=v.cellDim; loIdx=v.norm(loIdx-1); }
- if(j1==loIdx) {
assert(v[j1].coord>v.cellMax); v[j1].period+=1; v[j1].coord-=v.cellDim;
loIdx=v.norm(loIdx-1); }
+ if(j1==loIdx) {
assert(v[j1].coord>=v.cellMax); v[j1].period+=1; v[j1].coord-=v.cellDim;
loIdx=v.norm(loIdx-1); }
else if (vi.coord<v.cellMin &&
j==loIdx){ vi.period-=1; vi.coord+=v.cellDim; loIdx=v.norm(loIdx+1); }
if(doCollide && viBB &&
v[j].flags.hasBB) handleBoundInversion(vi.id,v[j].id,interactions,rb);
//v.dump(cerr);
@@ -163,6 +163,13 @@
XX[i].coord=((XX[i].flags.hasBB=(bool)bvXX) ?
(XX[i].flags.isMin ? bvXX->min[0] : bvXX->max[0]) :
(Body::byId(idXX,rb)->physicalParameters->se3.position[0])) -
XX.cellDim*XX[i].period;
YY[i].coord=((YY[i].flags.hasBB=(bool)bvYY) ?
(YY[i].flags.isMin ? bvYY->min[1] : bvYY->max[1]) :
(Body::byId(idYY,rb)->physicalParameters->se3.position[1])) -
YY.cellDim*YY[i].period;
ZZ[i].coord=((ZZ[i].flags.hasBB=(bool)bvZZ) ?
(ZZ[i].flags.isMin ? bvZZ->min[2] : bvZZ->max[2]) :
(Body::byId(idZZ,rb)->physicalParameters->se3.position[2])) -
ZZ.cellDim*ZZ[i].period;
+ // PERI: at the initial step, fix periods of bodies
+ // doInitSort is also called when bodies are just
added; changing the period should not have influence here, though.
+ if(doInitSort){
+ if(XX[i].coord<XX.cellMin ||
XX[i].coord>=XX.cellMax)
XX[i].coord=cellWrap(XX[i].coord,XX.cellMin,XX.cellMax,XX[i].period);
+ if(YY[i].coord<XX.cellMin ||
YY[i].coord>=YY.cellMax)
YY[i].coord=cellWrap(YY[i].coord,YY.cellMin,YY.cellMax,YY[i].period);
+ if(ZZ[i].coord<ZZ.cellMin ||
ZZ[i].coord>=ZZ.cellMax)
ZZ[i].coord=cellWrap(ZZ[i].coord,ZZ.cellMin,ZZ.cellMax,ZZ[i].period);
+ }
// and for each body, copy its minima and maxima arrays
as well
if(XX[i].flags.isMin){
BOOST_STATIC_ASSERT(sizeof(Vector3r)==3*sizeof(Real));
@@ -171,15 +178,15 @@
}
else{ const Vector3r&
pos=Body::byId(idXX,rb)->physicalParameters->se3.position;
memcpy(&minima[3*idXX],pos,3*sizeof(Real));
memcpy(&maxima[3*idXX],pos,3*sizeof(Real)); }
// PERI: add periods, but such that both
minimum and maximum is within the cell!
- Vector3r
period(XX[i].period*XX.cellDim,YY[i].period*YY.cellDim,ZZ[i].period*ZZ.cellDim);
- *(Vector3r*)(&minima[3*idXX])+=period;
*(Vector3r*)(&maxima[3*idXX])+=period; //ugh
+ //Vector3r
period(XX[i].period*XX.cellDim,YY[i].period*YY.cellDim,ZZ[i].period*ZZ.cellDim);
+ //*(Vector3r*)(&minima[3*idXX])+=period;
*(Vector3r*)(&maxima[3*idXX])+=period; //ugh
}
}
// process interactions that the constitutive law asked to be erased
interactions->erasePending(*this,rb);
- LOG_DEBUG("Step "<<Omega::instance().getCurrentIteration());
- ZZ.dump(cerr);
+ //LOG_TRACE("Step "<<Omega::instance().getCurrentIteration());
+ //ZZ.dump(cerr);
// XX.dump(cerr); YY.dump(cerr); ZZ.dump(cerr);
// sort
@@ -188,13 +195,10 @@
insertionSort(XX,interactions,rb);
insertionSort(YY,interactions,rb); insertionSort(ZZ,interactions,rb);
}
else {
- if(doInitSort){
- // the initial sort is in independent in 3
dimensions, may be run in parallel
- // it seems that there is no time gain running
this in parallel, though
- std::sort(XX.vec.begin(),XX.vec.end());
std::sort(YY.vec.begin(),YY.vec.end()); std::sort(ZZ.vec.begin(),ZZ.vec.end());
- } else { // sortThenCollide
- insertionSort(XX,interactions,rb,false);
insertionSort(YY,interactions,rb,false);
insertionSort(ZZ,interactions,rb,false);
- }
+ // the initial sort is in independent in 3 dimensions,
may be run in parallel
+ // it seems that there is no time gain running this in
parallel, though
+ std::sort(XX.vec.begin(),XX.vec.end());
std::sort(YY.vec.begin(),YY.vec.end()); std::sort(ZZ.vec.begin(),ZZ.vec.end());
+
// traverse the container along requested axis
assert(sortAxis==0 || sortAxis==1 || sortAxis==2);
VecBounds& V=(sortAxis==0?XX:(sortAxis==1?YY:ZZ));
@@ -219,7 +223,7 @@
*/
// TRVAR3(i,iid,V[i].coord);
// go up until we meet the upper bound
- for(size_t j=i+1; V[j].id!=iid && /* handle
case 2. of swapped min/max */ j<2*(size_t)nBodies; j++){
+ for(size_t j=i+1; /* handle case 2. of swapped
min/max */ j<2*(size_t)nBodies && V[j].id!=iid; j++){
const body_id_t& jid=V[j].id;
/// Not sure why this doesn't work. If
this condition is commented out, we have exact same interactions as from
SpatialQuickSort. Otherwise some interactions are missing!
// skip bodies with smaller (arbitrary,
could be greater as well) id, since they will detect us when their turn comes
Modified: trunk/extra/PeriodicInsertionSortCollider.hpp
===================================================================
--- trunk/extra/PeriodicInsertionSortCollider.hpp 2009-08-06 22:05:28 UTC
(rev 1928)
+++ trunk/extra/PeriodicInsertionSortCollider.hpp 2009-08-07 10:27:49 UTC
(rev 1929)
@@ -43,8 +43,10 @@
void insertionSort(VecBounds& v,InteractionContainer*,MetaBody*,bool
doCollide=true);
void
handleBoundInversion(body_id_t,body_id_t,InteractionContainer*,MetaBody*);
bool spatialOverlap(body_id_t,body_id_t, MetaBody*, Vector3<int>&)
const;
- static Real cellWrap(Real,Real,Real,long&);
+ static Real cellWrap(const Real, const Real, const Real, int&);
+ static Real cellWrapRel(const Real, const Real, const Real);
+
public:
//! axis for the initial sort
int sortAxis;
Modified: trunk/gui/qt3/GLViewer.cpp
===================================================================
--- trunk/gui/qt3/GLViewer.cpp 2009-08-06 22:05:28 UTC (rev 1928)
+++ trunk/gui/qt3/GLViewer.cpp 2009-08-07 10:27:49 UTC (rev 1929)
@@ -323,6 +323,18 @@
else if(e->key()!=Qt::Key_Escape && e->key()!=Qt::Key_Space)
QGLViewer::keyPressEvent(e);
updateGL();
}
+/* Center the scene such that periodic cell is contained in the view */
+void GLViewer::centerPeriodic(){
+ MetaBody* rb=Omega::instance().getRootBody().get();
+ assert(rb->isPeriodic);
+ Vector3r center=.5*(rb->cellMin+rb->cellMax);
+ Vector3r halfSize=.5*(rb->cellMax-rb->cellMin);
+ float radius=std::max(halfSize[0],std::max(halfSize[1],halfSize[2]));
+ LOG_DEBUG("Periodic scene center="<<center<<", halfSize="<<halfSize<<",
radius="<<radius);
+ setSceneCenter(qglviewer::Vec(center[0],center[1],center[2]));
+ setSceneRadius(radius*1.5);
+ showEntireScene();
+}
/* Calculate medians for x, y and z coordinates of all bodies;
*then set scene center to median position and scene radius to
2*inter-quartile distance.
@@ -332,6 +344,7 @@
* "central" (where most bodies is) part very small or even invisible.
*/
void GLViewer::centerMedianQuartile(){
+ if(Omega::instance().getRootBody()->isPeriodic){ centerPeriodic();
return; }
long nBodies=Omega::instance().getRootBody()->bodies->size();
if(nBodies<4) {
LOG_INFO("Less than 4 bodies, median makes no sense; calling
centerScene() instead.");
@@ -357,6 +370,7 @@
void GLViewer::centerScene(){
MetaBody* rb=Omega::instance().getRootBody().get();
if (!rb) return;
+ if(rb->isPeriodic){ centerPeriodic(); return; }
if(rb->bodies->size()<renderer->selectBodyLimit){LOG_INFO("Less than
"+lexical_cast<string>(renderer->selectBodyLimit)+" bodies, moving possible.
Select with shift, press 'm' to move.");}
else{LOG_INFO("More than
"+lexical_cast<string>(renderer->selectBodyLimit)+"
(OpenGLRenderingEngine::selectBodyLimit) bodies. Moving not possible.");}
Modified: trunk/gui/qt3/GLViewer.hpp
===================================================================
--- trunk/gui/qt3/GLViewer.hpp 2009-08-06 22:05:28 UTC (rev 1928)
+++ trunk/gui/qt3/GLViewer.hpp 2009-08-07 10:27:49 UTC (rev 1929)
@@ -66,6 +66,7 @@
virtual void draw();
virtual void drawWithNames();
void centerScene();
+ void centerPeriodic();
void mouseMovesCamera();
void mouseMovesManipulatedFrame(qglviewer::Constraint* c=NULL);
void resetManipulation();
Modified: trunk/pkg/common/Engine/MetaEngine/InteractionDispatchers.cpp
===================================================================
--- trunk/pkg/common/Engine/MetaEngine/InteractionDispatchers.cpp
2009-08-06 22:05:28 UTC (rev 1928)
+++ trunk/pkg/common/Engine/MetaEngine/InteractionDispatchers.cpp
2009-08-07 10:27:49 UTC (rev 1929)
@@ -34,6 +34,7 @@
LOG_WARN("Interactions pending erase found (erased), no
collider being used?");
alreadyWarnedNoCollider=true;
}
+ Vector3r cellSize; if(rootBody->isPeriodic)
cellSize=rootBody->cellMax-rootBody->cellMin;
#ifdef YADE_OPENMP
const long size=rootBody->interactions->size();
#pragma omp parallel for schedule(guided)
@@ -72,7 +73,12 @@
assert(I->functorCache.geom);
bool wasReal=I->isReal();
- bool
geomCreated=I->functorCache.geom->go(b1->interactingGeometry,b2->interactingGeometry,b1->physicalParameters->se3,
b2->physicalParameters->se3,I);
+ bool geomCreated;
+ if(!rootBody->isPeriodic)
geomCreated=I->functorCache.geom->go(b1->interactingGeometry,b2->interactingGeometry,b1->physicalParameters->se3,
b2->physicalParameters->se3,I);
+ else{ // handle periodicity
+ Se3r se32=b2->physicalParameters->se3;
se32.position+=Vector3r(I->cellDist[0]*cellSize[0],I->cellDist[1]*cellSize[1],I->cellDist[2]*cellSize[2]);
+
geomCreated=I->functorCache.geom->go(b1->interactingGeometry,b2->interactingGeometry,b1->physicalParameters->se3,se32,I);
+ }
if(!geomCreated){
if(wasReal)
rootBody->interactions->requestErase(I->getId1(),I->getId2()); // fully created
interaction without geometry is reset and perhaps erased in the next step
continue; // in any case don't care about this
one anymore
Modified: trunk/pkg/common/Engine/MetaEngine/InteractionGeometryMetaEngine.cpp
===================================================================
--- trunk/pkg/common/Engine/MetaEngine/InteractionGeometryMetaEngine.cpp
2009-08-06 22:05:28 UTC (rev 1928)
+++ trunk/pkg/common/Engine/MetaEngine/InteractionGeometryMetaEngine.cpp
2009-08-07 10:27:49 UTC (rev 1929)
@@ -51,6 +51,7 @@
}
shared_ptr<BodyContainer>& bodies = ncb->bodies;
+ Vector3r cellSize; if(ncb->isPeriodic)
cellSize=ncb->cellMax-ncb->cellMin;
#ifdef YADE_OPENMP
const long size=ncb->transientInteractions->size();
#pragma omp parallel for
@@ -63,10 +64,16 @@
const shared_ptr<Body>& b2=(*bodies)[I->getId2()];
bool wasReal=I->isReal();
if (!b1->interactingGeometry ||
!b2->interactingGeometry) { assert(!wasReal); continue; } // some bodies do not
have interactingGeometry
- bool geomCreated=operator()(b1->interactingGeometry,
b2->interactingGeometry, b1->physicalParameters->se3,
b2->physicalParameters->se3, I);
+ bool geomCreated;
+ if(!ncb->isPeriodic){
+ geomCreated=operator()(b1->interactingGeometry,
b2->interactingGeometry, b1->physicalParameters->se3,
b2->physicalParameters->se3, I);
+ } else{
+ Se3r se32=b2->physicalParameters->se3;
se32.position+=Vector3r(I->cellDist[0]*cellSize[0],I->cellDist[1]*cellSize[1],I->cellDist[2]*cellSize[2]);
// add periodicity to the position of the 2nd body
+ geomCreated=operator()(b1->interactingGeometry,
b2->interactingGeometry, b1->physicalParameters->se3, se32, I);
+ }
// reset && erase interaction that existed but now has
no geometry anymore
if(wasReal && !geomCreated){
ncb->interactions->requestErase(I->getId1(),I->getId2()); }
}
}
-YADE_PLUGIN((InteractionGeometryMetaEngine));
\ No newline at end of file
+YADE_PLUGIN((InteractionGeometryMetaEngine));
Modified: trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp
===================================================================
--- trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp
2009-08-06 22:05:28 UTC (rev 1928)
+++ trunk/pkg/common/Engine/StandAloneEngine/InsertionSortCollider.cpp
2009-08-07 10:27:49 UTC (rev 1929)
@@ -230,7 +230,7 @@
*/
// TRVAR3(i,iid,V[i].coord);
// go up until we meet the upper bound
- for(size_t j=i+1; V[j].id!=iid && /* handle
case 2. of swapped min/max */ j<2*nBodies; j++){
+ for(size_t j=i+1; /* handle case 2. of swapped
min/max */ j<2*nBodies && V[j].id!=iid; j++){
const body_id_t& jid=V[j].id;
/// Not sure why this doesn't work. If
this condition is commented out, we have exact same interactions as from
SpatialQuickSort. Otherwise some interactions are missing!
// skip bodies with smaller (arbitrary,
could be greater as well) id, since they will detect us when their turn comes
Modified:
trunk/pkg/common/RenderingEngine/OpenGLRenderingEngine/OpenGLRenderingEngine.cpp
===================================================================
---
trunk/pkg/common/RenderingEngine/OpenGLRenderingEngine/OpenGLRenderingEngine.cpp
2009-08-06 22:05:28 UTC (rev 1928)
+++
trunk/pkg/common/RenderingEngine/OpenGLRenderingEngine/OpenGLRenderingEngine.cpp
2009-08-07 10:27:49 UTC (rev 1929)
@@ -109,16 +109,28 @@
numBodiesWhenRefSe3LastSet=rootBody->bodies->size();
numIterWhenRefSe3LastSet=Omega::instance().getCurrentIteration();
}
+/* mostly copied from PeriodicInsertionSortCollider
+ FIXME: common implementation somewhere */
+Real OpenGLRenderingEngine::wrapCell(const Real x, const Real x0, const Real
x1){
+ Real xNorm=(x-x0)/(x1-x0);
+ return x0+(xNorm-floor(xNorm))*(x1-x0);
+}
+Vector3r OpenGLRenderingEngine::wrapCellPt(const Vector3r& pt, MetaBody* rb){
+ if(!rb->isPeriodic) return pt;
+ return
Vector3r(wrapCell(pt[0],rb->cellMin[0],rb->cellMax[0]),wrapCell(pt[1],rb->cellMin[1],rb->cellMax[1]),wrapCell(pt[2],rb->cellMin[2],rb->cellMax[2]));
+}
+
void OpenGLRenderingEngine::setBodiesDispSe3(const shared_ptr<MetaBody>&
rootBody){
FOREACH(const shared_ptr<Body>& b, *rootBody->bodies){
if(!b->physicalParameters) continue;
const Se3r& se3=b->physicalParameters->se3; const Se3r&
refSe3=b->physicalParameters->refSe3; Se3r&
dispSe3=b->physicalParameters->dispSe3;
- b->physicalParameters->isDisplayed=!pointClipped(se3.position);
+ Vector3r posCell=wrapCellPt(se3.position,rootBody.get());
+ b->physicalParameters->isDisplayed=!pointClipped(posCell);
// if no scaling, return quickly
- if(!(scaleDisplacements||scaleRotations)){
b->physicalParameters->dispSe3=b->physicalParameters->se3; continue; }
+
if(!(scaleDisplacements||scaleRotations||rootBody->isPeriodic)){
b->physicalParameters->dispSe3=b->physicalParameters->se3; continue; }
// apply scaling
- dispSe3.position=(scaleDisplacements ?
diagMult(displacementScale,se3.position-refSe3.position)+refSe3.position :
se3.position );
+ dispSe3.position=(scaleDisplacements ?
diagMult(displacementScale,se3.position-refSe3.position)+wrapCellPt(refSe3.position,rootBody.get())
: posCell );
if(scaleRotations){
Quaternionr
relRot=refSe3.orientation.Conjugate()*se3.orientation;
Vector3r axis; Real angle;
relRot.ToAxisAngle(axis,angle);
@@ -127,7 +139,19 @@
} else {dispSe3.orientation=se3.orientation;}
}
}
+// draw periodic cell, if active
+void OpenGLRenderingEngine::drawPeriodicCell(MetaBody* rootBody){
+ if(!rootBody->isPeriodic) return;
+ glPushMatrix();
+ glColor3v(Vector3r(1,1,0));
+ Vector3r cent=.5*(rootBody->cellMin+rootBody->cellMax);
Vector3r size=rootBody->cellMax-rootBody->cellMin;
+ glTranslate(cent[0],cent[1],cent[2]);
glScale(size[0],size[1],size[2]);
+ glutWireCube(1);
+ glPopMatrix();
+}
+
+
void OpenGLRenderingEngine::render(const shared_ptr<MetaBody>& rootBody,
body_id_t selection /*FIXME: not sure. maybe a list of selections, or maybe
bodies themselves should remember if they are selected? */) {
assert(glutInitDone);
@@ -167,6 +191,8 @@
// set displayed Se3 of body (scaling) and isDisplayed (clipping)
setBodiesDispSe3(rootBody);
+ drawPeriodicCell(rootBody.get());
+
if (Show_DOF || Show_ID) renderDOF_ID(rootBody);
if (Body_geometrical_model){
if (Cast_shadows){
@@ -401,49 +427,78 @@
if(rootBody->geometricalModel)
geometricalModelDispatcher(rootBody->geometricalModel,rootBody->physicalParameters,Body_wire);
}
-void OpenGLRenderingEngine::renderGeometricalModel(const shared_ptr<MetaBody>&
rootBody){
+void OpenGLRenderingEngine::renderGeometricalModel(const shared_ptr<MetaBody>&
rootBody){
const GLfloat ambientColorSelected[4]={10.0,0.0,0.0,1.0};
const GLfloat ambientColorUnselected[4]={0.5,0.5,0.5,1.0};
- if((rootBody->geometricalModel || Draw_inside) && Draw_inside) {
- FOREACH(const shared_ptr<Body> b, *rootBody->bodies){
- if(b->geometricalModel && ((b->getGroupMask() &
Draw_mask) || b->getGroupMask()==0)){
- if(b->physicalParameters &&
!b->physicalParameters->isDisplayed) continue;
- const Se3r& se3=b->physicalParameters->dispSe3;
- glPushMatrix();
- Real angle; Vector3r axis;
se3.orientation.ToAxisAngle(axis,angle);
-
glTranslatef(se3.position[0],se3.position[1],se3.position[2]);
-
glRotatef(angle*Mathr::RAD_TO_DEG,axis[0],axis[1],axis[2]);
- if(current_selection==b->getId() ||
b->geometricalModel->highlight){
-
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambientColorSelected);
-
glColorMaterial(GL_FRONT_AND_BACK,GL_EMISSION);
- const Vector3r&
h(current_selection==b->getId() ? highlightEmission0 : highlightEmission1);
- glColor4(h[0],h[1],h[2],.2);
-
glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);
+ if(rootBody->geometricalModel)
geometricalModelDispatcher(rootBody->geometricalModel,rootBody->physicalParameters,Body_wire);
+ if(!Draw_inside) return;
+ FOREACH(const shared_ptr<Body> b, *rootBody->bodies){
+ if(!b->geometricalModel || (!((b->getGroupMask() & Draw_mask)
|| b->getGroupMask()==0))) continue;
+ if(b->physicalParameters &&
!b->physicalParameters->isDisplayed) continue;
+ const Se3r& se3=b->physicalParameters->dispSe3;
+ glPushMatrix();
+ Real angle; Vector3r axis;
se3.orientation.ToAxisAngle(axis,angle);
+ glTranslatef(se3.position[0],se3.position[1],se3.position[2]);
+ glRotatef(angle*Mathr::RAD_TO_DEG,axis[0],axis[1],axis[2]);
+ if(current_selection==b->getId() ||
b->geometricalModel->highlight){
+
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambientColorSelected);
+ glColorMaterial(GL_FRONT_AND_BACK,GL_EMISSION);
+ const Vector3r& h(current_selection==b->getId() ?
highlightEmission0 : highlightEmission1);
+ glColor4(h[0],h[1],h[2],.2);
+ glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);
-
geometricalModelDispatcher(b->geometricalModel,b->physicalParameters,Body_wire);
+
geometricalModelDispatcher(b->geometricalModel,b->physicalParameters,Body_wire);
-
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambientColorUnselected);
-
glColorMaterial(GL_FRONT_AND_BACK,GL_EMISSION);
- glColor3v(Vector3r::ZERO);
-
glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);
- } else {
-
geometricalModelDispatcher(b->geometricalModel,b->physicalParameters,Body_wire);
+
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambientColorUnselected);
+ glColorMaterial(GL_FRONT_AND_BACK,GL_EMISSION);
+ glColor3v(Vector3r::ZERO);
+ glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);
+ } else {
+
geometricalModelDispatcher(b->geometricalModel,b->physicalParameters,Body_wire);
+ }
+ glPopMatrix();
+ if(current_selection==b->getId() ||
b->geometricalModel->highlight){
+ if(!b->boundingVolume || Body_wire ||
b->geometricalModel->wire) GLUtils::GLDrawInt(b->getId(),se3.position);
+ else {
+ // move the label towards the camera by the
bounding box so that it is not hidden inside the body
+ const Vector3r& mn=b->boundingVolume->min;
const Vector3r& mx=b->boundingVolume->max; const Vector3r& p=se3.position;
+ Vector3r
ext(viewDirection[0]>0?p[0]-mn[0]:p[0]-mx[0],viewDirection[1]>0?p[1]-mn[1]:p[1]-mx[1],viewDirection[2]>0?p[2]-mn[2]:p[2]-mx[2]);
// signed extents towards the camera
+ Vector3r
dr=-1.01*(viewDirection.Dot(ext)*viewDirection);
+
GLUtils::GLDrawInt(b->getId(),se3.position+dr,Vector3r::ONE);
+ }
+ }
+ // if the body goes over the cell margin, draw it in all other
positions with wire
+ if(b->boundingVolume && rootBody->isPeriodic){
+ const Vector3r& cellMin(rootBody->cellMin); const
Vector3r& cellMax(rootBody->cellMax); Vector3r cellSize=cellMax-cellMin;
+ Vector3<int> bodyPer,minPer,maxPer;
+ for(int i=0; i<3; i++){
+
bodyPer[i]=(int)floor((b->physicalParameters->se3.position[i]-cellMin[i])/cellSize[i]);
+
minPer[i]=(int)floor((b->boundingVolume->min[i]-cellMin[i])/cellSize[i]);
+
maxPer[i]=(int)floor((b->boundingVolume->max[i]-cellMin[i])/cellSize[i]);
+ //assert(bodyPer[i]<=maxPer[i]);
assert(bodyPer[i]>=minPer[i]);
+ }
+ /* m is bitmask from 3 couples (0…64=2^6) */
+ for(int m=0; m<64; m++){
+ // any mask containing 00 couple is invalid
+ if((!(m&1) && (!(m&2))) || (!(m&4) && (!(m&8)))
|| (!(m&16) && (!(m&32)))) continue;
+ Vector3r pt(se3.position);
+ bool isInside=false;
+ for(int j=0; j<3; j++){
+ if(m&(1<<(2*j))) {
+ if(m&(1<<(2*j+1))) {
if(bodyPer[j]>=maxPer[j]) {isInside=true; break; } pt[j]-=cellSize[j]; }
+ else {
if(bodyPer[j]<=minPer[j]){ isInside=true; break; } pt[j]+=cellSize[j]; }
+ }
}
+ if(isInside) continue;
+ if(pt==se3.position) continue; // shouldn't
happen, but it happens :-(
+ glPushMatrix();
+ glTranslatev(pt);
+
glRotatef(angle*Mathr::RAD_TO_DEG,axis[0],axis[1],axis[2]);
+
geometricalModelDispatcher(b->geometricalModel,b->physicalParameters,/*Body_wire*/
true);
glPopMatrix();
- if(current_selection==b->getId() ||
b->geometricalModel->highlight){
- if(!b->boundingVolume || Body_wire ||
b->geometricalModel->wire) GLUtils::GLDrawInt(b->getId(),se3.position);
- else {
- // move the label towards the
camera by the bounding box so that it is not hidden inside the body
- const Vector3r&
mn=b->boundingVolume->min; const Vector3r& mx=b->boundingVolume->max; const
Vector3r& p=se3.position;
- Vector3r
ext(viewDirection[0]>0?p[0]-mn[0]:p[0]-mx[0],viewDirection[1]>0?p[1]-mn[1]:p[1]-mx[1],viewDirection[2]>0?p[2]-mn[2]:p[2]-mx[2]);
// signed extents towards the camera
- Vector3r
dr=-1.01*(viewDirection.Dot(ext)*viewDirection);
-
GLUtils::GLDrawInt(b->getId(),se3.position+dr,Vector3r::ONE);
- }
- }
}
}
}
- if(rootBody->geometricalModel)
geometricalModelDispatcher(rootBody->geometricalModel,rootBody->physicalParameters,Body_wire);
}
@@ -509,10 +564,10 @@
const Se3r& se3=b->physicalParameters->dispSe3;
if(b->interactingGeometry && ((b->getGroupMask()&Draw_mask) ||
b->getGroupMask()==0)){
glPushMatrix();
- Real angle; Vector3r axis;
se3.orientation.ToAxisAngle(axis,angle);
-
glTranslatef(se3.position[0],se3.position[1],se3.position[2]);
-
glRotatef(angle*Mathr::RAD_TO_DEG,axis[0],axis[1],axis[2]);
-
interactingGeometryDispatcher(b->interactingGeometry,b->physicalParameters,Body_wire);
+ Real angle; Vector3r axis;
se3.orientation.ToAxisAngle(axis,angle);
+
glTranslatef(se3.position[0],se3.position[1],se3.position[2]);
+
glRotatef(angle*Mathr::RAD_TO_DEG,axis[0],axis[1],axis[2]);
+
interactingGeometryDispatcher(b->interactingGeometry,b->physicalParameters,Body_wire);
glPopMatrix();
}
}
Modified:
trunk/pkg/common/RenderingEngine/OpenGLRenderingEngine/OpenGLRenderingEngine.hpp
===================================================================
---
trunk/pkg/common/RenderingEngine/OpenGLRenderingEngine/OpenGLRenderingEngine.hpp
2009-08-06 22:05:28 UTC (rev 1928)
+++
trunk/pkg/common/RenderingEngine/OpenGLRenderingEngine/OpenGLRenderingEngine.hpp
2009-08-07 10:27:49 UTC (rev 1929)
@@ -39,6 +39,13 @@
Real normSaw(Real t, Real period){ Real
xi=(t-period*((int)(t/period)))/period; /* normalized value, (0-1〉 */ return
(xi<.5?2*xi:2-2*xi); }
Real normSquare(Real t, Real period){ Real
xi=(t-period*((int)(t/period)))/period; /* normalized value, (0-1〉 */ return
(xi<.5?0:1); }
+ //! wrap number to interval x0…x1
+ Real wrapCell(const Real x, const Real x0, const Real x1);
+ //! wrap point to inside MetaBody's cell (identity if
!MetaBody::isPeriodic)
+ Vector3r wrapCellPt(const Vector3r& pt, MetaBody* rb);
+ void drawPeriodicCell(MetaBody*);
+
+
private :
DynLibDispatcher< InteractionGeometry ,
GLDrawInteractionGeometryFunctor, void , TYPELIST_5(const
shared_ptr<InteractionGeometry>&, const shared_ptr<Interaction>& , const
shared_ptr<Body>&, const shared_ptr<Body>&, bool) >
interactionGeometryDispatcher;
DynLibDispatcher< InteractionPhysics ,
GLDrawInteractionPhysicsFunctor, void , TYPELIST_5(const
shared_ptr<InteractionPhysics>& , const shared_ptr<Interaction>&, const
shared_ptr<Body>&, const shared_ptr<Body>&, bool) >
interactionPhysicsDispatcher;
Modified: trunk/scripts/test/periodic-simple.py
===================================================================
--- trunk/scripts/test/periodic-simple.py 2009-08-06 22:05:28 UTC (rev
1928)
+++ trunk/scripts/test/periodic-simple.py 2009-08-07 10:27:49 UTC (rev
1929)
@@ -10,15 +10,15 @@
[Law2_Dem3Dof_Elastic_Elastic()],
),
GravityEngine(gravity=[0,0,-10]),
- NewtonsDampedLaw(damping=.1)
+
TranslationEngine(translationAxis=(1,0,0),velocity=10,subscribedBodies=[0]),
+ NewtonsDampedLaw(damping=.4)
]
-O.bodies.append(utils.sphere([0,0,2],1,dynamic=False,density=1000))
-O.bodies.append(utils.sphere([0,0,3],1,density=1000))
+O.bodies.append(utils.sphere([-4,0,11],2,dynamic=False,density=1000))
+O.bodies.append(utils.sphere([0,-1,5.5],2,density=1000))
+O.bodies.append(utils.sphere([0,2,5.5],2,density=2000))
O.periodicCell=((-5,-5,0),(5,5,10))
-O.dt=utils.PWaveTimeStep()
+O.dt=.1*utils.PWaveTimeStep()
O.saveTmp()
from yade import qt
qt.Controller()
qt.View()
-O.run(17)
-
_______________________________________________
Mailing list: https://launchpad.net/~yade-dev
Post to : [email protected]
Unsubscribe : https://launchpad.net/~yade-dev
More help : https://help.launchpad.net/ListHelp
_______________________________________________
yade-dev mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/yade-dev