コード例 #1
0
ファイル: Tentacle.cpp プロジェクト: CalebVDW/smr-motion
/**
* update the Horde tentacle according to Smr _tentacleIK
*/
static void updateTentacle()
{
  //set of floats storing Horde's tentacle joints state
  float tx,ty,tz,rx,ry,rz,foo;
  double rrx,rry,rrz;
  // a Horde handle towards a tentacle Bone (joint)
  H3DNode tentacleBone;
  // and its corresponding node in Smr
  SMRKinematicJoint* ikJoint;

  //get the transformation parameters from the SmrTentacle
  for( unsigned int i=0; i < _tentacleIK->getNumJoints()-1 ; i++)
  {
    ikJoint = _tentacleIK->getJoint(i);

    //get Horde tentacle's corresponding joint joint (Horde) 
    h3dFindNodes(H3DRootNode,ikJoint->getName().c_str(), H3DNodeTypes::Joint);
    tentacleBone = h3dGetNodeFindResult(0);
    h3dGetNodeTransform(tentacleBone,&tx,&ty,&tz,&rx,&ry,&rz,&foo,&foo,&foo);

    //put the rotation values into euler angles (in degrees)
    ikJoint->getOrientation().toEulerAngles(rrx,rry,rrz);

    // update tentacle's joint according to Smr kinematic chain equivalent
    h3dSetNodeTransform( tentacleBone, tx, ty, tz, radToDeg( ((float)(rrx)) ), radToDeg( ((float)(rry)) ), radToDeg( ((float)(rrz)) ), foo, foo, foo );
  }
  // orientate Horde tentacles root joint correctly //No more in the new version !
  ikJoint = _tentacleIK->getJoint(0);
  h3dFindNodes(H3DRootNode,ikJoint->getName().c_str(), H3DNodeTypes::Joint);
  tentacleBone = h3dGetNodeFindResult(0);
  h3dGetNodeTransform(tentacleBone,&tx,&ty,&tz,&rx,&ry,&foo,&foo,&foo,&foo);
  h3dSetNodeTransform(tentacleBone,tx,ty,tz,rx,ry,rz,foo,foo,foo);
}
コード例 #2
0
ファイル: Gaze.cpp プロジェクト: dreamsxin/nawia
bool Gaze::moveEye(Joint *eye, Joint *aux_eye, bool simulate)
{
	bool result = true;
	float angle;
	Horde3D::Vec3f axis;
	AxisLock lock(true, false, false);
		
	//clear eye rotation
	eye->update();
	Horde3D::Vec3f s = eye->getScale();
	Horde3D::Vec3f p = eye->getTranslation();
	Horde3D::Vec3f r = eye->getRotation();
	h3dSetNodeTransform( eye->getHordeID(), 
		p.x,p.y,p.z, 
		Config::getParamF(IK_Param::DfltEyeRotX_F), Config::getParamF(IK_Param::DfltEyeRotY_F), Config::getParamF(IK_Param::DfltEyeRotZ_F),
		s.x,s.y,s.z );
	
	m_endEffector = aux_eye;
	if( computeRotation(eye, &axis, &angle) )
	{		
		if(!simulate)
			result = applyRotation(eye, axis, angle, &lock, false);
		else
			result = simulateRotation(eye, axis, angle, &lock, r);
	}
	return result;
}
コード例 #3
0
ファイル: Gaze.cpp プロジェクト: dreamsxin/nawia
bool Gaze::moveHead(bool simulate)
{
	bool result = true;	
	float angle;
	Horde3D::Vec3f axis;
	AxisLock lock(false, false, (Config::getParamI(IK_Param::UseZLock_I) == 0) ? false : true);

	//clear head rotation
	m_head->update();
	Horde3D::Vec3f s = m_head->getScale();
	Horde3D::Vec3f p = m_head->getTranslation();
	Horde3D::Vec3f r = m_head->getRotation();
	h3dSetNodeTransform( m_head->getHordeID(), 
		p.x,p.y,p.z, 
		0,0,0,
		s.x,s.y,s.z );
	
	if( computeHeadRotation(&axis, &angle) )
	{
		if(!simulate)
			result = applyRotation(m_head, axis, angle, &lock, false);
		else
			result = simulateRotation(m_head, axis, angle, &lock, r);
	}
	return result;
}
コード例 #4
0
ファイル: crowd.cpp プロジェクト: Amroll/Horde3D
void CrowdSim::init()
{
	// Init random generator
	//srand( (unsigned int)time( NULL ) );
	srand( 99777 );  // Use fixed value for better performance comparisons
	
	// Load character with walk animation
	H3DRes characterRes = h3dAddResource( H3DResTypes::SceneGraph, "models/man/man.scene.xml", 0 );
	H3DRes characterWalkRes = h3dAddResource( H3DResTypes::Animation, "animations/man.anim", 0 );
	h3dutLoadResourcesFromDisk( _contentDir.c_str() );
	
	// Add characters
	for( unsigned int i = 0; i < 100; ++i )
	{
		Particle p;
		
		// Add character to scene and apply animation
		p.node = h3dAddNodes( H3DRootNode, characterRes );
		h3dSetupModelAnimStage( p.node, 0, characterWalkRes, 0, "", false );
		
		// Characters start in a circle formation
		p.px = sinf( (i / 100.0f) * 6.28f ) * 10.0f;
		p.pz = cosf( (i / 100.0f) * 6.28f ) * 10.0f;

		chooseDestination( p );

		h3dSetNodeTransform( p.node, p.px, 0.02f, p.pz, 0, 0, 0, 1, 1, 1 );

		_particles.push_back( p );
	}
}
コード例 #5
0
void utils::setEntityPosition(int eID, Vec3f newPos)
{
	//GameEvent translate(GameEvent::E_TRANSLATE_GLOBAL, &newPos, 0);
	//GameEngine::sendEvent(eID, &translate);

	unsigned int hiD = GameEngine::entitySceneGraphID(eID);
	Vec3f p,r,s;

	h3dGetNodeTransform( (H3DNode)hiD, &p.x,&p.y,&p.z, &r.x,&r.y,&r.z, &s.x,&s.y,&s.z );
	h3dSetNodeTransform( (H3DNode)hiD, newPos.x,newPos.y,newPos.z, r.x,r.y,r.z, s.x,s.y,s.z );
};
コード例 #6
0
ファイル: Gaze.cpp プロジェクト: dreamsxin/nawia
Gaze::Gaze(Joint *head, Joint *lefteye, Joint *righteye) : 
m_head(head), m_leye(lefteye), m_reye(righteye), m_aux_leye(0), m_aux_reye(0), m_headpitch(0), m_targetIsSet(false), m_gazeaux_res(0)
{
	Horde3D::Vec3f p,r,s;

	//clear rotations
	lefteye->update();
	s = lefteye->getScale();
	p = lefteye->getTranslation();
	h3dSetNodeTransform( lefteye->getHordeID(), 
		p.x,p.y,p.z, 
		Config::getParamF(IK_Param::DfltEyeRotX_F), Config::getParamF(IK_Param::DfltEyeRotY_F), Config::getParamF(IK_Param::DfltEyeRotZ_F),
		s.x,s.y,s.z );

	righteye->update();
	s = righteye->getScale();
	p = righteye->getTranslation();
	h3dSetNodeTransform( righteye->getHordeID(), 
		p.x,p.y,p.z, 
		Config::getParamF(IK_Param::DfltEyeRotX_F), Config::getParamF(IK_Param::DfltEyeRotY_F), Config::getParamF(IK_Param::DfltEyeRotZ_F),
		s.x,s.y,s.z );

	
	//Generating 2 auxiliary eye nodes which will help us detrmine the orientation of each eye.
	#ifdef IK_DEBUG
		m_aux_leye = createGazeAux(lefteye, "gazeaux.scene.xml", "models/gazeaux/"); //WARNING, requires external gazeaux file
		m_aux_reye = createGazeAux(righteye, "gazeaux.scene.xml", "models/gazeaux/"); //WARNING, requires external gazeaux file
	#else
		m_aux_leye = createGazeAux(lefteye);
		m_aux_reye = createGazeAux(righteye);
	#endif
	//making a small position offset between the eye and the eyeaux
	//ASSUMING the eye is oriented (1,0,0)
	//Setting the auxiliar eye joint (in)visible
	#ifdef IK_DEBUG
		s = m_leye->getAbsScale();
		h3dSetNodeTransform( m_aux_leye->getHordeID(), 0.5f, 0, 0, 0, 0, 0, 4.0f/s.x, 0.2f/s.y, 0.2f/s.z );
		h3dSetNodeFlags( m_aux_leye->getHordeID(), 0, true );

		s = m_reye->getAbsScale();
		h3dSetNodeTransform( m_aux_reye->getHordeID(), 0.5f, 0, 0, 0, 0, 0, 4.0f/s.x, 0.2f/s.y, 0.2f/s.z );
		h3dSetNodeFlags( m_aux_reye->getHordeID(), 0, true );
	#else
		h3dSetNodeTransform( m_aux_leye->getHordeID(), 0.5f, 0, 0, 0, 0, 0, 1, 1, 1 );
		h3dSetNodeFlags( m_aux_leye->getHordeID(), H3DNodeFlags::Inactive, true );

		h3dSetNodeTransform( m_aux_reye->getHordeID(), 0.5f, 0, 0, 0, 0, 0, 1, 1, 1 );
		h3dSetNodeFlags( m_aux_reye->getHordeID(), H3DNodeFlags::Inactive, true );
	#endif

	if(m_head > 0 && m_leye > 0 && m_reye > 0 && m_aux_leye > 0 && m_aux_reye > 0)
		GameLog::logMessage( "IKComponent loaded and initialized");
	else
		GameLog::errorMessage( "IKComponent: gaze failed to initialize" );

	//Chek for missing DOFR information
	if(m_head->getDOFR()->isWeak())		m_head->setDOFR(DOFRestrictions::HEAD);
	if(m_leye->getDOFR()->isWeak())		m_leye->setDOFR(DOFRestrictions::LEFT_EYE);
	if(m_reye->getDOFR()->isWeak())		m_reye->setDOFR(DOFRestrictions::RIGHT_EYE);
}
コード例 #7
0
ファイル: QJointNode.cpp プロジェクト: dreamsxin/nawia
void QJointNode::addRepresentation()
{		
	QSceneNode* parentNode = static_cast<QSceneNode*>(parent());
	unsigned int rootID = parentNode ? parentNode->hordeId() : H3DRootNode;

	m_hordeID = h3dAddJointNode(rootID, qPrintable(m_xmlNode.attribute("name", "ATTENTION No Node Name")), m_xmlNode.attribute("jointIndex").toInt());
	
	float x, y, z, rx, ry, rz, sx, sy, sz;
	getTransformation(x,y,z,rx,ry,rz,sx,sy,sz);
	h3dSetNodeTransform(m_hordeID, x, y, z, rx, ry, rz, sx, sy, sz);

	// Attachment
	QDomElement attachment = m_xmlNode.firstChildElement("Attachment");	
	SceneTreeModel* model = static_cast<SceneTreeModel*>(m_model);
	AttachmentPlugIn* plugIn = model->nodeFactory()->attachmentPlugIn();
	if (!attachment.isNull() &&  plugIn != 0)
		plugIn->initNodeAttachment(this);
}
コード例 #8
0
void Camera::setView(const Vector2 &size, const float fovDegrees, const Vector2 &clipDistances)
{
	this->viewSize = size;
	this->fovDegrees = fovDegrees;
	this->clipDistances = clipDistances;

	h3dSetNodeParamI(cameraNode, H3DCamera::ViewportXI, 0);
	h3dSetNodeParamI(cameraNode, H3DCamera::ViewportYI, 0);
	h3dSetNodeParamI(cameraNode, H3DCamera::ViewportWidthI, size.x);
	h3dSetNodeParamI(cameraNode, H3DCamera::ViewportHeightI, size.y);

	h3dSetupCameraView(cameraNode, fovDegrees, viewSize.x / viewSize.y, clipDistances.x, clipDistances.y);
    h3dResizePipelineBuffers(Modules::renderer().getPipelineHandle(), viewSize.x, viewSize.y);

	h3dSetNodeTransform(cameraNode, 0, 1.8f, 10.0f, 0 , 0, 0, 1, 1, 1);

	h3dGetCameraProjMat(cameraNode, projMat.ptr());
	projMat = Matrix4::initPerspMat(fovDegrees, size.x / size.y, clipDistances.x, clipDistances.y);
}
コード例 #9
0
ファイル: QSceneNode.cpp プロジェクト: antmanler/PebbleEngine
void QSceneNode::setRotation(const QVec3f& rotation)
{
	if (signalsBlocked())
	{		
		QVec3f pos = position();
		QVec3f scaling = scale();
		h3dSetNodeTransform(m_hordeID, pos.X, pos.Y, pos.Z, rotation.X, rotation.Y, rotation.Z, scaling.X, scaling.Y, scaling.Z);
		m_xmlNode.setAttribute( "rx", QString::number( rotation.X, 'f', 5 ) );
		m_xmlNode.setAttribute( "ry", QString::number( rotation.Y, 'f', 5 ) );
		m_xmlNode.setAttribute( "rz", QString::number( rotation.Z, 'f', 5 ) );
	}
	else if (rotation != QSceneNode::rotation())
	{
		static const QString undoText = tr("Set Rotation");
		if (m_model->undoStack()->undoText() == undoText)
			m_model->undoStack()->push(new QXmlNodePropertyCommand(undoText, this, "Rotation", QVariant::fromValue(rotation), -1));
		else
			m_model->undoStack()->push(new QXmlNodePropertyCommand(undoText, this, "Rotation", QVariant::fromValue(rotation), TransformationID));
	
	}
}
コード例 #10
0
ファイル: QSceneNode.cpp プロジェクト: antmanler/PebbleEngine
void QSceneNode::setScale(const QVec3f& scale)
{
	if (signalsBlocked())
	{		
		QVec3f pos = position();
		QVec3f rot = rotation();
		h3dSetNodeTransform(m_hordeID, pos.X, pos.Y, pos.Z, rot.X, rot.Y, rot.Z, scale.X, scale.Y, scale.Z);
		m_xmlNode.setAttribute( "sx", QString::number( scale.X, 'f', 5 ) );
		m_xmlNode.setAttribute( "sy", QString::number( scale.Y, 'f', 5 ) );
		m_xmlNode.setAttribute( "sz", QString::number( scale.Z, 'f', 5 ) );
	}
	else if (scale != QSceneNode::scale())
	{
		static const QString undoText = tr("Set Scale");
		if (m_model->undoStack()->undoText() == undoText)
			m_model->undoStack()->push(new QXmlNodePropertyCommand(undoText, this, "Scale", QVariant::fromValue(scale), -1));
		else
			m_model->undoStack()->push(new QXmlNodePropertyCommand(undoText, this, "Scale", QVariant::fromValue(scale), TransformationID));
	
	}
}
コード例 #11
0
void QModelNode::addRepresentation()
{
	m_resourceID = h3dAddResource(H3DResTypes::Geometry, qPrintable(m_xmlNode.attribute("geometry")), 0);

	// Load resource immediately since a later call to loadResourceFromDisk results in a bad behaviour of the Horde3D engine
	QString resourceName = h3dutGetResourcePath(H3DResTypes::Geometry);
	if( !resourceName.isEmpty() && !resourceName.endsWith('/') && !resourceName.endsWith('\\'))
		resourceName += '/';
	resourceName += geometry();

	QFile file(QFileInfo(resourceName).absoluteFilePath());
	if (!file.open(QIODevice::ReadOnly))
		qWarning("Error opening resource %s (%s)", qPrintable(m_xmlNode.attribute("geometry")), qPrintable( QFileInfo(resourceName).absoluteFilePath() ));
	
	// Stupid return value, if false it can also be the case that the resource was loaded before instead of that their was an error
	h3dLoadResource(m_resourceID, file.readAll().constData(), file.size());
	file.close();

	QSceneNode* parentNode = static_cast<QSceneNode*>(parent());
	unsigned int rootID = parentNode ? parentNode->hordeId() : H3DRootNode;

	m_hordeID = h3dAddModelNode(rootID, qPrintable(m_xmlNode.attribute("name", "ATTENTION No Node Name")), m_resourceID);
	
	float x, y, z, rx, ry, rz, sx, sy, sz;
	getTransformation(x,y,z,rx,ry,rz,sx,sy,sz);
	h3dSetNodeTransform(m_hordeID, x, y, z, rx, ry, rz, sx, sy, sz);
	
	h3dSetNodeParamI(m_hordeID, H3DModel::SWSkinningI, softwareSkinning());
	h3dSetNodeParamF(m_hordeID, H3DModel::LodDist1F, 0, lodDist1());
	h3dSetNodeParamF(m_hordeID, H3DModel::LodDist2F, 0, lodDist2());
	h3dSetNodeParamF(m_hordeID, H3DModel::LodDist3F, 0, lodDist3());
	h3dSetNodeParamF(m_hordeID, H3DModel::LodDist4F, 0, lodDist4());

	// Attachment
	QDomElement attachment = m_xmlNode.firstChildElement("Attachment");	
	SceneTreeModel* model = static_cast<SceneTreeModel*>(m_model);
	AttachmentPlugIn* plugIn = model->nodeFactory()->attachmentPlugIn();
	if (!attachment.isNull() &&  plugIn != 0)
		plugIn->initNodeAttachment(this);
}
コード例 #12
0
	void gameLoop()
	{
		frameNum++;

		//LOG("doFrame()...");
		doFrame();

		h3dSetNodeTransform(cam,
				//0, 0, 0,
				0, 10, 10,
				_rx ,_ry, 0,
				1, 1, 1
				);

		//LOG("h3dRender(cam)...");
		h3dRender(cam);

		//LOG("h3dutShowFrameStats(fontMatRes, panelMatRes, 2)...");
		h3dutShowFrameStats(fontMatRes, panelMatRes, 2);

#if 0
		//int n = snprintf(text, textLen - 1, "Frame %d: %f ms", frameNum, msSinceLastFrame());
		//int n = snprintf(text, textLen - 1, "Frame %d", frameNum % 32);
		int n = snprintf(text, textLen - 1, "Frame %d", frameNum);

		LOG("Showing text \"%s\" (wrote %d chars) with color (%d, %d, %d)", text, n, frameNum % 2, (frameNum >> 1) % 2, (frameNum >> 2) % 2);
		h3dutShowText(text,
				0.5, 0.5,   // Position
				0.05,       // Size (scale)
				frameNum % 2, (frameNum >> 1) % 2, (frameNum >> 2) % 2, // Color (RGB)
				fontMatRes  // Font material
				);
#endif

		//LOG("h3dFinalizeFrame()...");
		h3dFinalizeFrame();

		//LOG("Frame finished.");
	} // end gameLoop
