New project (yet another material editor)

vintersorg

30-03-2006 07:57:24

Hello.

I've been using Ogre with c++ for a while now, and have a couple of projects going, have been interested in odn for a while though, but been too lazy.-

Well, actually compiled the ogredotnet dll's for the first time yesterday, worked nicely... Good job. Thought it would be much more difficult to get it working, but a few clicks and it was all ok.

So, finally i could work on my material/shader editor for ogre.

The editor can read/write material files to/from a treeview or flowchart, and be previewed on a mesh. You can add/change attributes, texture units, vertex programs etc by rightclicking and choosing the item you want to add.

I will also be working on a point&click shader-tool for the editor, can't give much info on this yet though.. Needs more planning.

Will post some screens when i have some more progress.

rastaman

30-03-2006 14:49:34

wow that sounds cool. Can't wait to see it. :)

EagleEye

30-03-2006 20:06:34

Graphical tools to help with managing and manipulating meshes and other XML-based stuff are always a good thing. :)

vintersorg

31-03-2006 07:18:51

Well. Progress is going forward.

Although i had some problems manually loading a material file via ogre's materialmanager class. Currently i'm parsing the material in my own function, but it would be much better to use ogre's internal function.

Anyone has gotten the manualresourceloader to work with the materialmanager?

rastaman

31-03-2006 15:46:40

I've never had to parse a material script with Ogre. What interfaces are used. Is it something that has not been SWIGed yet?

ManualResourceLoader will need a custom director class. I'll update cvs when I get home from work.

rastaman

31-03-2006 16:15:25

I think I see part of the problem. How do you create a MemoryDataStream with your material script? You have to give MemoryDataStream an IntPtr to a block of memory. I don't know of anyway in .Net to create an unmanaged block of memory to give to ogre. So the only solution I can think of ATM is to extend the class with functions to create and set it.

vintersorg

03-04-2006 07:35:28

hey.

Thanx for looking at my problem. :)

Well, i've done some experiments during weekend, and i think i will make a dll with functions to parse a file into a material-class and/or xml.

To avoid that the parser get's outdated if the materials change, i was thinking about defining the material structure in an xml-file, which the dll will be depentent of, so if something get changed, I just need to update the xml, and it will be good to go.. Not sure about this yet though.

At the moment i can read a loaded material from a class into a treeview and change some of the settings, I'm trying to logically group some of the settings in the material (ambient, diffuse, specular, emissive, and dynamic lighting in one group, etc) to make it easier to use and make the tree smaller/less complex. I'm also adding text from the docs as tooltips, so when you point at "ambient Light" you get the description for it.

Lee04

03-04-2006 09:00:56

Material editor...I thought first you where making a vertex/pixel shader graphical programming editor. But your editor doesn't do that? Any plans in that direction?

vintersorg

03-04-2006 09:36:09

Well, First step is editing materials & connect them to shaders in an easy way.

The next step (as soon as the other stuff works), is to make a good integrated editor for shaders (at the moment you can only edit them in a textbox), i'm working on a flowchart-style interface for building the shaders.

Lee04

03-04-2006 09:53:53

Great, I learned RTZens material editor really nice. But it's on the market any more. I do have a license still up and working though.

Vintersorg are you Swedish by any chance?
Where in Sweden are you located?
I am in Stockholm.

vintersorg

03-04-2006 10:12:57

Cool. :)

Yeah i'm Swedish. (Lindesberg, 40 km north of Örebro)

Lee04

03-04-2006 11:48:35

My old freind Leif used to live in Lindesberg, so I been there a couple of times :) What are you doing there???? What are you doing?

vintersorg

03-04-2006 11:52:02

Cool.

I work as a programmer+webdesigner. Have 2 kids & not much time for anything else. Spare time goes to game programming. :)

Lee04

03-04-2006 13:24:18

If you ever in Stockholm/Södertälje area you can pop buy I have my studio in Gnesta..just message me.

vintersorg

03-04-2006 13:34:27

Cool. I have a good friend in Södertälje which i haven't visited for a while. :)

