This example shows how to create an object with custom geometry, attach the buoyancy model to it, and dynamically modify it in real time.
DtExampleModelManager is responsible for creating the objects, processing events to resize the objects, and call updateSize on them every frame. DtExampleModel is the DtModel derived object that creates the model instances for the example model. DtExampleModelInstance is the actual model and contains the node and geometry for the object. It also updates the geometries vertices.
This example is a plug-in. You can run it by running ./bin64/exampleDynamidDraw_stealth.bat (on Windows) or ./bin64/exampleDynamicDraw_stealth.sh (on Linux). This example is intended to be run without a terrain. When VR-Vantage starts close the startup dialog. Add a dynamic ocean layer using the Terrain Editor Panel (can be shown via the View->Terrain Editor Panel menu). Press 'f' to add cubes. Press 'r', 'R', 't', and 'T' to resize the cubes. Press 'o' and 'O' to change the animation rate of the cubes. For more information about running examples, please see Running Applications and Examples.
namespace makVrv
{
, mySceneConnector( new DtOsgSceneConnector( de ) )
, mySceneObjectId(0)
{
DtExampleModelInstance *exampleModelInstance = new DtExampleModelInstance(de, halfLength, animateRate);
setModelInstance(exampleModelInstance);
}
DtExampleModel::~DtExampleModel()
{
delete mySceneConnector;
mySceneConnector = 0;
}
void DtExampleModel::setSolid(bool isSolid) {};
void DtExampleModel::setIsSupportModel( bool isSupport )
{
mySceneConnector->setSupportFlags( isSupport );
}
void DtExampleModel::setPosition( int vtx, const DtVector& position )
{
mySceneConnector->setPosition( position );
}
void DtExampleModel::setOrientation( int vtx, const DtTaitBryan& orientation )
{
mySceneConnector->setOrientation( orientation );
}
void DtExampleModel::setVisible(bool isVisible)
{
DtModel::setVisible(isVisible);
if(visible() == isVisible)
{
mySceneConnector->setVisible( isVisible );
mySceneConnector->setConnectedWhileHidden( ! isVisible );
}
}
void DtExampleModel::setModelScalingEnabled( bool b )
{
mySceneConnector->setModelScalingEnabled( b );
}
void DtExampleModel::setLocalModelScalingEnabled(
bool enabled )
{
mySceneConnector->setLocalModelScalingEnabled( enabled );
}
void DtExampleModel::setLocalModelScalingAmount( float localScl )
{
mySceneConnector->setLocalModelScalingAmount( localScl );
}
void DtExampleModel::addToScene(
const DtUniqueID& sceneObjectId,
{
DtOsgModelInstance* osgModelInstance =
dynamic_cast<DtOsgModelInstance*>( modelInstance() );
if ( osgModelInstance )
{
mySceneConnector->addToScene( osgModelInstance,
sceneObjectId, modelSet, visualizerType );
mySceneConnector->setVisible( visible() );
mySceneObjectId = sceneObjectId;
}
}
void DtExampleModel::removeFromScene()
{
DtOsgModelInstance* osgModelInstance =
dynamic_cast<DtOsgModelInstance*>( modelInstance() );
if ( osgModelInstance )
{
mySceneConnector->removeFromScene( osgModelInstance );
}
}
}
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Material>
namespace makVrv
{
, myMinSize(halfLength - animateRate * 120.0, halfLength - animateRate * 120.0, halfLength)
, myMaxSize(halfLength + animateRate * 120.0, halfLength + animateRate * 120.0, halfLength)
, myCurrentSize(halfLength, halfLength, halfLength)
, myAnimateRate(animateRate, animateRate, 0.0)
{
createCubeGeode();
}
void DtExampleModelInstance::createCubeGeode()
{
DtOsgFileCache* osgFileCache =
dynamic_cast<DtOsgFileCache*
>(myDe.
fileCache());
osg::ref_ptr<osg::Texture> iceTex = NULL;
if(osgFileCache)
{
std::string iceTexFilename(
"../examples/exampleDynamicDraw/ice_texture.png");
iceTex = osgFileCache->getTextureInstance(iceTexFilename,
osg::Texture::LINEAR_MIPMAP_LINEAR,osg::Texture::LINEAR_MIPMAP_LINEAR,osg::Texture::REPEAT,osg::Texture::REPEAT,
lfo);
}
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
normals->push_back(osg::Vec3(0.0f,-1.0f,0.0f));
normals->push_back(osg::Vec3(0.0f,1.0f,0.0f));
normals->push_back(osg::Vec3(1.0f,0.0f,0.0f));
normals->push_back(osg::Vec3(-1.0f,0.0f,0.0f));
normals->push_back(osg::Vec3(0.0f,0.0f,-1.0f));
normals->push_back(osg::Vec3(0.0f,0.0f,1.0f));
osg::ref_ptr<osg::Vec3Array> colors = new osg::Vec3Array;
colors->push_back(osg::Vec3(1.0f, 1.0f, 1.0f));
colors->push_back(osg::Vec3(1.0f, 1.0f, 1.0f));
colors->push_back(osg::Vec3(1.0f, 1.0f, 1.0f));
colors->push_back(osg::Vec3(1.0f, 1.0f, 1.0f));
colors->push_back(osg::Vec3(1.0f, 1.0f, 1.0f));
colors->push_back(osg::Vec3(1.0f, 1.0f, 1.0f));
osg::Geometry* cubeGeom = new osg::Geometry();
float dx = myCurrentSize.x();
float dy = myCurrentSize.y();
float dz = myCurrentSize.z();
{
osg::Vec3 myCoords[] =
{
osg::Vec3(-dx, -dy, dz),
osg::Vec3(-dx, -dy, -dz),
osg::Vec3(dx, -dy, -dz),
osg::Vec3(dx, -dy, dz),
osg::Vec3(dx, dy, dz),
osg::Vec3(dx, dy, -dz),
osg::Vec3(-dx, dy, -dz),
osg::Vec3(-dx, dy, dz),
osg::Vec3(dx, -dy, dz),
osg::Vec3(dx, -dy, -dz),
osg::Vec3(dx, dy, -dz),
osg::Vec3(dx, dy, dz),
osg::Vec3(-dx, dy, dz),
osg::Vec3(-dx, dy, -dz),
osg::Vec3(-dx, -dy, -dz),
osg::Vec3(-dx, -dy, dz),
osg::Vec3(dx, dy, -dz),
osg::Vec3(dx, -dy, -dz),
osg::Vec3(-dx, -dy, -dz),
osg::Vec3(-dx, dy, -dz),
osg::Vec3(dx, dy, dz),
osg::Vec3(-dx, dy, dz),
osg::Vec3(-dx, -dy, dz),
osg::Vec3(dx, -dy, dz),
};
osg::Vec2 myTexCoords[] =
{
osg::Vec2(0, 0),
osg::Vec2(0, 1),
osg::Vec2(1, 1),
osg::Vec2(1, 0),
osg::Vec2(0, 0),
osg::Vec2(0, 1),
osg::Vec2(1, 1),
osg::Vec2(1, 0),
osg::Vec2(0, 0),
osg::Vec2(0, 1),
osg::Vec2(1, 1),
osg::Vec2(1, 0),
osg::Vec2(0, 0),
osg::Vec2(0, 1),
osg::Vec2(1, 1),
osg::Vec2(1, 0),
osg::Vec2(0, 0),
osg::Vec2(0, 1),
osg::Vec2(1, 1),
osg::Vec2(1, 0),
osg::Vec2(0, 0),
osg::Vec2(0, 1),
osg::Vec2(1, 1),
osg::Vec2(1, 0)
};
int numCoords =
sizeof(myCoords)/
sizeof(osg::Vec3);
osg::Vec3Array* vertices = new osg::Vec3Array(numCoords,myCoords);
cubeGeom->setVertexArray(vertices);
osg::Vec2Array* texCoords = new osg::Vec2Array(numCoords,myTexCoords);
cubeGeom->setTexCoordArray(0, texCoords);
cubeGeom->setNormalArray(normals.get(), osg::Array::BIND_PER_PRIMITIVE_SET);
cubeGeom->setColorArray(colors.get(), osg::Array::BIND_PER_PRIMITIVE_SET);
cubeGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,numCoords));
}
cubeGeom->setInitialBound(osg::BoundingBox(osg::Vec3(-dx, -dy, -dz), osg::Vec3(dx, dy, dz)));
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable(cubeGeom);
osg::StateSet *ss = cubeGeom->getOrCreateStateSet();
ss->setTextureAttributeAndModes(0,iceTex.get());
osg::Material* material = new osg::Material;
ss->setAttribute(material);
DtOsgShaderManager& shaderManager = DtOsgShaderManager::instance(myDe);
shaderManager.generateShaders(geode, "DtExampleModelInstance");
setRootNode((osg::Node*)geode);
}
void DtExampleModelInstance::setVisible(bool isVisible) {}
void DtExampleModelInstance::changeSideSize(int side, double deltaChange)
{
if(side == 0 && (myCurrentSize.x() + deltaChange > 0.0))
{
myCurrentSize.x() += deltaChange;
}else if(side == 1 && (myCurrentSize.y() + deltaChange > 0.0))
{
myCurrentSize.y() += deltaChange;
}
myMinSize.x() =
std::min(myCurrentSize.x(), myMinSize.x());
myMinSize.y() =
std::min(myCurrentSize.y(), myMinSize.y());
myMaxSize.x() =
std::max(myCurrentSize.x(), myMaxSize.x());
myMaxSize.y() =
std::max(myCurrentSize.y(), myMaxSize.y());
}
void DtExampleModelInstance::updateSize(double animationScale)
{
osg::Geode *geode = dynamic_cast<osg::Geode*>(rootNode());
if(animationScale > 0.0)
{
osg::Vec3 animateRate = myAnimateRate * animationScale;
myCurrentSize += animateRate;
if(myMaxSize.x() != myMinSize.x())
{
if(myCurrentSize.x() > myMaxSize.x())
{
myAnimateRate.x() *= -1.0;
myCurrentSize.x() = myMaxSize.x() - animateRate.x();
}
if(myCurrentSize.x() < myMinSize.x())
{
myAnimateRate.x() *= -1.0;
myCurrentSize.x() = myMinSize.x() - animateRate.x();
}
}
if(myMaxSize.y() != myMinSize.y())
{
if(myCurrentSize.y() > myMaxSize.y())
{
myAnimateRate.y() *= -1.0;
myCurrentSize.y() = myMaxSize.y() - animateRate.y();
}
if(myCurrentSize.y() < myMinSize.y())
{
myAnimateRate.y() *= -1.0;
myCurrentSize.y() = myMinSize.y() - animateRate.y();
}
}
}
if(geode)
{
osg::Geometry *geom = dynamic_cast<osg::Geometry*>(geode->getDrawable(0));
osg::Array* vertArray = geom->getVertexArray();
osg::Vec3* vertVecs = (osg::Vec3*)(vertArray->getDataPointer());
double dx = myCurrentSize.x();
double dy = myCurrentSize.y();
double dz = myCurrentSize.z();
vertVecs[0] = osg::Vec3(-dx, -dy, dz);
vertVecs[1] = osg::Vec3(-dx, -dy, -dz);
vertVecs[2] = osg::Vec3(dx, -dy, -dz);
vertVecs[3] = osg::Vec3(dx, -dy, dz);
vertVecs[4] = osg::Vec3(dx, dy, dz);
vertVecs[5] = osg::Vec3(dx, dy, -dz);
vertVecs[6] = osg::Vec3(-dx, dy, -dz);
vertVecs[7] = osg::Vec3(-dx, dy, dz);
vertVecs[8] = osg::Vec3(dx, -dy, dz);
vertVecs[9] = osg::Vec3(dx, -dy, -dz);
vertVecs[10] = osg::Vec3(dx, dy, -dz);
vertVecs[11] = osg::Vec3(dx, dy, dz);
vertVecs[12] = osg::Vec3(-dx, dy, dz);
vertVecs[13] = osg::Vec3(-dx, dy, -dz);
vertVecs[14] = osg::Vec3(-dx, -dy, -dz);
vertVecs[15] = osg::Vec3(-dx, -dy, dz);
vertVecs[16] = osg::Vec3(dx, dy, -dz);
vertVecs[17] = osg::Vec3(dx, -dy, -dz);
vertVecs[18] = osg::Vec3(-dx, -dy, -dz);
vertVecs[19] = osg::Vec3(-dx, dy, -dz);
vertVecs[20] = osg::Vec3(dx, dy, dz);
vertVecs[21] = osg::Vec3(-dx, dy, dz);
vertVecs[22] = osg::Vec3(-dx, -dy, dz);
vertVecs[23] = osg::Vec3(dx, -dy, dz);
vertArray->dirty();
geom->setInitialBound(osg::BoundingBox(-myCurrentSize, myCurrentSize));
geom->dirtyBound();
}
}
}
namespace makVrv
{
: myDe(de)
, myModelInstances()
, myAnimateScale(1.0)
{
&DtExampleModelManager::tick, this));
}
DtExampleModelManager::~DtExampleModelManager()
{
}
void DtExampleModelManager::changeSideSize(int side, double deltaChange)
{
std::list<DtExampleModelInstance*>::iterator it = myModelInstances.begin(), nd = myModelInstances.end();
for(; it != nd; ++it)
{
(*it)->changeSideSize(side, deltaChange);
}
}
void DtExampleModelManager::changeAnimateScale(double deltaChange)
{
myAnimateScale += deltaChange;
if(myAnimateScale < 0)
{
myAnimateScale = 0;
}
}
void DtExampleModelManager::createRandomCube()
{
double cubeX = rand() % 2000;
double cubeY = rand() % 2000;
double cubeZ = rand() % 2000;
double cubeHalfLength = rand() % 20 + 10;
double heading = rand() % 360;
createCube(cubeX, cubeY, cubeZ, cubeHalfLength, heading);
}
void DtExampleModelManager::createCube(double x, double y, double z, double halfLength, double heading)
{
DtSceneObject* sceneObj = new DtSceneObject(myDe, 3);
sceneObj->setModelSet(DtModelSetId::Models3D);
sceneObj->setPosition(0, DtVector(x, y, z));
sceneObj->setOrientation(0, DtTaitBryan(heading, 0.0, 0.0));
sceneObj->setBoundingBoxSize(-halfLength,-halfLength,-halfLength,halfLength,halfLength,halfLength);
DtTritonWaterClampingUpdater *waterUpdater = new DtTritonWaterClampingUpdater(myDe, uid);
waterUpdater->addSceneObjectToUpdate( DtModelSetId::Models3D, sceneObj);
waterUpdater->setInputPosition(DtVector(x, y, z));
waterUpdater->setInputOrientation(DtTaitBryan(heading, 0.0, 0.0));
waterUpdater->setLOD(-1.0);
DtExampleModel* model = new DtExampleModel(myDe, uid, halfLength, 5.0 / 60.0);
myModelInstances.push_back(dynamic_cast<DtExampleModelInstance *>(model->modelInstance()));
sceneObj->addModel(model, 0);
return;
}
void DtExampleModelManager::tick()
{
std::list<DtExampleModelInstance*>::iterator it = myModelInstances.begin(), nd = myModelInstances.end();
for(; it != nd; ++it)
{
(*it)->updateSize(myAnimateScale);
}
}
}