[Solved] Dynamically loading a material script at runtime


06-05-2007 21:49:55

I posted this over on the OGRE forums to see if I was making a general OGRE mistake, or if I was having a MOGRE problem. It seems I may be having a MOGRE problem, or at any rate I think I am having a MOGRE specific issue. My first thought is that I am not using the DataStream correctly.

Here is the code:

private void SetupResourceGroup () {
m_Group = String.Format ("MaterialGroup{0}", m_GroupCount++);
ResourceGroupManager.Singleton.CreateResourceGroup (m_Group);
ResourceGroupManager.Singleton.InitialiseResourceGroup (m_Group);

public void Load (string path) {
try {
if (m_Group == String.Empty) {
SetupResourceGroup ();

m_Path = path;
using (StreamReader sr = new StreamReader (path)) {
m_MaterialScript = sr.ReadToEnd();

ResourceGroupManager.Singleton.ClearResourceGroup (m_Group);
m_MaterialNames.Clear ();

// Regex is /material\s+([\w|\/|\\|_]+)/
MatchCollection matches = m_MaterialRegex.Matches (m_MaterialScript);
foreach(Match m in matches) {
if(m.Groups.Count > 1) {
string name = m.Groups[1].Value;
m_MaterialNames.Add (name);

MemoryStream memStream = new MemoryStream (Encoding.ASCII.GetBytes (m_MaterialScript));
DataStreamPtr stream = new DataStreamPtr (new ManagedDataStream (memStream));
MaterialManager.Singleton.ParseScript (stream, m_Group);

foreach(string name in m_MaterialNames) {
ResourcePtr res = MaterialManager.Singleton.GetByName (name); // PROBLEM: This always returns a null reference, like the materials didn't load
if(res == null || res.Group != m_Group || !(res.Target is Material)) {

((Material)res.Target).Compile (true);
res.Load ();
m_Materials.Add (res.Name, (Material)res.Target);
catch {
throw; // TODO: Properly handle exceptions

For some reason, I think something is going wrong at the stream level. I don't think ParseScript is getting the data I want it to, so it's not creating any material instances. Thus my call to MaterialManager.GetByName() can't find any materials, because none have been loaded.

Do anyone see anything else wrong with the code?


10-05-2007 03:23:12

No one has any ideas? I guess I am going to have to get debug versions of everything and do some debugging, wee :)


16-05-2007 14:46:59

Figured it out. There was a bug in ManagedDataStream. It was doing:

bool ManagedDataStream::eof() const {
return _managed->_stream->Position < _managed->_stream->Length;

That's obviously wrong. You want to check that Position >= Length - 1. I fixed this in my 1.4.1 recompile source and it will be fixed when I release an SDK.


19-05-2007 13:19:23

Ouch! That's an embarrassing bug, thanks for catching it!