rastaman

03-04-2006 17:16:44

I haven't for got about this. Developer cvs was down all weekend, or I just couldn't get in. Now that I'm back at work its probably up again :?
Here is a quick and dirty for the changes to have a ManualResourceLoader, and the ParseScript thing.
To use ManualResourceLoader create a new instance of ManualResourceLoaderDirector and pass that instance to any function that wants it. That class has the events you would want to respond to.


new file ogredotnet/OgreNet/ResourceExt.h
//ResourceExt.h
#ifndef __ResourceExt_H_
#define __ResourceExt_H_

namespace Ogre
{
typedef const void (SWIGSTDCALL *MRLD_FP_loadResource) ( Resource* );

class ManualResourceLoaderDirector : public Ogre::ManualResourceLoader
{
public:
MRLD_FP_loadResource mFP_loadResource;

ManualResourceLoaderDirector()
{
mFP_loadResource = 0;
}
virtual ~ManualResourceLoaderDirector() {}

/** Called when a resource wishes to load.
@param resource The resource which wishes to load
*/
virtual void loadResource(Resource* resource)
{
if (mFP_loadResource)
mFP_loadResource(resource);
}
};
}

extern "C" SWIGEXPORT void set_MRLD_FP_loadResource( void * nld, void * _fn )
{
((Ogre::ManualResourceLoaderDirector*)nld)->mFP_loadResource = (MRLD_FP_loadResource)_fn;
}

#endif //__ResourceExt_H_



change ogredotnet/OgreNet/OgreResource.i
%{
#include "OgreResource.h"
#include "ResourceExt.h"
%}

%rename Ogre::Resource::load Load;
%rename Ogre::Resource::reload Reload;
%rename Ogre::Resource::isManuallyLoaded IsManuallyLoaded;
%rename Ogre::Resource::unload Unload;
%rename Ogre::Resource::getSize GetSize;
%rename Ogre::Resource::touch Touch;
%rename Ogre::Resource::getName GetName;
%rename Ogre::Resource::getHandle GetHandle;
%rename Ogre::Resource::isLoaded IsLoaded;
%rename Ogre::Resource::getGroup GetGroup;
%rename Ogre::Resource::getCreator GetCreator;
%rename Ogre::Resource::getOrigin GetOrigin;

//typedef SharedPtr<Resource> ResourcePtr;
%template(ResourcePtr) Ogre::SharedPtr<Ogre::Resource>;



%typemap(cscode) Ogre::ManualResourceLoaderDirector %{
public delegate void MRLD_Delegate_loadResource ( Resource resource );
protected delegate void _MRLD_Delegate_loadResource ( IntPtr resource );

public void SubscribeEvents()
{
m_Delegate_loadResource = new _MRLD_Delegate_loadResource ( Handle_LoadResource );
set_MRLD_FP_loadResource (swigCPtr, m_Delegate_loadResource);
}

public event MRLD_Delegate_loadResource evtLoadResource = null;
protected _MRLD_Delegate_loadResource m_Delegate_loadResource = null;


[DllImport("OgreBindings", EntryPoint="set_MRLD_FP_loadResource")]
protected static extern void set_MRLD_FP_loadResource( HandleRef manualresourceloaderdirector, _MRLD_Delegate_loadResource fn );


protected void Handle_LoadResource ( IntPtr resource )
{
if( evtLoadResource != null )
evtLoadResource( new Resource( resource, false ) );
}

%}



%include "OgreResource.h"

namespace Ogre
{
class ManualResourceLoaderDirector : public Ogre::ManualResourceLoader
{
public:
ManualResourceLoaderDirector();
virtual ~ManualResourceLoaderDirector();
virtual void loadResource(Resource* resource);
};
}



change ogredotnet/OgreNet/OgreDataStream.i
// from Sinjaph in forums post
%{
#include "OgreDataStream.h"
%}

//rastaman C# has file streams.
%ignore Ogre::FileHandleDataStream;
%ignore Ogre::FileStreamDataStream;


