void QEmitterNode::setForce(const QVec3f &value)
{
	if (signalsBlocked())
	{
		m_xmlNode.setAttribute("forceX", value.X);
		m_xmlNode.setAttribute("forceY", value.Y);
		m_xmlNode.setAttribute("forceZ", value.Z);
		h3dSetNodeParamF(m_hordeID, H3DEmitter::ForceF3, 0, value.X);
		h3dSetNodeParamF(m_hordeID, H3DEmitter::ForceF3, 1, value.Y);
		h3dSetNodeParamF(m_hordeID, H3DEmitter::ForceF3, 2, value.Z);
	}
	else if (value != QEmitterNode::force())
		m_model->undoStack()->push(new QXmlNodePropertyCommand(tr("Set Force"), this, "Force", QVariant::fromValue(value), EmitterForceID));
}
void QEmitterNode::setDelay(float value)
{
	if (signalsBlocked())
	{
		m_xmlNode.setAttribute("delay", value);
		h3dSetNodeParamF(m_hordeID, H3DEmitter::DelayF, 0, value);
	}
	else if (value != QEmitterNode::delay())
		m_model->undoStack()->push(new QXmlNodePropertyCommand(tr("Set Delay"), this, "Delay", value, EmitterDelayID));
}
void QEmitterNode::setSpreadAngle(float value)
{
	if (signalsBlocked())
	{
		m_xmlNode.setAttribute("spreadAngle", value);
		h3dSetNodeParamF(m_hordeID, H3DEmitter::SpreadAngleF, 0, value);
	}
	else if (value != QEmitterNode::spreadAngle())
		m_model->undoStack()->push(new QXmlNodePropertyCommand(tr("Set Spread Angle"), this, "Spread_Angle", value, EmitterSpreadAngleID));
}
void QEmitterNode::setEmissionRate(int value)
{
	if (signalsBlocked())
	{
		m_xmlNode.setAttribute("emissionRate", value);
		h3dSetNodeParamF(m_hordeID, H3DEmitter::EmissionRateF, 0, value);
	}
	else if (value != QEmitterNode::emissionRate())
		m_model->undoStack()->push(new QXmlNodePropertyCommand(tr("Set Emission Rate"), this, "Emission_Rate", value, EmitterEmissionRateID));
}
void QTerrainNode::setMeshQuality(const float quality)
{
	if (signalsBlocked())
	{
		m_xmlNode.setAttribute("meshQuality", quality);
		h3dSetNodeParamF(m_hordeID, H3DEXTTerrain::MeshQualityF, 0, quality);
	}
	else if (quality != QTerrainNode::meshQuality())
		m_model->undoStack()->push(new QXmlNodePropertyCommand("Set Mesh Quality", this, "Mesh_Quality", QVariant::fromValue(quality), TerrainMeshQualityID));	
}
void QTerrainNode::setSkirtHeight(const float height)
{
	if (signalsBlocked())
	{
		m_xmlNode.setAttribute("skirtHeight", height);
		h3dSetNodeParamF(m_hordeID, H3DEXTTerrain::SkirtHeightF, height, 0);
	}
	else if (height!= QTerrainNode::skirtHeight())
		m_model->undoStack()->push(new QXmlNodePropertyCommand("Set Skirt Height", this, "Skirt_Height", QVariant::fromValue(height), TerrainSkirtHeightID));	
}
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);
}
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);
}
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);
}
Exemple #10
0
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;
}
Exemple #11
0
void Application::keyHandler( float timeSinceLastFrame )
{
	float curVel = _velocity * timeSinceLastFrame;

	if( _keys[GLFW_KEY_LSHIFT] )
		curVel *= 5;

	if( _keys['W'] )
	{
		// Move forward
		_x -= sinf( degToRad( _ry ) ) * cosf( -degToRad( _rx ) ) * curVel;
		_y -= sinf( -degToRad( _rx ) ) * curVel;
		_z -= cosf( degToRad( _ry ) ) * cosf( -degToRad( _rx ) ) * curVel;
	}

	if( _keys['S'] )
	{
		// Move backward
		_x += sinf( degToRad( _ry ) ) * cosf( -degToRad( _rx ) ) * curVel;
		_y += sinf( -degToRad( _rx ) ) * curVel;
		_z += cosf( degToRad( _ry ) ) * cosf( -degToRad( _rx ) ) * curVel;
	}

	if( _keys['A'] )
	{
		// Strafe left
		_x += sinf( degToRad( _ry - 90) ) * curVel;
		_z += cosf( degToRad( _ry - 90 ) ) * curVel;
	}

	if( _keys['D'] )
	{
		// Strafe right
		_x += sinf( degToRad( _ry + 90 ) ) * curVel;
		_z += cosf( degToRad( _ry + 90 ) ) * curVel;
	}

	if( _keys['3'] )
	{
		// Increase volume
		_soundVolume += 0.5f * timeSinceLastFrame;

		if( _soundVolume > 2.0f )
			_soundVolume = 2.0f;

		h3dSetNodeParamF( _sound1, H3DSoundNodeParams::Gain, 0, _soundVolume );
		h3dSetNodeParamF( _sound2, H3DSoundNodeParams::Gain, 0, _soundVolume );
	}

	if( _keys['4'] )
	{
		// Decrease volume
		_soundVolume -= 0.5f * timeSinceLastFrame;

		if( _soundVolume < 0 )
			_soundVolume = 0;

		h3dSetNodeParamF( _sound1, H3DSoundNodeParams::Gain, 0, _soundVolume );
		h3dSetNodeParamF( _sound2, H3DSoundNodeParams::Gain, 0, _soundVolume );
	}

	if( _keys['5'] )
	{
		// Increase pitch
		_soundPitch += 0.5f * timeSinceLastFrame;

		if( _soundPitch > 2.0f )
			_soundPitch = 2.0f;

		h3dSetNodeParamF( _sound1, H3DSoundNodeParams::Pitch, 0, _soundPitch );
		h3dSetNodeParamF( _sound2, H3DSoundNodeParams::Pitch, 0, _soundPitch );
	}

	if( _keys['6'] )
	{
		// Decrease pitch
		_soundPitch -= 0.5f * timeSinceLastFrame;

		if( _soundPitch < 0.5f )
			_soundPitch = 0.5f;

		h3dSetNodeParamF( _sound1, H3DSoundNodeParams::Pitch, 0, _soundPitch );
		h3dSetNodeParamF( _sound2, H3DSoundNodeParams::Pitch, 0, _soundPitch );
	}
}
Exemple #12
0
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();
}
Exemple #13
0
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;
}
	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