コード例 #13
0
void SceneGraphComponent::setParentNode(H3DNode newParentNode, const Attach* data)
{
	if (m_hordeID > 0)
	{
		if(data->Child && strcmp(data->Child,"") != 0 )
		{
			int nodes = h3dFindNodes( newParentNode, data->Child, H3DNodeTypes::Undefined );
			H3DNode child = h3dGetNodeFindResult(0);
	
			h3dSetNodeParent(m_hordeID, child);
		}
		else
		{
			h3dSetNodeParent(m_hordeID, newParentNode);
		}

		h3dSetNodeTransform(m_hordeID,data->Tx,data->Ty, data->Tz,
			data->Rx, data->Ry, data->Rz,
			data->Sx, data->Sy, data->Sz);

		checkTransformation();
	}
}
コード例 #14
0
ファイル: scenario.cpp プロジェクト: cewbost/dlrts
void Camera::_update()
{
  Utils::Vec3f pos = _relative + _target;
  Utils::Vec3f angle = (-_relative).toRotation();

  angle.x = Utils::radToDeg(angle.x);
  angle.y = Utils::radToDeg(angle.y);
  angle.z = Utils::radToDeg(angle.z);

  h3dSetNodeTransform(
    handle,
    pos.x, pos.y, pos.z,
    angle.x, angle.y, angle.z,
    //angle.x, angle.y, angle.z,
    1.0, 1.0, 1.0);

  const float* mat_data;
  h3dGetNodeTransMats(handle, nullptr, &mat_data);
  _inv_modelview_mat = Utils::Matrix4f(mat_data).inverted();
  Utils::Matrix4f::fastMult43(_screenspace_mat, _proj_mat,
                              _inv_modelview_mat);

  return;
}
コード例 #15
0
void QTerrainNode::addRepresentation()
{
	m_heightMapID = h3dAddResource(
		H3DResTypes::Texture, 
		qPrintable(m_xmlNode.attribute("heightmap")), 
		H3DResFlags::NoTexCompression | H3DResFlags::NoTexMipmaps );
	m_materialID = h3dAddResource(H3DResTypes::Material, qPrintable(m_xmlNode.attribute("material")), 0);
	// Load resource immediately since a later call to loadResourceFromDisk results in a bad behaviour of the Horde3D engine
	QDir textureDir( QDir::current() );
	QFile file(textureDir.absoluteFilePath(m_xmlNode.attribute("heightmap")));
	if (!file.open(QIODevice::ReadOnly))
		qWarning("Error opening resource %s", qPrintable(m_xmlNode.attribute("heightmap")));
	
	// Stupid return value, if false it can also be the case that the resource was loaded before instead of that their was an error
	h3dLoadResource(m_heightMapID, file.readAll().constData(), file.size());
	file.close();

	QSceneNode* parentNode = static_cast<QSceneNode*>(parent());
	unsigned int rootID = parentNode ? parentNode->hordeId() : H3DRootNode;

	m_hordeID = h3dextAddTerrainNode(rootID, qPrintable(m_xmlNode.attribute("name", "ATTENTION No Node Name")), m_heightMapID, m_materialID);
	h3dSetNodeParamI(m_hordeID, H3DEXTTerrain::BlockSizeI, blockSize());
	h3dSetNodeParamF(m_hordeID, H3DEXTTerrain::MeshQualityF, 0, meshQuality());
	h3dSetNodeParamF(m_hordeID, H3DEXTTerrain::SkirtHeightF, 0, skirtHeight());

	float x, y, z, rx, ry, rz, sx, sy, sz;
	getTransformation(x,y,z,rx,ry,rz,sx,sy,sz);
	h3dSetNodeTransform(m_hordeID, x, y, z, rx, ry, rz, sx, sy, sz);

	// Attachment		
	QDomElement attachment = m_xmlNode.firstChildElement("Attachment");	
	SceneTreeModel* model = static_cast<SceneTreeModel*>(m_model);
	AttachmentPlugIn* plugIn = model->nodeFactory()->attachmentPlugIn();
	if (!attachment.isNull() &&  plugIn != 0)
		plugIn->initNodeAttachment(this);
}
コード例 #16
0
	H3DView(int winWidth, int winHeight) :
			BulletEngineTest(),
			//model(0),
			cam(0),
			frameNum(0),
			text(NULL), textLen(32),
			_rx(15), _ry(-50),
			//_rx(0), _ry(0),
			_prev_x(0), _prev_y(0),
			_mouseEnteredThisFrame(false)
	{
		assert(view == NULL);
		view = this;

		text = new char[textLen];
		memset(text, 0, textLen);

		LOG("Initializing Horde3D...");
		h3dInit();

		h3dSetOption(H3DOptions::MaxAnisotropy, 8);
		h3dSetOption(H3DOptions::SampleCount, 16);

		//h3dSetOption(H3DOptions::WireframeMode, 1);
		//h3dSetOption(H3DOptions::DebugViewMode, 1);
		h3dSetOption(H3DOptions::GatherTimeStats, 1);

		LOG("Declaring resources...");

		pipeRes = h3dAddResource(H3DResTypes::Pipeline, "pipelines/forward.pipeline.xml", 0);

		H3DRes skyBoxRes = h3dAddResource(H3DResTypes::SceneGraph, "models/skybox/skybox.scene.xml", 0);

		//modelRes = h3dAddResource(H3DResTypes::SceneGraph, "models/AssJacket/AssJacket.scene.xml", 0);
		//modelRes = h3dAddResource(H3DResTypes::SceneGraph, "models/ares/ares.scene.xml", 0);
		modelRes = h3dAddResource(H3DResTypes::SceneGraph, "models/man/man.scene.xml", 0);

		fontMatRes = h3dAddResource(H3DResTypes::Material, "overlays/font.material.xml", 0);
		panelMatRes = h3dAddResource(H3DResTypes::Material, "overlays/panel.material.xml", 0);

		LOG("Loading resources from disk...");
		h3dutLoadResourcesFromDisk("/home/whitelynx/devel/other/Horde3D/build-make/Binaries/Content"
				"|/home/whitelynx/devel/skewedaspect/precursors-client/resources/content");

		LOG("Building scene...");
		/*
		// Add model to scene
		model = h3dAddNodes(H3DRootNode, modelRes);
		h3dSetNodeTransform(model,
				0, 0, -500,  // Translation
				0, 0, 0,     // Rotation
				1, 1, 1      // Scale
				);
		*/

		// Add light source
		H3DNode light = h3dAddLightNode(H3DRootNode, "Light1", 0, "LIGHTING", "SHADOWMAP");
		// Set light position and radius
		h3dSetNodeTransform(light,
				0, 20, 0,
				0, 0, 0,
				10, 10, 10
				);
		h3dSetNodeParamF(light, H3DLight::RadiusF, 0, 50.0f);

		LOG("Setting up camera...");
		cam = h3dAddCameraNode(H3DRootNode, "Camera", pipeRes);

		resizeViewport(winWidth, winHeight);

#if 1
		H3DNode sky = h3dAddNodes(H3DRootNode, skyBoxRes);
		h3dSetNodeTransform(sky,
				0, 0, 0,      // Translation
				0, 0, 0,      // Rotation
				210, 50, 210  // Scale
				);
		h3dSetNodeFlags(sky, H3DNodeFlags::NoCastShadow, true);
#endif

		LOG("Setting BulletEngine callbacks...");
		setMakeModelCallback(&makeModelCB);
		setUpdateModelCallback(&updateModelCB);

		LOG("Initializing physics...");
		initPhysics();

		LOG("Ready.");
	} // end H3DView