// typedef SharedPtr<DataStream> DataStreamPtr;
%template(DataStreamPtr) Ogre::SharedPtr<Ogre::DataStream>;

// typedef std::list<DataStreamPtr> DataStreamList;
SWIG_STD_LIST_SPECIALIZE_MINIMUM(DataStreamPtr , Ogre::SharedPtr<Ogre::DataStream>)
%template(DataStreamList) std::list<Ogre::SharedPtr<Ogre::DataStream> >;


// typedef SharedPtr<DataStreamList> DataStreamListPtr;
//DLLNonePtrType(DataStreamList, std::list<Ogre::SharedPtr<Ogre::DataStream> >)
//%template(DataStreamListPtr) Ogre::SharedPtr<std::list<Ogre::SharedPtr<Ogre::DataStream> > >;


//causes error in OgreDotNet "no suitable method found to override"
//ignore for the functions does not work, ATM no other class exposes it
// typedef SharedPtr<MemoryDataStream> MemoryDataStreamPtr;
// %template(MemoryDataStreamPtr) Ogre::SharedPtr<Ogre::MemoryDataStream>;
%ignore Ogre::MemoryDataStreamPtr;


%typemap(ctype) void *newmembuff "void *"
%typemap(imtype) void *newmembuff "byte[]"
%typemap(cstype) void *newmembuff "byte[]"
%typemap(in) void *newmembuff %{ $1 = ($1_ltype)$input; %}
%typemap(csin) void *newmembuff "$csinput"


%include "OgreDataStream.h"

%extend Ogre::MemoryDataStream {
void SetBuffer(const Ogre::String& data)
{
Ogre::uchar *mybuff = self->getPtr();
size_t mysize = self->size();
size_t newdatasize = data.length();
size_t sizeTocopy = ((newdatasize > mysize)? mysize : newdatasize);

strcpy((char*)mybuff, data.substr(0, sizeTocopy).c_str() );
}
//.Net should se newmembuff as a byte[]
void SetBuffer(void *newmembuff, Ogre::uint pos, Ogre::uint count)
{
Ogre::uchar *mybuff = self->getPtr();
size_t mysize = self->size();
size_t sizeTocopy = ((count > mysize)? mysize : count);

memcpy(mybuff, newmembuff, sizeTocopy);
}
};




I had a problem on exit in my test it seems ogre distroys the MemoryDataStream so we need a function to distconnect the swig proxy class.
Nere the end of ogredotnet/OgreNet/CLSCompliancy.i it says "// The following typemaps"
Inside the first 2 "%typemap" after the function "static public HandleRef getCPtr"
Add this function befor the "%}"
Don't add it to the last %typemap

static public void RemoveOwnership($csclassname obj) {
if (obj!=null)
obj.swigCMemOwn=false;
}



my test
using System;
using System.Drawing;

using Math3D;
using OgreDotNet;

