00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <vlVolume/VolumePlot.hpp>
00033 #include <vlGraphics/Light.hpp>
00034 #include <vlGraphics/SceneManager.hpp>
00035 #include <vlGraphics/FontManager.hpp>
00036 #include <vlCore/VisualizationLibrary.hpp>
00037 #include <vlGraphics/GeometryPrimitives.hpp>
00038
00039 using namespace vl;
00040
00069
00070
00071
00072 VolumePlot::VolumePlot()
00073 {
00074 VL_DEBUG_SET_OBJECT_NAME()
00075 mActorTreeMulti = new ActorTree;
00076 mPlotTransform = new Transform;
00077 mIsosurfaceActor = new Actor;
00078 mIsosurfaceGeometry = new Geometry;
00079 mIsosurfaceEffect = new Effect;
00080 mBoxEffect = new Effect;
00081 mTextTemplate = new Text;
00082 mSamplingResolution = ivec3(64,64,64);
00083 mLabelFormat = "(%.2n %.2n %.2n)";
00084 mLabelFont = defFontManager()->acquireFont("/font/bitstream-vera/VeraMono.ttf", 8);
00085 mMinCorner = fvec3(-1,-1,-1);
00086 mMaxCorner = fvec3(+1,+1,+1);
00087
00088
00089
00090 mIsosurfaceEffect->shader()->setRenderState( new Light, 0 );
00091 mIsosurfaceEffect->shader()->gocMaterial()->setFrontDiffuse(red);
00092 mIsosurfaceEffect->shader()->gocMaterial()->setBackDiffuse(green);
00093 mIsosurfaceEffect->shader()->enable(EN_LIGHTING);
00094 mIsosurfaceEffect->shader()->enable(EN_DEPTH_TEST);
00095 mIsosurfaceEffect->shader()->gocLightModel()->setTwoSide(true);
00096
00097 mBoxEffect->shader()->gocPolygonMode()->set(PM_LINE, PM_LINE);
00098 mBoxEffect->shader()->enable(EN_DEPTH_TEST);
00099
00100 textTemplate()->setColor(white);
00101 }
00102
00107 void VolumePlot::compute(const Function& func, float threshold)
00108 {
00109 actorTreeMulti()->actors()->clear();
00110 mActors.clear();
00111
00112
00113 ref<Geometry> box_outline = makeBox(AABB((vec3)minCorner(),(vec3)maxCorner()));
00114
00115
00116
00117 MarchingCubes mc;
00118
00119 mIsosurfaceGeometry->setVertexArray(mc.mVertsArray.get());
00120 mIsosurfaceGeometry->setNormalArray(mc.mNormsArray.get());
00121 mIsosurfaceGeometry->drawCalls()->clear();
00122 mIsosurfaceGeometry->drawCalls()->push_back(mc.mDrawElements.get());
00123
00124 mIsosurfaceActor->setLod(0, mIsosurfaceGeometry.get());
00125 mIsosurfaceActor->setEffect(mIsosurfaceEffect.get());
00126 mIsosurfaceActor->setTransform(mPlotTransform.get());
00127 mActors.push_back(mIsosurfaceActor.get());
00128 mActors.push_back( new Actor(box_outline.get(),mBoxEffect.get(),mPlotTransform.get()) );
00129
00130 ref<Volume> volume = new Volume;
00131 volume->setup( NULL, false, false, minCorner(), maxCorner(), mSamplingResolution );
00132
00133 mc.volumeInfo()->push_back( new VolumeInfo( volume.get(), threshold ) );
00134
00135 evaluateFunction(volume->values(), minCorner(), maxCorner(), func);
00136
00137
00138 mc.run(false);
00139
00140
00141 setupLabels(labelFormat(), minCorner(), maxCorner(), labelFont(), mPlotTransform.get());
00142
00143 for(unsigned i=0; i<mActors.size(); ++i)
00144 actorTreeMulti()->actors()->push_back(mActors[i].get());
00145 }
00146
00147 void VolumePlot::setupLabels(const String& format, const fvec3& min_corner, const fvec3& max_corner, Font* font, Transform* root_tr)
00148 {
00149 ref< Effect > text_fx = new Effect;
00150 text_fx->shader()->enable(EN_BLEND);
00151 text_fx->shader()->enable(EN_DEPTH_TEST);
00152
00153 float coords[][3] =
00154 {
00155 {min_corner.x(), min_corner.y(), min_corner.z()},
00156 {max_corner.x(), min_corner.y(), min_corner.z()},
00157 {max_corner.x(), max_corner.y(), min_corner.z()},
00158 {min_corner.x(), max_corner.y(), min_corner.z()},
00159 {min_corner.x(), min_corner.y(), max_corner.z()},
00160 {max_corner.x(), min_corner.y(), max_corner.z()},
00161 {max_corner.x(), max_corner.y(), max_corner.z()},
00162 {min_corner.x(), max_corner.y(), max_corner.z()}
00163 };
00164
00165 String coord_label[] =
00166 {
00167 Say(format) << min_corner.x() << min_corner.y() << min_corner.z(),
00168 Say(format) << max_corner.x() << min_corner.y() << min_corner.z(),
00169 Say(format) << max_corner.x() << max_corner.y() << min_corner.z(),
00170 Say(format) << min_corner.x() << max_corner.y() << min_corner.z(),
00171 Say(format) << min_corner.x() << min_corner.y() << max_corner.z(),
00172 Say(format) << max_corner.x() << min_corner.y() << max_corner.z(),
00173 Say(format) << max_corner.x() << max_corner.y() << max_corner.z(),
00174 Say(format) << min_corner.x() << max_corner.y() << max_corner.z()
00175 };
00176
00177 for(int i=0; i<8; ++i)
00178 {
00179 ref<Text> text = new Text;
00180 text->setDisplayListEnabled(false);
00181 text->setBufferObjectEnabled(false);
00182 text->setFont( font );
00183 text->setAlignment(AlignHCenter| AlignVCenter);
00184 text->setText(coord_label[i]);
00185
00186 text->setColor( textTemplate()->color() );
00187 text->setBorderColor( textTemplate()->borderColor() );
00188 text->setBorderEnabled( textTemplate()->borderEnabled() );
00189 text->setBackgroundColor( textTemplate()->backgroundColor() );
00190 text->setBackgroundEnabled( textTemplate()->backgroundEnabled() );
00191 text->setMargin( textTemplate()->margin() );
00192 text->setOutlineColor( textTemplate()->outlineColor() );
00193 text->setOutlineEnabled( textTemplate()->outlineEnabled() );
00194 text->setShadowColor( textTemplate()->shadowColor() );
00195 text->setShadowEnabled( textTemplate()->shadowEnabled() );
00196 text->setShadowVector( textTemplate()->shadowVector() );
00197 text->setMatrix( textTemplate()->matrix() );
00198
00199 ref<Actor> text_a = new Actor( text.get(), text_fx.get(), new Transform );
00200 text_a->transform()->setLocalMatrix( mat4::getTranslation(coords[i][0],coords[i][1],coords[i][2]) );
00201 if (root_tr)
00202 root_tr->addChild( text_a->transform() );
00203 text_a->transform()->computeWorldMatrix();
00204
00205 mActors.push_back( text_a.get() );
00206 }
00207 }
00208
00209 void VolumePlot::evaluateFunction(float* scalar, const fvec3& min_corner, const fvec3& max_corner, const Function& func)
00210 {
00211 fvec3 v;
00212 int w = mSamplingResolution.x();
00213 int h = mSamplingResolution.y();
00214 int d = mSamplingResolution.z();
00215 for(int z=0; z<d; ++z)
00216 {
00217 float tz = (float)z/(d-1);
00218 v.z() = min_corner.z()*(1.0f-tz) + max_corner.z()*tz;
00219 for(int y=0; y<h; ++y)
00220 {
00221 float ty = (float)y/(h-1);
00222 v.y() = min_corner.y()*(1.0f-ty) + max_corner.y()*ty;
00223 for(int x=0; x<w; ++x)
00224 {
00225 float tx = (float)x/(w-1);
00226 v.x() = min_corner.x()*(1.0f-tx) + max_corner.x()*tx;
00227
00228 scalar[x+y*w+z*w*h] = func(v.x(),v.y(),v.z());
00229 }
00230 }
00231 }
00232 }
00233