Loading from VRML 2.0 - X3D         A VRML loader using the X3D format

Description

This is a basic Entity creator, loads datas from VRML 2.0 / X3D using CyberX3D (basically the only correct open-source C++ VRML 2.0 (X3D) loader I found), this is a very basic loader, but demonstrates the creation of Meshes and Submeshes. Creates custom Manager for VRML files, based on the article: Resources and ResourceManagers.

VRML and X3D

This is a VRML 2.0 loader, uses a lib for X3D format. Basicly, X3D is an extension of VRML 2.0 . More info in wikis: Wikipedia - X3D and Wikipedia - VRML97

Environment

  • MSVC++ 2008 Express
  • Ogre 1.4.9


Anybody want to extend/correct the article is welcome!

(article will be extended when I have more time)

Overview

  • materials have to be created based on transparency (question: if the VRML-material doesn't contain transparency but the related texture is transparent - how should indicate this?)

Limitations

  • can handle only 'normalPerVertex FALSE'
  • triangle based models
  • no hierarchy
  • no scripting
  • no multi-texture

Usage

// register the manager (only once!)
new VrmlFileManager();

// ...

// load the VRML to memory + let CyberX3D to process it
VrmlFilePtr vrml_scene = VrmlFileManager::getSingleton().load(
		EyeWitnessInterfaceConverter::convertResourceUrlRelativeToDirectory(in_file_name, in_base_dir), 
		GlobalSettings::getSingleton().getResourceGroupAct()
	);

// and create an entity from the VRML datas
Ogre::Entity* mp_entity = vrml_scene->createEntity("the-id", GlobalSettings::getSingleton().getSceneManager(), 
		1.0f, Ogre::Vector3::ZERO, Ogre::CULL_NONE);

Header

#ifndef _VRML_FILE_H_
#define _VRML_FILE_H_

//============
// INCLUDES
#include <Base.h>
#include <cybergarage\x3d\CyberX3D.h>

#include <OgreResourceManager.h>
#include <OgreVector3.h>

//============
// USING

//============
// CLASSES

	/// *********** CLASS **************/
	/// <name> XmlFile </name>
	/// <description> - </description>
	/// <remarks> - </remarks>
	/// ********************************/
	class VrmlFile : public Ogre::Resource
	{
	protected:
		// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
		// inherited from Resource 
		// -> must implement these from the Ogre::Resource interface
		// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
		void loadImpl();
		void unloadImpl();
		size_t calculateSize() const;

	public:
		VrmlFile(Ogre::ResourceManager* creator, const Ogre::String &name, 
			Ogre::ResourceHandle handle, const Ogre::String& group, bool isManual = false, 
			Ogre::ManualResourceLoader* loader = 0);
		virtual ~VrmlFile();

		///----------- FUNCTION ------------
		/// <name> createEntity </name>
		/// <description> - </description>
		/// <parameters> 
		/// @in_base_unique_name := an unique string, the entities/meshes/materials will use this to make unique names (required by Ogre)
		///		-> entities will be named:		base-unique-name/number-of-the-shape-node-in-this-file
		///											or if the shape-node has a name: base-unique-name/name-of-the-shape-node
		///		-> meshes will be named:		base-unique-name/meshes/number-of-the-shape-node-in-this-file
		///											or if the shape-node has a name: base-unique-name/meshes/name-of-the-shape-node (HAVE TO BE UNIQUE!!!)
		///		-> materials will be named:		base-unique-name/materials/texture-file-name
		///											or if it won't hold any textures: base-unique-name/materials/number-of-the-shape-node-in-this-file (the shape-node's number!!!)
		/// Example:
		///		in_base_unique_name example = StaticMeshesFromScene (
		///		first mesh will be: StaticMeshesFromScene/meshes/1
		/// </parameters>
		/// <remarks>
		///		* additionally this will create a scene-node, which is child of the roor-scene-node and
		///			possibly holds the transformations given from the VRML (rotation, scale, translation)
		///	</remarks>
		/// <return> - </return>
		///---------------------------------
		Ogre::Entity* createEntity(const Ogre::String& in_base_unique_name, Ogre::SceneManager* in_scene_manager, 
			const Ogre::Real in_scale_factor = 1.0f, const Ogre::Vector3& in_pos_offset = Ogre::Vector3::ZERO, Ogre::CullingMode in_cull_mode = Ogre::CULL_NONE);

		///----------- FUNCTION ------------
		/// <name> getBackgroundColor </name>
		/// <description> - </description>
		/// <parameters> - </parameters>
		/// <return> - </return>
		///---------------------------------
		Ogre::ColourValue getBackgroundColor();

		///----------- FUNCTION ------------
		/// <name> getContentString </name>
		/// <description> - </description>
		/// <parameters> - </parameters>
		/// <return> - </return>
		///---------------------------------
		const Ogre::String getContentString();

		///----------- FUNCTION ------------
		/// <name> getWorldAmbientColor </name>
		/// <description> - </description>
		/// <parameters> - </parameters>
		/// <return> - </return>
		///---------------------------------
		Ogre::ColourValue getWorldAmbientColor();

		///----------- FUNCTION ------------
		/// <name> getDirectionalLights </name>
		/// <description> - </description>
		/// <parameters> - </parameters>
		/// <return> - </return>
		///---------------------------------
		CyberX3D::DirectionalLightNode* VrmlFile::getDirectionalLights();

		///----------- FUNCTION ------------
		/// <name> getPointLights </name>
		/// <description> - </description>
		/// <parameters> - </parameters>
		/// <return> - </return>
		///---------------------------------
		CyberX3D::PointLightNode* VrmlFile::getPointLights();

	private:
		size_t m_size;
		CyberX3D::SceneGraph* m_x3d_scene_graph;

	private:
		///----------- FUNCTION ------------
		/// <name> loadToMemory </name>
		/// <description> - </description>
		/// <parameters> - </parameters>
		/// <return> - </return>
		///---------------------------------
		void loadToMemory(const Ogre::String& in_xml_file_string);

		///----------- FUNCTION ------------
		/// <name> addSubMesh </name>
		/// <description> adds a SubMesh (from VRML - Shape (node) ) to the reference ManualObject </description>
		/// <parameters>
		///		@in_is_generate_normal_if_needed:  
		/// </parameters>
		/// <return> - </return>
		///---------------------------------
		void addSubMesh(Ogre::ManualObject* ref_manual_object,const Ogre::String& in_base_unique_name, CyberX3D::ShapeNode* inp_shn, 
									Ogre::SceneManager* in_scene_manager, 
									const Ogre::Real in_scale_factor, const Ogre::Vector3& in_pos_offset,
									int in_curr_mesh_num, 
									const bool in_is_flip_texture_vertically = true, const bool in_is_flip_texture_horizontally = true,
									bool in_is_flip_normals = false, bool in_is_generate_normal_if_needed = true, 
									Ogre::CullingMode in_cull_mode = Ogre::CULL_NONE, bool in_is_overlay_to_debug = false);

		///----------- FUNCTION ------------
		/// <name> makeMaterialBase </name>
		/// <description> - </description>
		/// <parameters> - </parameters>
		/// <return> - </return>
		///---------------------------------
		void makeMaterialBase(Ogre::String& ref_mat_name, const Ogre::ColourValue in_diffuse_color,
			const Ogre::ColourValue in_ambient_color, Ogre::CullingMode in_cull_mode = Ogre::CULL_NONE);

		///----------- FUNCTION ------------
		/// <name> makeMaterialTextured </name>
		/// <description> - </description>
		/// <parameters> - </parameters>
		/// <return> - </return>
		///---------------------------------
		void makeMaterialTextured(Ogre::String& ref_material_name, const Ogre::String in_tex_name, 
			const Ogre::ColourValue in_diffuse_color, const Ogre::ColourValue in_ambient_color,
			Ogre::CullingMode in_cull_mode = Ogre::CULL_NONE);
	};

	/// *********** CLASS **************/
	/// <name> XmlFilePtr </name>
	/// <description> - </description>
	/// ********************************/
	class VrmlFilePtr : public Ogre::SharedPtr<VrmlFile> 
	{
	public:
		VrmlFilePtr() : Ogre::SharedPtr<VrmlFile>() {}
		explicit VrmlFilePtr(VrmlFile *rep) : Ogre::SharedPtr<VrmlFile>(rep) {}
		VrmlFilePtr(const VrmlFilePtr &r) : Ogre::SharedPtr<VrmlFile>(r) {} 
		VrmlFilePtr(const Ogre::ResourcePtr &r) : Ogre::SharedPtr<VrmlFile>()
		{
			// lock & copy other mutex pointer
			OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
				OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
				pRep = static_cast<VrmlFile*>(r.getPointer());
			pUseCount = r.useCountPointer();
			if (pUseCount)
			{
				++(*pUseCount);
			}
		}

		/// Operator used to convert a ResourcePtr to a VrmlFilePtr
		VrmlFilePtr& operator=(const Ogre::ResourcePtr& r)
		{
			if (pRep == static_cast<VrmlFile*>(r.getPointer()))
				return *this;
			release();
			// lock & copy other mutex pointer
			OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
				OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
				pRep = static_cast<VrmlFile*>(r.getPointer());
			pUseCount = r.useCountPointer();
			if (pUseCount)
			{
				++(*pUseCount);
			}
			return *this;
		}
	};

#endif // end-of: _VRML_FILE_H_

Source

#include "stdafx.h"

#include "VrmlFile.h"
#include "VrmlFileSerializer.h"
#include <xercesc/framework/MemBufInputSource.hpp>
#include <SearchInResources.h>
#include "MaterialFileConstants.h"
#include <TextureMaterialHelper.h>
#include <EyeWitnessInterfaceConverter.h>

#include <OgreManualObject.h>
#include <OgreMaterial.h>
#include <OgreRenderOperation.h>
#include <OgreEntity.h>
#include <OgrePass.h>
#include <OgreSceneManager.h>
#include <OgreStringConverter.h>
#include <OgreTechnique.h>

using namespace Ayroth;

//---------------------------------------------------------------------------------------------
VrmlFile::VrmlFile(Ogre::ResourceManager* creator, const Ogre::String &name, 
                    Ogre::ResourceHandle handle, const Ogre::String &group, bool isManual, 
                    Ogre::ManualResourceLoader *loader) 
	:	Ogre::Resource(creator, name, handle, group, isManual, loader)
{
    /* If you were storing a pointer to an object, then you would set that pointer to NULL here.
    */

    /* For consistency with StringInterface, but we don't add any parameters here
    That's because the Resource implementation of StringInterface is to
    list all the options that need to be set before loading, of which 
    we have none as such. Full details can be set through scripts.
    */ 
    createParamDictionary("VrmlFile");
}

//---------------------------------------------------------------------------------------------
VrmlFile::~VrmlFile()
{
    unload();
}

//---------------------------------------------------------------------------------------------
void VrmlFile::loadImpl()
{
    //VrmlFileSerializer serializer;
    //Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource(mName, mGroup, true, this);    
	//loadToMemory(serializer.importFromFile(stream));

	Ogre::String full_url = Ayroth::SearchInResources::GetFullPath(mName, mGroup);
	if( full_url == "0" )
	{
		LOG_CRITICAL( "Cannot load the file: " + mName + " (possibly this is not in the specified resource group: " + mGroup + ")");
		return;
	}

	m_size = 1024;		// TODO: TMP 1MB
	m_x3d_scene_graph = new CyberX3D::SceneGraph();
	LOG_NORMAL("Vrml-file: " + Ogre::String(full_url).c_str());
	bool result = m_x3d_scene_graph->load(Ogre::String(full_url).c_str());
	if (result == false) {
		LOG_CRITICAL(
			"VRML loading failed! Datas: " +
			Ogre::String(m_x3d_scene_graph->getParserErrorMessage()) + 
			" : " + Ogre::StringConverter::toString(m_x3d_scene_graph->getParserErrorLineNumber()) + 
			" | " + Ogre::String(m_x3d_scene_graph->getParserErrorToken())
			);
	}
}

//---------------------------------------------------------------------------------------------
void VrmlFile::unloadImpl()
{
    /* If you were storing a pointer to an object, then you would check the pointer here,
    and if it is not NULL, you would destruct the object and set its pointer to NULL again.
    */
}

//---------------------------------------------------------------------------------------------
void VrmlFile::loadToMemory(const Ogre::String& in_xml_file_string)
{
	m_size = in_xml_file_string.size();

	/*
	MemBufInputSource* memBufIS = new MemBufInputSource((const XMLByte*)in_xml_file_string.c_str(), in_xml_file_string.length(), 
		mName.c_str(), false);
	m_dom_parser->parse(*memBufIS);

	m_xml_doc = m_dom_parser->getDocument();
	m_root_element = m_xml_doc->getDocumentElement();
	*/
}

//---------------------------------------------------------------------------------------------
size_t VrmlFile::calculateSize() const
{
    return m_size;
}

//---------------------------------------------------------------------------------------------
const Ogre::String VrmlFile::getContentString()
{
	return Ogre::String("Need to implement!");
}

//---------------------------------------------------------------------------------------------
Ogre::Entity* VrmlFile::createEntity(const Ogre::String& in_base_unique_name, Ogre::SceneManager* in_scene_manager,
									 const Ogre::Real in_scale_factor, const Ogre::Vector3& in_pos_offset,
									 const Ogre::CullingMode in_cull_mode)
{
	LOG_NORMAL("Start to create entity from VRML - entity ID: " + in_base_unique_name);
	Ogre::Entity* _ret = NULL;

	// 1) start a new ManualObject, to create the mesh on-the-fly
	Ogre::ManualObject* mo = new Ogre::ManualObject("man_obj");

	// 2) traverse through all ShapeNodes 
	// -> each one is a SubMesh/entity, BECAUSE we use it this way; 
	// but VRML could handle hiearchy! (we just don't use it)
	// here: 1 VRML file is 1 Mesh/Entity; Shape's are Sub-Meshes/Entities
	int i = 0;
	CyberX3D::ShapeNode* shn = NULL;
	for( shn = m_x3d_scene_graph->getShapeNodes(), i = 0; shn; shn = shn->next(), i++)
	{
		this->addSubMesh(mo, in_base_unique_name, shn, in_scene_manager, in_scale_factor, in_pos_offset, i, true, true, false, true, in_cull_mode, false);
	}

	if( mo->getNumSections() == 0 )
	{
		LOG_WARNING("The VRML doesn't have any geometry");
		return NULL;
	}

	// set the ManualObject/Entity datas
	mo->setDynamic(false);
	mo->setCastShadows(false);

	Ogre::String mesh_name = in_base_unique_name + "Mesh";
	// convert it to Mesh
	Ogre::MeshPtr pmesh = mo->convertToMesh(mesh_name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
	pmesh->buildEdgeList(); // build edge-list to shadow-volumes
	// and delete the ManualObject
	delete mo;

	_ret = in_scene_manager->createEntity(
		in_base_unique_name,		// entity's name
		mesh_name
	);
	/*if( inp_shn->hasName() )
	{
		_ret_entity = in_scene_manager->createEntity(
			in_base_unique_name + Ogre::String(inp_shn->getName()),		// entity's name
			mesh_name
			);
	} else {
		_ret_entity = in_scene_manager->createEntity(
			in_base_unique_name + "/meshes/" + Ogre::StringConverter::toString(in_curr_mesh_num),		// entity's name
			mesh_name
			);
	}*/

	_ret->setCastShadows(true);
	Ogre::SceneNode* thisSceneNode = in_scene_manager->getRootSceneNode()->createChildSceneNode();
	//if( in_is_overlay_to_debug )
	//	thisSceneNode->setPosition(0.0f, 0.0f, 20.0f * in_curr_mesh_num);
	thisSceneNode->attachObject(_ret);

	return _ret;
}

//---------------------------------------------------------------------------------------------
void VrmlFile::addSubMesh(Ogre::ManualObject* ref_manual_object, const Ogre::String& in_base_unique_name, CyberX3D::ShapeNode* inp_shn, 
									Ogre::SceneManager* in_scene_manager, 
									const Ogre::Real in_scale_factor, const Ogre::Vector3& in_pos_offset,
									int in_curr_mesh_num, 
									const bool in_is_flip_texture_vertically, const bool in_is_flip_texture_horizontally,
									bool in_is_flip_normals, bool in_is_generate_normal_if_needed, 
									const Ogre::CullingMode in_cull_mode, bool in_is_overlay_to_debug)
{
	bool is_texture_available = true;
	bool is_normal_available = true;
	bool is_transparent = false;

	// :::::::::::::::::::
	// ::Appearance
	Ogre::String texture_name = "";
	Ogre::String material_name = "";
	Ogre::ColourValue diffuse_color = Ogre::ColourValue::White;
	Ogre::ColourValue ambient_color = Ogre::ColourValue::White;
	CyberX3D::AppearanceNode* pappearance_node = inp_shn->getAppearanceNodes();
	if( pappearance_node != NULL )
	{
		float transparency = pappearance_node->getMaterialNodes()->getTransparency();
		if( transparency > 0.0f )
			is_transparent = true;
		float* col = new float[3];
		pappearance_node->getMaterialNodes()->getDiffuseColor(col);
		diffuse_color = Ogre::ColourValue::ColourValue(col[0], col[1], col[2], 1.0f - transparency);
		float amb_int = 1.0f;
		amb_int = pappearance_node->getMaterialNodes()->getAmbientIntensity();
		ambient_color = Ogre::ColourValue::ColourValue(amb_int, amb_int, amb_int, 1.0f);

		CyberX3D::ImageTextureNode* pimage_tex_node = pappearance_node[0].getImageTextureNodes();
		// pimage_tex_node[0].getRepeatS
		// pimage_tex_node[0].getRepeatT
		pimage_tex_node[0].get
		if( pimage_tex_node != NULL )
		{
			texture_name = Ogre::String(pimage_tex_node[0].getUrl(0));
			texture_name = EyeWitnessInterfaceConverter::convertResourceUrlRelativeToFile(texture_name, mName, mGroup);
			//this->getName()
			material_name = in_base_unique_name + "/materials/" + texture_name;
			makeMaterialTextured(material_name, texture_name, diffuse_color, ambient_color, in_cull_mode);
		} else {
			is_texture_available = false;			// disable texture
			material_name = in_base_unique_name + "/materials/" + Ogre::StringConverter::toString(in_curr_mesh_num);
			material_name += Ogre::StringConverter::toString(diffuse_color);
			makeMaterialBase(material_name, diffuse_color, ambient_color, in_cull_mode);
		}
	} else {
		is_texture_available = false;			// disable texture
		material_name = "material/no-material";
		makeMaterialBase(material_name, diffuse_color, ambient_color);
	}

	// :::::::::::::::::::
	// ::Geometry
	//g_CurrAvailableVertexID = 0;
	//g_IndexBufferOffset = 0;

	// :::::::::::::::::::
	// :: 1.) Get datas ::
	Ogre::String mesh_name;
	if( inp_shn->hasName() )
		mesh_name = in_base_unique_name + "/meshes/" + Ogre::String(inp_shn->getName());
	else
		mesh_name = in_base_unique_name + "/meshes/" + Ogre::StringConverter::toString(in_curr_mesh_num);

	//CyberX3D::AppearanceNode* appearance = inp_shn->getAppearanceNodes();
	//CyberX3D::Geometry3DNode* pgeomn = inp_shn->getGeometry3DNode();

	CyberX3D::IndexedFaceSetNode* ifsn = inp_shn->getIndexedFaceSetNodes();
	if( ifsn==NULL )
	{
		LOG_CRITICAL("Cannot get face-set-nodes, probably this type is not supported.");
		return;
	}

	// coord-index
	CyberX3D::MFInt32* pcoord_idx = ifsn->getCoordIndexField();
	// points / coords
	CyberX3D::CoordinateNode* cn = ifsn->getCoordinateNodes();
	if( cn==NULL || pcoord_idx==NULL )
	{
		LOG_CRITICAL("Cannot get coordinates");
		return;
	}
	CyberX3D::MFVec3f* coordinate_points_field = cn[0].getPointField();
	// tex-coords
	CyberX3D::MFInt32* ptex_idx = ifsn->getTexCoordIndexField();
	CyberX3D::TextureCoordinateNode* tn = ifsn->getTextureCoordinateNodes();
	CyberX3D::MFVec2f* texture_coordinates_field = NULL;
	if( ptex_idx!=NULL && tn!=NULL )
	{
		texture_coordinates_field = tn[0].getPointField();
		if( ptex_idx->getSize() != pcoord_idx->getSize() )
		{
			// the only supported type is that:
			// each texCoordIndex attached to a coordIndex
			// -> per-face-vertex texCoordIndex
			// -> every face-vertex has to have a texCoordIndex!
			LOG_CRITICAL("tex-index's num is NOT equal to coord-index's num!");
			return;
		}
	} else {
		LOG_NORMAL("Can't find texture-coordinate datas in: " + mesh_name);	

		is_texture_available = false;			// disable texture
	}
	// normals
	//ifsn->setSolid(true);
	//ifsn->setCCW(true);
	//ifsn->setNormalPerVertex(false);	// -> set to per face
	CyberX3D::NormalNode* nn = ifsn->getNormalNodes();
	if( nn==NULL && in_is_generate_normal_if_needed )
	{
		// cannot find normal-datas
		// so try to generate them
		if( !ifsn->generateNormals() )
		{
			LOG_NORMAL("Cannot generate normals!");
		} else {
			nn = ifsn->getNormalNodes();
		}
	}

	CyberX3D::MFVec3f* normal_field = NULL;
	if( nn!=NULL )
	{
		normal_field = nn[0].getVectorField();
	} else {
			is_normal_available = false;
	}

	// :::::::::::::::::::::::::::::::
	// :: 2.) create the sub-mesh datas ::	
	ref_manual_object->begin(material_name, Ogre::RenderOperation::OT_TRIANGLE_LIST);
		int face_idx = 0;
		int vert_idx = 0;
		for( int i = 0; i < pcoord_idx->getSize(); i++ )
		{
			if( (i+1)%4 != 0 )
			{
				// add position
				Ogre::uint16 coord_idx = pcoord_idx->get1Value(i);
				float* pos = new float[3];
				coordinate_points_field->get1Value(coord_idx, pos);
				ref_manual_object->position(Ogre::Vector3(pos) * in_scale_factor);

				if( is_texture_available )
				{
					// add texture
					Ogre::uint16 tex_idx = ptex_idx->get1Value(i);
					float* tex = new float[2];
					texture_coordinates_field->get1Value(tex_idx, tex);
					Ogre::Vector2 tex_uv = Ogre::Vector2(tex);

					// make the flips (if needed)
					if( in_is_flip_texture_vertically )
					{
						tex_uv.y = 1.0f - tex_uv.y;
					}

					if( in_is_flip_texture_horizontally )
					{
						tex_uv.x = 1.0f - tex_uv.x;
					}

					ref_manual_object->textureCoord(tex_uv);
				} 

				if( is_normal_available )
				{
					// add normal
					Ogre::uint16 normal_idx = face_idx;
					float* norm = new float[3];
					normal_field->get1Value(normal_idx, norm);
					Ogre::Vector3 norm_vec = Ogre::Vector3(norm);
					if( in_is_flip_normals )
						norm_vec *= -1;
					ref_manual_object->normal(norm_vec);
				}

				ref_manual_object->index(vert_idx);
				vert_idx++;
			} else {
				face_idx++;
			}
		}
	ref_manual_object->end();

	//LOG_NORMAL(" VRML-MESH sub-mesh use the material: " + material_name);
	//LOG_NORMAL(" VRML-MESH face cnt: " + Ogre::StringConverter::toString(face_idx));
	//LOG_NORMAL(" VRML-MESH vert cnt: " + Ogre::StringConverter::toString(vert_idx));
}

//---------------------------------------------------------------------------------------------
void VrmlFile::makeMaterialBase(Ogre::String& ref_material_name, const Ogre::ColourValue in_diffuse_color, 
								const Ogre::ColourValue in_ambient_color, const Ogre::CullingMode in_cull_mode)
{
	Ogre::String base_mat = MaterialFileConstants::getMaterialNameNoTextureSimple();
	if( in_diffuse_color.a != 1.0f )
	{
		base_mat = MaterialFileConstants::getMaterialNameNoTextureAlphaBlend();
	}

	Ogre::MaterialPtr material;
	if( TextureMaterialHelper::cloneMaterialSafely(base_mat, material,
			ref_material_name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME) )
	{
		// OK
		Ogre::Material::TechniqueIterator tech_it =  material->getTechniqueIterator();
		// change all technique's first pass's texture
		//LOG_TRACE();
		while( tech_it.hasMoreElements() )
		{
			Ogre::Technique* ct = tech_it.getNext();
			Ogre::String desired_pass = MaterialFileConstants::getMaterialPassName_GenericMainPass();
			Ogre::Pass* pass = ct->getPass(desired_pass);
			if( pass == NULL )
			{
				LOG_CRITICAL("Pass (" + desired_pass + ") not found in technique: " + ct->getName());
			} else {
				pass->setAmbient(in_ambient_color);
				//LOG_NORMAL("Ambient: " + Ogre::StringConverter::toString(in_ambient_color));
				pass->setDiffuse(in_diffuse_color);
				//LOG_NORMAL("Diffuse: " + Ogre::StringConverter::toString(in_diffuse_color));
				//pass->setCullingMode(in_cull_mode);
			} 
		}
	}

	/*if( Ogre::MaterialManager::getSingleton().getByName(in_material_name).isNull() )
	{
		Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create(
			in_material_name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
		if( material.isNull() )
		{
			LOG_NORMAL("Error: material cannot be created! Maybe name duplication/material is already exists? " + in_material_name);	
		} else {
			if( in_diffuse_color.a < 1.0f )
			{
				material->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
				material->getTechnique(0)->getPass(0)->setSceneBlending(Ogre::SceneBlendType::SBT_TRANSPARENT_ALPHA);
			}
			else
			{
				material->getTechnique(0)->getPass(0)->setDepthWriteEnabled(true);
			}
			material->getTechnique(0)->getPass(0)->setDepthCheckEnabled(true);

			material->getTechnique(0)->getPass(0)->setDiffuse(in_diffuse_color);
			material->getTechnique(0)->getPass(0)->setAmbient(in_ambient_color);
			material->getTechnique(0)->getPass(0)->setCullingMode(in_cull_mode);
		}
	}*/
}

/*void VrmlFile::setToAllTechnique(Ogre::MaterialPtr in_material, Ogre::uint16 in_pass_idx, Ogre::ColourValue in_color)
{
	// try to get the material
	if( !in_material.isNull() )
	{
		// material is existing

		Ogre::Material::TechniqueIterator tech_it =  in_material->getTechniqueIterator();
		// change all technique's first pass's texture
		while( tech_it.hasMoreElements() )
		{
			Ogre::Pass* pass = tech_it.getNext()->getPass(in_pass_idx);
			pass->
		}
	} else {
		LOG_NORMAL("Error: material does not exist " + in_material->getName());
		return false;
	}
}*/

//---------------------------------------------------------------------------------------------
void VrmlFile::makeMaterialTextured(Ogre::String& ref_material_name, const Ogre::String in_tex_name, 
									const Ogre::ColourValue in_diffuse_color, const Ogre::ColourValue in_ambient_color, 
									const Ogre::CullingMode in_cull_mode)
{
	Ogre::String material_name = MaterialFileConstants::getMaterialNameTextureAmbientDiffuse();

	Ogre::MaterialPtr material;
	if( TextureMaterialHelper::cloneMaterialSafely(material_name, material,
			ref_material_name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME) )
	{
		if( TextureMaterialHelper::setTextureToAllTextureUnitThisName(material, 
				in_tex_name, MaterialFileConstants::getTextureUnitNameDiffuseTexture(), 0) )
		{
			// OK
			Ogre::Material::TechniqueIterator tech_it =  material->getTechniqueIterator();
			// change all technique's first pass's texture
			while( tech_it.hasMoreElements() )
			{
				Ogre::Technique* ct = tech_it.getNext();
				Ogre::String desired_pass = MaterialFileConstants::getMaterialPassName_GenericMainPass();
				Ogre::Pass* pass = ct->getPass(desired_pass);
				if( pass == NULL )
				{
					LOG_CRITICAL("Pass (" + desired_pass + ") not found in technique: " + ct->getName());
				} else {
					pass->setAmbient(in_ambient_color);
					pass->setDiffuse(in_diffuse_color);
					pass->setCullingMode(in_cull_mode);
				}
			}
		}
	}

	/*if( Ogre::MaterialManager::getSingleton().getByName(in_material_name).isNull() )
	{
		if( Ogre::TextureManager::getSingleton().getByName(in_tex_name).isNull() )
		{
			if( Ogre::TextureManager::getSingleton().load(in_tex_name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME).isNull() )
			{
				LOG_NORMAL("Error: texture cannot be loaded! " + in_tex_name);
			}
		}

		// 1) create an empty material
		Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create(
			in_material_name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
		if( material.isNull() )
		{
			LOG_NORMAL("Error: material cannot be created! Maybe name duplication problem or the material is already exists? " + in_material_name);	
		} else {
			// 2) if succeeded -> get the basic material (from a .material file! -> support both shader and ffp)
			//		[%%%] mostly the material has some remarks, see it in the material file!!!
			Ogre::MaterialPtr base_mat = Ogre::MaterialManager::getSingleton().load( MaterialFileConstants::getMaterialNameTextureAmbientDiffuse(), 
				Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);

			// 3) then copy the base material to our (empty) material
			base_mat->copyDetailsTo(material);
			// 4) and change the parameters, we need
			Ogre::Material::TechniqueIterator tech_it =  material->getTechniqueIterator();
			// change all technique's first pass's texture
			while( tech_it.hasMoreElements() )
			{
				//Ogre::Technique::PassIterator pass_it = tech_it.getNext()->getPassIterator();
				Ogre::Pass* pass = tech_it.getNext()->getPass(0);
				pass->getTextureUnitState( MaterialFileConstants::getTextureUnitNameDiffuseTexture() )->setTextureName(in_tex_name);
				pass->setDiffuse(in_diffuse_color);

				while( pass_it.hasMoreElements() )
				{
					std::vector<Ogre::Pass*>::value_type pass_v = pass_it.getNext();
					pass_v->getTextureUnitState("color_texture")->setTextureName(in_tex_name);
					pass_v->setDiffuse(in_diffuse_color);
				}
			}

			if( in_diffuse_color.a < 1.0f )
			{
				material->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
			}
			else
			{
				material->getTechnique(0)->getPass(0)->setDepthWriteEnabled(true);
			}

			// [iii]
			// info on multiple semi-transparency: 
			// http://www.ogre3d.org/phpBB2/viewtopic.php?t=12694&view=next&sid=ce193664e1d3d7c4af509e6f4e2718c6

			material->getTechnique(0)->getPass(0)->setAlphaRejectSettings(Ogre::CMPF_GREATER, 128);
			material->getTechnique(0)->getPass(0)->setDepthWriteEnabled(true);
			material->getTechnique(0)->getPass(0)->setSceneBlending(Ogre::SceneBlendType::SBT_TRANSPARENT_ALPHA);
			material->getTechnique(0)->getPass(0)->setDiffuse(in_diffuse_color);
			material->getTechnique(0)->getPass(0)->setCullingMode(in_cull_mode);
		}
	} else {
		// don't do anything, the material is already exist!
	}*/
}

//---------------------------------------------------------------------------------------------
Ogre::ColourValue VrmlFile::getBackgroundColor()
{
	float* vec3 = new float[3];
	vec3[0] = 1; vec3[1] = 1; vec3[2] = 1;
	if( m_x3d_scene_graph->getBackgroundNode() != NULL )
	{
		m_x3d_scene_graph->getBackgroundNode()->getSkyColor(0, vec3);
	}

	//mViewport->setBackgroundColour(
	//	Ogre::ColourValue::ColourValue(vec3[0], vec3[1], vec3[2], 1));

	return Ogre::ColourValue::ColourValue(vec3[0], vec3[1], vec3[2], 1);
}

//---------------------------------------------------------------------------------------------
CyberX3D::DirectionalLightNode* VrmlFile::getDirectionalLights()
{
	return m_x3d_scene_graph->getDirectionalLightNodes();
}

//---------------------------------------------------------------------------------------------
CyberX3D::PointLightNode* VrmlFile::getPointLights()
{
	return m_x3d_scene_graph->getPointLightNodes();
}

//---------------------------------------------------------------------------------------------
Ogre::ColourValue VrmlFile::getWorldAmbientColor()
{
	float* vec3 = new float[3];
	CyberX3D::DirectionalLightNode* dir_ln = m_x3d_scene_graph->getDirectionalLightNodes();
	dir_ln->getAmbientColor(vec3);
	//dir_ln->getAmbientIntensity();

	//mViewport->setBackgroundColour(
	//	Ogre::ColourValue::ColourValue(vec3[0], vec3[1], vec3[2], 1));

	return Ogre::ColourValue::ColourValue(vec3[0], vec3[1], vec3[2], 1) * dir_ln->getAmbientIntensity();
	//return Ogre::ColourValue::White;
}

Manager

Header

//================================
// VrmlFileManager.h
//--------------------------------
// copyright: -
// based on: http://www.ogre3d.org/wiki/index.php/Advanced_Tutorial_1
// description: -
//================================

#ifndef _VRML_FILE_MANAGER_H_
#define _VRML_FILE_MANAGER_H_

//============
// INCLUDES
#include <OgreResourceManager.h>
#include "VrmlFile.h"


//============
// CLASSES

	class VrmlFileManager : public Ogre::ResourceManager, public Ogre::Singleton<VrmlFileManager>
	{
	protected:

		// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
		// must implement this from ResourceManager's interface
		// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
		Ogre::Resource *createImpl(const Ogre::String &name, Ogre::ResourceHandle handle, 
			const Ogre::String &group, bool isManual, Ogre::ManualResourceLoader *loader, 
			const Ogre::NameValuePairList *createParams);

	public:
		VrmlFileManager();
		virtual ~VrmlFileManager();
		static VrmlFileManager &getSingleton();
		static VrmlFileManager *getSingletonPtr();

	public:
		virtual VrmlFilePtr load(const Ogre::String &name, const Ogre::String &group);

		///----------- FUNCTION ------------
		/// <name> getTypeName </name>
		/// <description> 
		///		-
		///	</description>
		/// <parameters> - </parameters>
		/// <return> - </return>
		///---------------------------------
		std::string getTypeName();
	};

#endif // end-of: _VRML_FILE_MANAGER_H_


Source

#include "stdafx.h"

#include "VrmlFileManager.h"

#include <OgreStringConverter.h>


//---------------------------------------------------------------------------------------------
template<> VrmlFileManager* Ogre::Singleton<VrmlFileManager>::ms_Singleton = 0;

//---------------------------------------------------------------------------------------------
VrmlFileManager* VrmlFileManager::getSingletonPtr()
{
    return ms_Singleton;
}

//---------------------------------------------------------------------------------------------
VrmlFileManager& VrmlFileManager::getSingleton()
{  
    assert(ms_Singleton);  
    return(*ms_Singleton);
}

//---------------------------------------------------------------------------------------------
VrmlFileManager::VrmlFileManager()
{
    mResourceType = "VrmlFile";

    // low, because it will likely reference other resources
    mLoadOrder = 30.0f;

    // this is how we register the ResourceManager with OGRE
    Ogre::ResourceGroupManager::getSingleton()._registerResourceManager(mResourceType, this);
}

//---------------------------------------------------------------------------------------------
VrmlFileManager::~VrmlFileManager()
{
    // and this is how we unregister it
    Ogre::ResourceGroupManager::getSingleton()._unregisterResourceManager(mResourceType);
}

//---------------------------------------------------------------------------------------------
VrmlFilePtr VrmlFileManager::load(const Ogre::String& name, const Ogre::String &group)
{
	LOG_NORMAL("Start to load VRML: " + name);
    VrmlFilePtr file = getByName(name);

    if (file.isNull())
        file = create(name, group);

    file->load();
    return file;
}

//---------------------------------------------------------------------------------------------
Ogre::Resource* VrmlFileManager::createImpl(const Ogre::String& name, Ogre::ResourceHandle handle, 
                                            const Ogre::String& group, bool isManual, Ogre::ManualResourceLoader* loader, 
                                            const Ogre::NameValuePairList* createParams)
{
    return new VrmlFile(this, name, handle, group, isManual, loader);
}

//---------------------------------------------------------------------------------------------
std::string VrmlFileManager::getTypeName()
{
	return "VrmlFileManager";
}

Serializer

Header

//================================
// VrmlFileSerializer.h
//--------------------------------
// copyright: -
// based on: http://www.ogre3d.org/wiki/index.php/Advanced_Tutorial_1
// description: -
//================================

#ifndef _VRML_FILE_SERIALIZER_H_
#define _VRML_FILE_SERIALIZER_H_

//============
// INCLUDES
#include <OgreSerializer.h>

//============
// CLASSES

	class VrmlFile; // forward declaration

	class VrmlFileSerializer : public Ogre::Serializer
	{
	public:
		VrmlFileSerializer();
		virtual ~VrmlFileSerializer();

		void exportToFile(VrmlFile* in_vrml_file, const Ogre::String& file_name);
		Ogre::String importFromFile(Ogre::DataStreamPtr& in_stream);
	};


#endif // end-of: _VRML_FILE_SERIALIZER_H_


Source

#include "stdafx.h"

#include "VrmlFileSerializer.h"
#include "VrmlFile.h"

//---------------------------------------------------------------------------------------------
VrmlFileSerializer::VrmlFileSerializer()
{
}

//---------------------------------------------------------------------------------------------
VrmlFileSerializer::~VrmlFileSerializer()
{
}

//---------------------------------------------------------------------------------------------
void VrmlFileSerializer::exportToFile(VrmlFile* in_vrml_file, const Ogre::String& in_file_name)
{
    std::ofstream outFile;
    outFile.open(in_file_name.c_str(), std::ios::out);
    outFile << in_vrml_file->getContentString();
    outFile.close();
}

//---------------------------------------------------------------------------------------------
Ogre::String VrmlFileSerializer::importFromFile(Ogre::DataStreamPtr& in_stream)
{
    return in_stream->getAsString();
}


Alias: Loading from VRML 2.0 / X3D