namespace ODNTester
{

class cODNTester1 : OgreDotNet.ExampleApplication
{
protected OgreDotNet.MemoryDataStream mMDS=null;
protected OgreDotNet.DataStreamPtr mDSP=null;

protected override void CreateScene()
{

mSceneManager.SetSkyBox(true, "Examples/CloudyNoonSkyBox" );

//create a custom material the commented lines show using a byte[] array
string aa= "material MyNewMaterial/ThatIJustCreated\n{\n technique\n {\n pass\n {\n texture_unit\n {\n texture WoodPallet.png\n }\n }\n }\n}\n";
//byte[] bb = System.Text.Encoding.ASCII.GetBytes(aa);
mMDS = new MemoryDataStream( "myMemDataStream" , (uint)aa.Length+2, false );
mMDS.SetBuffer(bb, 0, (uint)bb.Length );
//mMDS.SetBuffer(aa);
mDSP = new DataStreamPtr( mMDS );

//now parse the script
MaterialManager.Instance.ParseScript( mDSP, ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME);


Entity e=null;
SceneNode n=null;

//create a ground plain
Plane plane = new Plane();
plane.Normal.x=0;
plane.Normal.y=1;
plane.Normal.z=0;
plane.D = 0;
MeshPtr m = MeshManager.GetSingleton().CreatePlane( "Ground", "General" , plane,
5000,5000,10,10,true,1,50,50,Vector3.UnitZ );
e = mSceneManager.CreateEntity( "Ground", "Ground" );
e.SetMaterialName("MyNewMaterial/ThatIJustCreated");
e.SetCastShadows(false);
mSceneManager.GetRootSceneNode().CreateChildSceneNode("Ground").AttachObject(e);
m.SetNull();
m=null;


mCamera.Move( new Vector3(0, 200, 600) );
mCamera.LookAt = new Vector3( 0, 0, 0 );
}


public override void Dispose()
{
//
//mSceneManager.ClearScene(); //.DestroyEntity("Ground");
//MeshManager.Instance.unload("Ground");
//MaterialManager.Instance.unload("MyNewMaterial/ThatIJustCreated");

MemoryDataStream.RemoveOwnership(mMDS);
mMDS=null;

mDSP.SetNull();
mDSP.Dispose();
mDSP=null;



mLog.Dispose();
mLog=null;

base.Dispose();
}

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
cODNTester1 app = new cODNTester1();
try
{
app.Start();
}
catch ( Exception ex)
{
Console.WriteLine( "### Exception {0}\n{1}\n{2}", ex.Message ,ex.Source , ex.StackTrace );
}
finally
{
try
{
app.Dispose();
}
catch ( Exception ex)
{
Console.WriteLine( "### Exception {0}\n{1}\n{2}", ex.Message ,ex.Source , ex.StackTrace );
}
}
}
}
}

vintersorg

04-04-2006 07:15:22

This is great.

Thanx man! This will without doubt speed up the progress on the editor. :)

Will try to grab some screenies when i get home from work today.

vintersorg

05-04-2006 07:27:29

Alright. I had 3 screens on my USB-memory, unfortunately i forgot it at home. :(

But I can now load materials, works fine. There is some path-issues though when loading a material which has a gpu-program, if i don't manually change the path it will try to find for example "media/scripts/programs relative to the folder where i load the material from, this is also the case with textures.

Another thing that i'm trying to work around is that when loading a material, the vertex/fragment-program will load automatically, which can be an issue if you load a material with another resource structure than the material editor has. I think i will solve this by simply searching the material file for vertex/fragment programs/textures, and if found, tell the user to provide the path to the folder containing the gpuprogram, the application will then add the full path to the resourcemanager and last of all parse the material.

Huge Credits to Rastaman for fixing the resourceloader stuff so quickly! :)

vintersorg

06-04-2006 07:21:38

Ok. Here are my screens. Maybe not too impressive at the moment, but this will hopefully be a useful application when done. Got my CG-book yesterday too, so i will look at a nice way to work with the shaders. :)

This is actually from two different tests...

Screen 1

Screen 2

Screen 3

Lee04

06-04-2006 09:07:34

Really nice.



/Lee04

vintersorg

06-04-2006 09:32:00

Thanx. Well, this is early tests to find a somewhat easy interface to use.

rastaman

06-04-2006 15:54:31

looking good :)
I'm happy to see somone finding ODN usefull.

vintersorg

10-04-2006 07:27:38

Yes, i find it extremely useful. :) Even though i'm using C++ for my game, there's always alot of tools needed when building a game, and VB/C# is perfect for GUI-based applications... I've been a huge VB-fan since i first tried it (version 4), and actually wrote my first piece of code 17 years ago in Commodore 64-basic. :)

The editor is still evolving, although i'm trying a different approach now, i think it's too much file-searching when loading a material file, then try to find the vertex/fragment program-definitions, then the CG-file.. Then the textures. etc.. I will try using the Resources.Cfg as a kind of workspace, and the application will also create such a file if needed. That way, you don't need to get confused searching (although i made a File Explorer, which displays the material/vertex/fragment-program names as tooltips when ponting at the files which might be useful when looking for them)..

Well. :) Thanx for your support. :)