コード例 #17
0
void QEmitterNode::addRepresentation()
{	
	m_matResource = h3dAddResource(H3DResTypes::Material, qPrintable(m_xmlNode.attribute("material")), 0);

	// Load resource immediately since a later call to loadResourceFromDisk results in a bad behaviour of the Horde3D engine
	QString resourceName = h3dutGetResourcePath(H3DResTypes::Material);
	if( !resourceName.isEmpty() && !resourceName.endsWith('/') && !resourceName.endsWith('\\') )
		resourceName += '/';
	resourceName += m_xmlNode.attribute("material");

	QFile matFile(QFileInfo(resourceName).absoluteFilePath());
	if (!matFile.open(QIODevice::ReadOnly))
		qWarning("Error opening resource %s", qPrintable(m_xmlNode.attribute("material")));

	// Stupid return value, if false it can also be the case that the resource was loaded before instead of that their was an error



	h3dLoadResource(m_matResource, matFile.readAll().append('\0').constData(), matFile.size() + 1);
	matFile.close();

	m_effectResource = h3dAddResource(H3DResTypes::ParticleEffect, qPrintable(m_xmlNode.attribute("particleEffect")), 0);

	// Load resource immediately since a later call to loadResourceFromDisk results in a bad behaviour of the Horde3D engine
	resourceName = h3dutGetResourcePath(H3DResTypes::ParticleEffect);
	if (!resourceName.isEmpty() && !resourceName.endsWith('/') && !resourceName.endsWith('\\'))
		resourceName += '/';
	resourceName += m_xmlNode.attribute("particleEffect");

	QFile effectFile(QFileInfo(resourceName).absoluteFilePath());
	if (!effectFile.open(QIODevice::ReadOnly))
		qWarning("Error opening resource %s", qPrintable(m_xmlNode.attribute("particleEffect")));

	// Stupid return value, if false it can also be the case that the resource was loaded before instead of that their was an error
	h3dLoadResource(m_effectResource, effectFile.readAll().append('\0').constData(), effectFile.size()+1);
	effectFile.close();

	QSceneNode* parentNode = static_cast<QSceneNode*>(parent());
	unsigned int rootID = parentNode ? parentNode->hordeId() : H3DRootNode;

	m_hordeID = h3dAddEmitterNode(
		rootID, 
		qPrintable(m_xmlNode.attribute("name", "ATTENTION No Node Name")), 
		m_matResource, 
		m_effectResource, 
		m_xmlNode.attribute("maxCount").toUInt(),
		m_xmlNode.attribute("respawnCount").toInt()
	);

	h3dSetNodeParamF(m_hordeID, H3DEmitter::ForceF3, 0, m_xmlNode.attribute("forceX", "0.0").toFloat());
	h3dSetNodeParamF(m_hordeID, H3DEmitter::ForceF3, 1, m_xmlNode.attribute("forceY", "0.0").toFloat());
	h3dSetNodeParamF(m_hordeID, H3DEmitter::ForceF3, 2, m_xmlNode.attribute("forceZ", "0.0").toFloat());
	h3dSetNodeParamF(m_hordeID, H3DEmitter::DelayF, 0, m_xmlNode.attribute("delay", "0.0").toFloat());
	h3dSetNodeParamF(m_hordeID, H3DEmitter::SpreadAngleF, 0, m_xmlNode.attribute("spreadAngle", "0.0").toFloat());
	h3dSetNodeParamF(m_hordeID, H3DEmitter::EmissionRateF, 0, m_xmlNode.attribute("emissionRate", "0.0").toFloat());

	// load transformation from file...
	float x, y, z, rx, ry, rz, sx, sy, sz;
	getTransformation(x,y,z,rx,ry,rz,sx,sy,sz);
	// ...and update scene representation
	h3dSetNodeTransform(m_hordeID, x, y, z, rx, ry, rz, sx, sy, sz);
	
	// Attachment
	QDomElement attachment = m_xmlNode.firstChildElement("Attachment");	
	SceneTreeModel* model = static_cast<SceneTreeModel*>(m_model);
	AttachmentPlugIn* plugIn = model->nodeFactory()->attachmentPlugIn();
	if (!attachment.isNull() &&  plugIn != 0)
		plugIn->initNodeAttachment(this);

	startTimer(100);
}
コード例 #18
0
ファイル: app.cpp プロジェクト: dreamsxin/nawia
bool Application::init()
{	
	// Initialize engine and open default sound device
	if( !h3dInit() || !h3dOpenDevice( 0x0 ) )
	{	
		h3dutDumpMessages();
		return false;
	}

	// Set options
	h3dSetOption( H3DOptions::LoadTextures, 1 );
	h3dSetOption( H3DOptions::TexCompression, 0 );
	h3dSetOption( H3DOptions::FastAnimation, 0 );
	h3dSetOption( H3DOptions::MaxAnisotropy, 4 );
	h3dSetOption( H3DOptions::ShadowMapSize, 2048 );

	// Add resources
	// Pipelines
	_hdrPipeRes = h3dAddResource( H3DResTypes::Pipeline, "pipelines/hdr.pipeline.xml", 0 );
	_forwardPipeRes = h3dAddResource( H3DResTypes::Pipeline, "pipelines/forward.pipeline.xml", 0 );
	// Overlays
	_fontMatRes = h3dAddResource( H3DResTypes::Material, "overlays/font.material.xml", 0 );
	_panelMatRes = h3dAddResource( H3DResTypes::Material, "overlays/panel.material.xml", 0 );
	_logoMatRes = h3dAddResource( H3DResTypes::Material, "overlays/logo.material.xml", 0 );
	// Environment
	H3DRes floorRes = h3dAddResource( H3DResTypes::SceneGraph, "models/tiles/tiles.scene.xml", 0 );
	// Knight
	H3DRes speakerRes = h3dAddResource( H3DResTypes::SceneGraph, "models/speaker/speaker.scene.xml", 0 );
	// Music
	_soundRes = h3dAddResource( RST_SoundResource, "sounds/stringed_disco.ogg", 0 );

	// Load resources
	h3dutLoadResourcesFromDisk( _contentDir.c_str() );

	// Add scene nodes
	// Add camera
	_cam = h3dAddCameraNode( H3DRootNode, "Camera", _hdrPipeRes );
	//h3dSetNodeParamI( _cam, CameraNodeParams::OcclusionCulling, 1 );
	// Add listener to the camera
	H3DNode listener = h3dAddListenerNode( _cam, "Listener" );
	h3dSetActiveListener( listener );
	// Add floor
	H3DNode floor = h3dAddNodes( H3DRootNode, floorRes );
	h3dSetNodeTransform( floor, 0, -0.125, 0, 0, 0, 0, 1, 1, 1 );
	// Add the speakers
	H3DNode speaker1 = h3dAddNodes( H3DRootNode, speakerRes );
	h3dSetNodeTransform( speaker1, -2, 0, -2, 0, 215.0f, 0, 1, 1, 1 );
	H3DNode speaker2 = h3dAddNodes( H3DRootNode, speakerRes );
	h3dSetNodeTransform( speaker2, 2, 0, -2, 0, 145.0f, 0, 1, 1, 1 );
	// Add music to the speakers
	_sound1 = h3dAddSoundNode( speaker1, "Sound1", _soundRes );
	_sound2 = h3dAddSoundNode( speaker2, "Sound2", _soundRes );
	// Add light source
	_light = h3dAddLightNode( H3DRootNode, "Light1", 0, "LIGHTING", "SHADOWMAP" );
	h3dSetNodeTransform( _light, 0, 7, 0, -90, 0, 0, 1, 1, 1 );
	h3dSetNodeParamF( _light, H3DLight::RadiusF, 0, 30 );
	h3dSetNodeParamF( _light, H3DLight::FovF, 0, 90 );
	h3dSetNodeParamI( _light, H3DLight::ShadowMapCountI, 1 );
	h3dSetNodeParamF( _light, H3DLight::ShadowMapBiasF, 0, 0.01f );

	// Set the distance model
	h3dSetDistanceModel( _distanceModel );
	// Set the timer so the light immediately gets a random color
	_lightTimer = 1.0f;

	// Customize post processing effects
	H3DRes matRes = h3dFindResource( H3DResTypes::Material, "pipelines/postHDR.material.xml" );
	// hdrParams: exposure, brightpass threshold, brightpass offset (see shader for description)
	h3dSetMaterialUniform( matRes, "hdrParams", 2.0f, 0.6f, 0.08f, 0 );

	// Play the music
	h3dPlaySound( _sound1 );
	h3dPlaySound( _sound2 );

	return true;
}
コード例 #19
0
ファイル: app.cpp プロジェクト: dreamsxin/nawia
void Application::mainLoop( float timeSinceLastFrame )
{
	keyHandler( timeSinceLastFrame );

	// Set camera parameters
	h3dSetNodeTransform( _cam, _x, _y, _z, _rx ,_ry, 0, 1, 1, 1 );

	_lightTimer += timeSinceLastFrame;

	// Has it gone a second since the light changed color?
	if( _lightTimer >= 1.0f )
	{
		// Set a random light color
		switch( rand() % 6 )
		{
		case 0:
			// Red
			h3dSetNodeParamF( _light, H3DLight::ColorF3, 0, 1.0f );
			h3dSetNodeParamF( _light, H3DLight::ColorF3, 1, 0.0f );
			h3dSetNodeParamF( _light, H3DLight::ColorF3, 2, 0.0f );
			break;
		case 1:
			// Green
			h3dSetNodeParamF( _light, H3DLight::ColorF3, 0, 0.0f );
			h3dSetNodeParamF( _light, H3DLight::ColorF3, 1, 1.0f );
			h3dSetNodeParamF( _light, H3DLight::ColorF3, 2, 0.0f );
			break;
		case 2:
			// Blue
			h3dSetNodeParamF( _light, H3DLight::ColorF3, 0, 0.0f );
			h3dSetNodeParamF( _light, H3DLight::ColorF3, 1, 0.0f );
			h3dSetNodeParamF( _light, H3DLight::ColorF3, 2, 1.0f );
			break;
		case 3:
			// Yellow
			h3dSetNodeParamF( _light, H3DLight::ColorF3, 0, 1.0f );
			h3dSetNodeParamF( _light, H3DLight::ColorF3, 1, 1.0f );
			h3dSetNodeParamF( _light, H3DLight::ColorF3, 2, 0.0f );
			break;
		case 4:
			// Purple
			h3dSetNodeParamF( _light, H3DLight::ColorF3, 0, 1.0f );
			h3dSetNodeParamF( _light, H3DLight::ColorF3, 1, 0.0f );
			h3dSetNodeParamF( _light, H3DLight::ColorF3, 2, 1.0f );
			break;
		case 5:
			// Cyan
			h3dSetNodeParamF( _light, H3DLight::ColorF3, 0, 0.0f );
			h3dSetNodeParamF( _light, H3DLight::ColorF3, 1, 1.0f );
			h3dSetNodeParamF( _light, H3DLight::ColorF3, 2, 1.0f );
			break;
		}

		// Reset the timer
		_lightTimer = 0.0f;
	}

	// Show stats
	h3dutShowFrameStats( _fontMatRes, _panelMatRes, _statMode );
	if( _statMode > 0 )
	{	
		displaySoundInfo();
	}

	// Show logo
	const float ww = (float)h3dGetNodeParamI( _cam, H3DCamera::ViewportWidthI ) /
	                 (float)h3dGetNodeParamI( _cam, H3DCamera::ViewportHeightI );
	const float ovLogo[] = { ww-0.4f, 0.8f, 0, 1,  ww-0.4f, 1, 0, 0,  ww, 1, 1, 0,  ww, 0.8f, 1, 1 };
	h3dShowOverlays( ovLogo, 4, 1.f, 1.f, 1.f, 1.f, _logoMatRes, 0 );

	// Render scene
	h3dRender( _cam );

	// Finish rendering of frame
	h3dFinalizeFrame();

	// Remove all overlays
	h3dClearOverlays();

	// Write all mesages to log file
	h3dutDumpMessages();
}
コード例 #20
0
ファイル: Gaze.cpp プロジェクト: dreamsxin/nawia
bool Gaze::computeHeadRotation( Horde3D::Vec3f *out_axis, float *out_angleRad)
{
	//Saving the current eye transformation
	Horde3D::Vec3f p,r,s;
	m_leye->update();
	Horde3D::Matrix4f eyeTransf( m_leye->getRelTransf()->x );
	eyeTransf.decompose( p, r, s );

	//Computing the head pitch
	// Allow (-10 , +10) values for head_picth 
	// where -10 means a higher angle for the "pointing joint" therefor a "less arrogant" gaze
	// and +10 means a lower angle for the "point joint" therefor a "more arrogant" gaze
	if(m_headpitch > 10) m_headpitch = 10;
	else if(m_headpitch < -10) m_headpitch = -10;		
	m_headpitch = (m_headpitch > 0) ?
		m_headpitch + (int)((m_headpitch/2)*(m_headpitch/2)) :
		m_headpitch - (int)((m_headpitch/2)*(m_headpitch/2));

	
	//We simplify the geometric problem by saying that the head's rotational adjustment is the same as the eye's
	//if we position it at the center of the distance between the two eyes
	//This, depending on the skeleton, may be inaccurate
	
	//First, we must temporary position the eye in the center of the face, 
	//clear its rotations and calculate the endPos
	//This computation is skeleton specific. Remove comments from desired aproach (TODO: better implementation)
	//You MUST also set the DfltEyeRot parameters to correspond to the "looking straight ahead" rotation of the eyes

	//** 1. Eyetype: x-axis goes left (or right), y-axis goes up (or down), z-axis comes out of the eye
	//		Known skeletons: 
	//		- Ritchie (some versions, Bip01-Skeleton used at Human Centered Multimedia, Augsburg University)
	//h3dSetNodeTransform( m_leye->getHordeID(), 
	//	0, p.y, p.z, 
	//	(float)(Config::getParamF(IK_Param::DfltEyeRotX_F) + m_headpitch), Config::getParamF(IK_Param::DfltEyeRotY_F), Config::getParamF(IK_Param::DfltEyeRotZ_F),
	//	1, 1, 1);

	//** 2. Eyetype: x-axis goes up (or down), y-axis goes left (or right), z-axis comes out of the eye
	//		Known skeletons: 
	//		- Biergarten Agents (Bip01-Skeleton used at Human Centered Multimedia, Augsburg University)
	//		- Ritchie (some versions, Bip01-Skeleton used at Human Centered Multimedia, Augsburg University)
	h3dSetNodeTransform( m_leye->getHordeID(), 
		p.x, 0, p.z, 
		Config::getParamF(IK_Param::DfltEyeRotX_F), (float)(Config::getParamF(IK_Param::DfltEyeRotY_F) + m_headpitch), Config::getParamF(IK_Param::DfltEyeRotZ_F),
		1, 1, 1);

	//** 3. Eyetype: x-axis comes out of the eye, y-axis goes up (or down), z-axis goes left (or right)
	//		Known skeletons:
	//		- Hamster (CAT-Skeleton used at Human Centered Multimedia, Augsburg University)
	//h3dSetNodeTransform( m_leye->getHordeID(), 
	//	p.x, p.y, 0, 
	//	Config::getParamF(IK_Param::DfltEyeRotX_F), Config::getParamF(IK_Param::DfltEyeRotY_F), (float)(Config::getParamF(IK_Param::DfltEyeRotZ_F) + m_headpitch),
	//	1, 1, 1);

	m_aux_leye->update();
	Horde3D::Vec3f endPos = m_aux_leye->getAbsTranslation();
	
	//Second, we have to align the eye's coordinate system with the head's coordinate system	
	//We eliminate all rotations from the eye's coordinate system
	h3dSetNodeTransform( m_leye->getHordeID(), 
		p.x, 0, p.z, 
		0, 0, 0, 
		1, 1, 1);

	m_leye->update();
	//We create the 2 vectors and normalize them
	Horde3D::Vec3f targetVec = m_leye->getAbsTransf()->inverted() * m_target;
	Horde3D::Vec3f currentVec = m_leye->getAbsTransf()->inverted() * endPos;

	targetVec = targetVec.normalized();
	currentVec = currentVec.normalized();

	//Finally, we reset the transformations
	h3dSetNodeTransMat( m_leye->getHordeID(), eyeTransf.x );

	//get angle between vectors
	float angleCos = targetVec.dot(currentVec);

	if(angleCos < 1.0f - Config::getParamF(IK_Param::CCDRotJitterTolerance_F) ) 
	{
		*out_angleRad = -acosf(angleCos);
		
		//get vector perpendicular to the plain described by two vectors
		*out_axis = targetVec.cross( currentVec );
		*out_axis = out_axis->normalized();

		return true;
	}
	return false;
}
コード例 #21
0
ファイル: Tentacle.cpp プロジェクト: CalebVDW/smr-motion
void TentacleApplication::mainLoop( float fps )
{
  _curFPS = fps;
  _timer += 1 / fps;
  keyHandler();

  h3dSetOption( H3DOptions::DebugViewMode, _debugViewMode ? 1.0f : 0.0f );
  h3dSetOption( H3DOptions::WireframeMode, _wireframeMode ? 1.0f : 0.0f );

  if( !_freeze )
  {
    float tx,ty,tz,foo;
    h3dGetNodeTransform(_fly,&tx,&ty,&tz,&foo,&foo,&foo,&foo,&foo,&foo);
    if (!_freezeFly)
    {
      // routhly simulates the random fly of a fly
      if((rand() % 100)>95)
      {
        _dx = ((ranf()))/50.0f;
        _dy = ((ranf()))/50.0f;
        _dz = ((ranf()))/50.0f;
      }
      // change fly position
      h3dSetNodeTransform( _fly, tx+_dx, ty+_dy, tz+_dz, 0, 0, 0, 0.2f, 0.2f, 0.2f );
      if (tx < -4.0) _dx =  0.05f;
      if (tx >  4.0) _dx = -0.05f;
      if (ty <  0.0) _dy =  0.05f;
      if (ty >  6.0) _dy = -0.05f;
      if (tz < -4.0) _dz =  0.05f;
      if (tz >  4.0) _dz = -0.05f;
      h3dGetNodeTransform(_fly,&tx,&ty,&tz,&foo,&foo,&foo,&foo,&foo,&foo);


      //update constraint position according to fly position
      _ikConstraint->setPosition(SMRVector3(tx, ty, tz));
    }

    if (!_freezeIK || _ikStep)
    {
      //Compute inverse kinematics
      _currentSolver->process();

      // update tentacle's joint (IK)
      updateTentacle();
      _ikStep = false;
    }
  }

  // Set camera parameters
  h3dSetNodeTransform( _cam, _x, _y, _z, _rx ,_ry, 0, 1, 1, 1 );

  if( _showFPS )
  {
    // Avoid updating FPS text every frame to make it readable
    if( _timer > 0.3f )
    {
      _fpsText.str( "" );
      _fpsText << "FPS: " << fixed << setprecision( 2 ) << _curFPS;
      _timer = 0;
    }

    // Show text
    //h3dutShowText( _fpsText.str().c_str(), 0, 0.95f, 0.03f, 0, _fontMatRes );
  }

  // Show title
  //h3dutShowText( "Comparing Standard IK algorithms.", 0.0f, 0.90f, 0.03f, 0, _fontMatRes );

  // Show IK method
  //h3dutShowText( _ikMethodString, 0.6f, 0.80f, 0.03f, 0, _fontMatRes );


  // Show logo
  //h3dShowOverlay( 0.7f, 0.2, 0, 0,
  //					    1, 0.2, 1, 0,
  //                        1, 0.6f, 1, 1, 
  //						0.7f, 0.6f, 0, 1,
  //                      7, _invJacMatRes );

  // Render scene
  h3dRender( _cam );

  // Remove all overlays
  h3dClearOverlays();

  // Write all mesages to log file
  h3dutDumpMessages();
}
コード例 #22
0
ファイル: crowd.cpp プロジェクト: Amroll/Horde3D
void CrowdSim::update( float fps )
{
	// Parameters for three repulsion zones
	float d1 = 0.25f, d2 = 2.0f, d3 = 4.5f;
	float f1 = 3.0f, f2 = 1.0f, f3 = 0.1f;
	
	for( unsigned int i = 0; i < _particles.size(); ++i )
	{
		Particle &p = _particles[i];
		
		// Reset force
		p.fx = 0; p.fz = 0;
		
		// Calculate distance to destination
		float dist = sqrtf( (p.dx - p.px)*(p.dx - p.px) + (p.dz - p.pz)*(p.dz - p.pz) );
		
		// If destination not reached walk to destination
		if( dist > 3.0f )
		{
			// Calculate normalized attraction force to destination
			float afx = (p.dx - p.px) / dist;
			float afz = (p.dz - p.pz) / dist;	

			p.fx += afx * 0.035f; p.fz += afz * 0.035f;

			// Repulsion forces from other particles
			for( unsigned int j = 0; j < _particles.size(); ++j )
			{
				if( j == i ) continue;
				
				Particle &p2 = _particles[j];
				
				float dist2 = sqrtf( (p.px - p2.px)*(p.px - p2.px) + (p.pz - p2.pz)*(p.pz - p2.pz) );
				float strength = 0;

				float rfx = (p.px - p2.px) / dist2;
				float rfz = (p.pz - p2.pz) / dist2;
				
				// Use three zones with different repulsion strengths
				if( dist2 <= d3 && dist2 > d2 )
				{
					float m = (f3 - 0) / (d2 - d3);
					float t = 0 - m * d3;
					strength = m * dist2 + t;
				}
				else if( dist2 <= d2 && dist2 > d1 )
				{
					float m = (f2 - f3) / (d1 - d2);
					float t = f3 - m * d2;
					strength = m * dist2 + t;
				}
				else if( dist2 <= d1 )
				{
					float m = (f1 - f2) / (0 - d1);
					float t = f2 - m * d1;
					strength = m * dist2 + t;
				}

				p.fx += rfx * strength; p.fz += rfz * strength;
			}
		}
		else
		{
			// Choose new destination
			chooseDestination( p );
		}

		// Make movement framerate independent
		p.fx *= (30 / fps);
		p.fz *= (30 / fps);
		float vel = sqrtf( p.fx * p.fx + p.fz * p.fz );
		
		// Set new position
		p.px += p.fx; p.pz += p.fz;
		
		// Calculate orientation
		p.ox = (p.ox + p.fx) / 2;
		p.oz = (p.oz + p.fz) / 2;

		// Get rotation from orientation
		float ry = 0;
		if( p.oz != 0 ) ry = atan2( p.ox, p.oz );
		ry *= 180 / 3.1415f;	// Convert from radians to degrees
		
		// Update character scene node position
		h3dSetNodeTransform( p.node, p.px, 0.02f, p.pz, 0, ry, 0, 1, 1, 1 );
		
		// Update animation
		p.animTime += vel * 35.0f;
		h3dSetModelAnimParams( p.node, 0, p.animTime, 1.0f );
		h3dUpdateModel( p.node, H3DModelUpdateFlags::Animation | H3DModelUpdateFlags::Geometry );
	}
}
コード例 #23
0
ファイル: Tentacle.cpp プロジェクト: CalebVDW/smr-motion
bool TentacleApplication::init()
{
  // Initialize engine
  if( !h3dInit() )
  {
    h3dutDumpMessages();
    return false;
  }

	// Set options
	h3dSetOption( H3DOptions::LoadTextures, 1 );
	h3dSetOption( H3DOptions::TexCompression, 0 );
	h3dSetOption( H3DOptions::MaxAnisotropy, 4 );
	h3dSetOption( H3DOptions::ShadowMapSize, 2048 );
	h3dSetOption( H3DOptions::FastAnimation, 1 );

  // Add resources
  // Pipelines
  _hdrPipeRes = h3dAddResource( H3DResTypes::Pipeline, "pipelines/hdr.pipeline.xml", 0 );
  _forwardPipeRes = h3dAddResource( H3DResTypes::Pipeline, "pipelines/forward.pipeline.xml", 0 );
  // Font
  _fontMatRes = h3dAddResource( H3DResTypes::Material, "overlays/font.material.xml", 0 );
  // Logo
  _logoMatRes = h3dAddResource( H3DResTypes::Material, "overlays/logo.material.xml", 0 );
  // invJacXpl
  //_invJacMatRes = h3dAddResource( H3DResTypes::Material, "materials/invJac.material.xml", 0 );
  // Environment
  H3DRes envRes = h3dAddResource( H3DResTypes::SceneGraph, "models/sphere/sphere.scene.xml", 0 );
  // Tentacle
  H3DRes tentacleRes = h3dAddResource( H3DResTypes::SceneGraph, "models/tentacle.scene.xml", 0 );
  // Fly
  H3DRes flyRes = h3dAddResource( H3DResTypes::SceneGraph, "models/fly.scene.xml", 0 );

  _dx = _dy = _dz = 0;

  // Load resources
  h3dutLoadResourcesFromDisk( _contentDir.c_str() );

  // Add scene nodes
  // Add camera
  _cam = h3dAddCameraNode( H3DRootNode, "Camera", _forwardPipeRes );
  // Add environment
  H3DNode env = h3dAddNodes( H3DRootNode, envRes );
  h3dSetNodeTransform( env, 0, -20, 0, 0, 0, 0, 20, 20, 20 );

  // Add tentacle node
  _tentacle = h3dAddNodes( H3DRootNode, tentacleRes );
  h3dSetNodeTransform( _tentacle, 0, 0, 0, 0, 0, 0.0, 1.0f, 1.0f, 1.0f );

  // Create tentacle kinematic chain
  _tentacleIK = setUpKinematikChain(_tentacle);
  //cout << _tentacleIK->getEndPosition(_tentacleIK->getNumJoints()-1);
  //_ikCCDSolver = new SmrCCDSolver(_tentacleIK);
  //_ikCCDSolver->addConstraintPtr(_ikConstraint);

  _ikGSMMSolver = new SMRGSMMSolver(_tentacleIK);
  _ikGSMMSolver->addConstraintPtr(_ikConstraint);

  _ikInvJacSolver = new SMRInvJacSolver(_tentacleIK);
  _ikInvJacSolver->addConstraintPtr(_ikConstraint);

  //delete(_tentacleIK);

  _currentSolver = _ikInvJacSolver;
  _ikMethodString = "J pseudo-inverse";

  // Add fly node
  _fly = h3dAddNodes( H3DRootNode, flyRes );
  h3dSetNodeTransform( _fly, 0, 4, 0, 0, 0, 0, 0.2f, 0.2f, 0.2f );

  // Add light source
  H3DNode light = h3dAddLightNode( H3DRootNode, "Light1", 0, "LIGHTING", "SHADOWMAP" );
  h3dSetNodeTransform( light, 0, 15, 10, -60, 0, 0, 1, 1, 1 );
  h3dSetNodeParamF( light, H3DLight::RadiusF,0, 30 );
  h3dSetNodeParamF( light, H3DLight::FovF,0, 90 );
  h3dSetNodeParamI( light, H3DLight::ShadowMapCountI, 0 );
  h3dSetNodeParamF( light, H3DLight::ShadowMapBiasF,0, 0.01f );
  h3dSetNodeParamF( light, H3DLight::ColorF3,0, 1.0f );
  h3dSetNodeParamF( light, H3DLight::ColorF3,1, 0.8f );
  h3dSetNodeParamF( light, H3DLight::ColorF3,2, 0.7f );

  // Customize post processing effects
	H3DNode matRes = h3dFindResource( H3DResTypes::Material, "pipelines/postHDR.material.xml" );

  //hdrParams: exposure, brightpass threshold, brightpass offset (see shader for description)
	h3dSetMaterialUniform( matRes, "hdrParams", 2.5f, 0.5f, 0.08f, 0 );

  return true;
}