Irrlicht Lime is a .NET wrapper for Irrlicht Engine

Announce new projects or updates of Irrlicht Engine related tools, games, and applications.
Also check the Wiki
greenya
Posts: 1012
Joined: Sun Jan 21, 2007 1:46 pm
Location: Ukraine
Contact:

Re: Irrlicht Lime is a .NET wrapper for Irrlicht Engine

Post by greenya »

You cannot inherit MeshLoader.
You have to load custom formats by yourself. Please see the examples to see how you can create a mesh.
szpaq234
Posts: 4
Joined: Tue Jul 19, 2011 2:49 pm

Re: Irrlicht Lime is a .NET wrapper for Irrlicht Engine

Post by szpaq234 »

Several hours of debugging to find out that this does not work:

Code: Select all

Driver.GPUProgrammingServices.OnSetConstants += new GPUProgrammingServices.SetConstantsHandler(DoShaderThing);
but this does:

Code: Select all

GPUProgrammingServices gpu = Driver.GPUProgrammingServices;
gpu.OnSetConstants += new GPUProgrammingServices.SetConstantsHandler(DoShaderThing);
What kind of madness is that ?
greenya
Posts: 1012
Joined: Sun Jan 21, 2007 1:46 pm
Location: Ukraine
Contact:

Re: Irrlicht Lime is a .NET wrapper for Irrlicht Engine

Post by greenya »

Driver.GPUProgrammingServices returns wrapped pointer on native video::IGPUProgrammingServices. It will return always a new object (new wrapped object GPUProgrammingServices). So in first case, you don't save it in any variable, so garbage collector destroys it any time soon. In the second case, you have a distinct variable, so it works.

You can test it also like:

Code: Select all

...
{
    // juts some local scope
    GPUProgrammingServices gpu = Driver.GPUProgrammingServices;
    gpu.OnSetConstants += new GPUProgrammingServices.SetConstantsHandler(DoShaderThing);
}
...
This should work just like in 1st case.
szpaq234
Posts: 4
Joined: Tue Jul 19, 2011 2:49 pm

Re: Irrlicht Lime is a .NET wrapper for Irrlicht Engine

Post by szpaq234 »

When I set Node.Visible = false, its collision doesn't work and its children's position are no longer updated. This is very wrong. How can I make node invisible only to my eyes ?
greenya
Posts: 1012
Joined: Sun Jan 21, 2007 1:46 pm
Location: Ukraine
Contact:

Re: Irrlicht Lime is a .NET wrapper for Irrlicht Engine

Post by greenya »

This is behavior of the Irrlicht Engine, not special case of the wrapper.
As for me, i agree, this is a problem, for instance in the example with small room, dwarf, water, flying light and real-time shadows. If you don't see the dwarf, its animation is also doesn't plays, you can see his freezing shadow on the wall.
bdpdonp
Posts: 68
Joined: Sat Oct 10, 2009 6:35 am

Re: Irrlicht Lime is a .NET wrapper for Irrlicht Engine

Post by bdpdonp »

I am using Visual Studio 2013 for the performance advantage of NET 4.5. In order to obtain DD support I need to change the irrlicht confim.h which I do. The problem is with the changes the wchar_t is not longer an option to change and I am therefor unable to rebuild lime.

Has anyone determined a fix to allow lime to compile with a rebuilt irrlicht under vs 2013?
Jonhson243
Posts: 9
Joined: Sun Aug 04, 2013 4:03 pm

Re: Irrlicht Lime is a .NET wrapper for Irrlicht Engine

Post by Jonhson243 »

Hi there, I have a question that seems easy but since I'm a beginner I don't know how to handle it.
I am building an app that is used to display Metallics Objects (3ds) models. I was happy with the rendering which is smooth and clean. However my customer told me that the objects look too much "like in video games".

Do you have any idea of the effects that I can apply to make the objects look more realistic ? I don't use UV Mapping, I have very simple 3Ds objects and I color the nodes using IrrlichtLime. I just want to try to make them more realistic, perhaps by adding some simple effects (Which one ? and - if you have some time - how ?) . I have a really close deadline so I would be very thankful for any kind of help. (Please note that I'm not fluent at all with 3D programming, this my first - and certainly last :lol: - project on the subject. I'm ready and willing to make efforts but honestly I won't be able to handle stuff too much complicate.)


Here is the code that I use to color the nodes :

Code: Select all

for (int i = 0; i < _node.MaterialCount; ++i)
            {
                _node.GetMaterial(i).EmissiveColor = new IrrlichtLime.Video.Color(R, G, B);
                _node.GetMaterial(i).DiffuseColor = new IrrlichtLime.Video.Color(R, G, B);
            }
            _node.SetMaterialType(MaterialType.Solid);
And below is the current code that I use to make it look better :

Code: Select all

 
 //On active la lumière sur le mesh
            _node.SetMaterialFlag(MaterialFlag.Lighting, true);
            _node.SetMaterialFlag(MaterialFlag.NormalizeNormals, true);
            _node.GetMaterial(0).SpecularColor = new Color(255, 255, 255, 255);
            _node.GetMaterial(0).AmbientColor = new Color(255, 255, 255, 255);
            _node.GetMaterial(0).DiffuseColor = new Color(255, 255, 255, 255);
            _node.GetMaterial(0).EmissiveColor = new Color(0, 0, 0, 0);
            _node.GetMaterial(0).Shininess = 50;
 
Thank you very much !
greenya
Posts: 1012
Joined: Sun Jan 21, 2007 1:46 pm
Location: Ukraine
Contact:

Re: Irrlicht Lime is a .NET wrapper for Irrlicht Engine

Post by greenya »

Hello.

Well, there are next ways to make object look better:
- play with colors (as you do)
- use texturing
- use shaders

If you use only "color", i don't think you can achieve good result. When you see in 3dmax simple colored object indeed its not only colored, its per-pixel-lighted, which makes it look good, and that "effect is made via shaders". The cheapest way to add realism is to use textures. I don't know what kind of app are you doing but if your objects static you can pretty much prerender textures with shadows which will look quite good. If your objects moves, than i still recommend you to get some textures; even if your objects are meant to be simple-colored you can add some roughness to make them look more real.
figment
Posts: 3
Joined: Sat Feb 08, 2014 4:51 pm

Re: Irrlicht Lime is a .NET wrapper for Irrlicht Engine

Post by figment »

Hi. I've recently discovered Irrlicht and Lime and they look to be perfect for what I would like to use them for. Effectively I'm looking for an embeddable .NET 3d engine with support for x86 and x64 builds and this fits the bill nicely. I've converted most of the examples to IronPython successfully (after fixing a bug in IronPython itself around protected events in base classes).

Now I'm encountering crashes in a Drop() method in the L05 example. I'm pretty confident the issue is centered in memory allocation issues. Basically, IrrlichtLime allocates memory in FileSystem.cpp and allows CMemoryReadFile to delete it when disposed. This seems like pretty bad practice on the Irrlicht Engine side as memory should always be allocated and freed by the same library and should never try to share things that way. I've fixed it in my local builds by adding an additional flag in FileSystem to duplicate the memory and then let it duplicate the memory block then having Lime use that with a pin_ptr.

Thoughts? I'll see what I can do about generating some patches for submission if you agree. I'll also share links to my version of the converted examples later after I get them all basically working.

Also I think it would be good practice to use IDispose and Finalizers on ReferenceCount objects rather than explicit Drop methods. IDispose would be consistent with .NET already and then semantics like Using in C# would do the right thing if exceptions occur. I see it was discussed before but will leave my thoughts here.

Edit: cannot submit patches/bugs/requests on sourceforge for your project. My request to Irrlicht Engine is https://sourceforge.net/p/irrlicht/patches/279/. And then use that in Lime (with use of pin_ptr and nullptr rather than constructing local objects in FileSystem.cpp.
greenya
Posts: 1012
Joined: Sun Jan 21, 2007 1:46 pm
Location: Ukraine
Contact:

Re: Irrlicht Lime is a .NET wrapper for Irrlicht Engine

Post by greenya »

Hello.

I don't see any problem with next code:

Code: Select all

 
ReadFile f = device.FileSystem.CreateMemoryReadFile("screenTexture", c);
Texture t = device.VideoDriver.GetTexture(f);
f.Drop();
 
We created object, we used it, we destroyed it explicitly (memory deallocated exactly at point where we expect it to be -- after Drop() call). And "yes", CreateMemoryReadFile() has next code:

Code: Select all

 
ReadFile^ FileSystem::CreateMemoryReadFile(String^ filename, array<unsigned char>^ content)
{
    LIME_ASSERT(filename != nullptr);
    LIME_ASSERT(content != nullptr);
 
    int c = content->Length;
    unsigned char* m = new unsigned char[c];
 
    for (int i = 0; i < c; i++)
        m[i] = content[i];
 
    io::IReadFile* f = m_FileSystem->createMemoryReadFile(
        m,
        c,
        Lime::StringToPath(filename),
        true /* allocated m will be deleted automatically on drop() */);
 
    return ReadFile::Wrap(f);
}
 
The idea is that we assume that programmer will call Drop(). This is not something which is about this method only, this is about whole Irrlicht and Irrlicht Lime (since second one is not a distinct engine, its a wrapper of the first one). So basically using Irrlicht Lime requires from programmer to call Drop() for each Create*(). It needs more attention, agreed, but it also gives more control and understanding of what exactly Irrlicht does.
figment
Posts: 3
Joined: Sat Feb 08, 2014 4:51 pm

Re: Irrlicht Lime is a .NET wrapper for Irrlicht Engine

Post by figment »

The code looks ok; the issue that you are allocating a buffer in one assembly, IrrichtLime.dll, and allowing another assembly/dll Irricht.dll to delete the memory which could have its own heap manager. Ideally if you use the same memory allocator then it will work and my experience that the debug builds of the msvcrt will let you delete from other heaps. My problem has been with X64 Release builds even with matching compiler settings (except for the /clr flag) which will always flag the free of the buffer as invalid and crash. I was using /MD on both libraries but it did not help.

Perhaps the commits I made to my local copies for the library will illustrate the change:
https://github.com/figment/Irrlicht/com ... b6db3c864f
https://github.com/figment/Irrlicht-Lim ... 33a2185397

Anyway, I've ported most of your examples except L08.WPFWindow to IronPython 2.9.x (unreleased) for both Win32 and X64 architectures and surprisingly they worked very well and have great performance. The biggest issues were the pathfinding and abstracttrace examples which IronPython does not handle well with a simple port.

Here is the LimePy repository if there is any interest:
https://github.com/figment/Irrlicht-LimePy

I'm looking forward to using this library quite a bit after seeing how well it performs and how easy it is to use.
greenya
Posts: 1012
Joined: Sun Jan 21, 2007 1:46 pm
Location: Ukraine
Contact:

Re: Irrlicht Lime is a .NET wrapper for Irrlicht Engine

Post by greenya »

If I would accept solutions with changing Irrlicht native code for Lime needs, than yeah, that code would get some other implementation for sure. But Lime doesn't change the source of the Irricht. I mean you literally compile Lime with original Irrlicht source (IrrCompileConfig.h is the only file gets changes about enabling _IRR_COMPILE_WITH_DIRECT3D_8_ and _IRR_WCHAR_FILESYSTEM). This is convenient because i don't need to support such changes in future. But this approach has drawbacks, just like you described.

I suppose next changes:
- tell to IFileSystem::createMemoryReadFile() "do not drop memory for us";
- add storing of pointer on the buffer in managed ReadFile class;
- override Drop() of ReferenceCounted interface (for this we need to mark ReferenceCounted::Drop() with "virtual");

The patch would be next:

Code: Select all

Index: source/FileSystem.cpp
===================================================================
--- source/FileSystem.cpp   (revision 496)
+++ source/FileSystem.cpp   (working copy)
@@ -273,10 +273,18 @@
    io::IReadFile* f = m_FileSystem->createMemoryReadFile(
        m,
        c,
-       Lime::StringToPath(filename),
-       true /* allocated m will be deleted automatically on drop() */);
+       Lime::StringToPath(filename));
 
-   return ReadFile::Wrap(f);
+   if (f == nullptr)
+   {
+       delete[] m;
+       return nullptr;
+   }
+
+   ReadFile^ readFile = ReadFile::Wrap(f);
+   readFile->m_MemoryBuffer = m;
+
+   return readFile;
 }
 
 WriteFile^ FileSystem::CreateMemoryWriteFile(String^ filename, int length)
Index: source/ReadFile.cpp
===================================================================
--- source/ReadFile.cpp (revision 496)
+++ source/ReadFile.cpp (working copy)
@@ -21,8 +21,19 @@
    : ReferenceCounted(ref)
 {
    m_ReadFile = ref;
+   m_MemoryBuffer = nullptr;
 }
 
+bool ReadFile::Drop()
+{
+   bool r = ReferenceCounted::Drop();
+
+   if (r && m_MemoryBuffer != nullptr)
+       delete[] m_MemoryBuffer;
+   
+   return r;
+}
+
 array<unsigned char>^ ReadFile::Read(int bytesToRead)
 {
    LIME_ASSERT(bytesToRead > 0);
Index: source/ReadFile.h
===================================================================
--- source/ReadFile.h   (revision 496)
+++ source/ReadFile.h   (working copy)
@@ -14,6 +14,8 @@
 {
 public:
 
+   virtual bool Drop() override;
+
    array<unsigned char>^ Read(int bytesToRead);
 
    bool Seek(long position, bool relativeMovement);
@@ -31,6 +33,7 @@
    ReadFile(io::IReadFile* ref);
 
    io::IReadFile* m_ReadFile;
+   unsigned char* m_MemoryBuffer;
 };
 
 } // end namespace IO
Index: source/ReferenceCounted.h
===================================================================
--- source/ReferenceCounted.h   (revision 496)
+++ source/ReferenceCounted.h   (working copy)
@@ -15,7 +15,7 @@
    static bool operator == (ReferenceCounted^ v1, ReferenceCounted^ v2);
    static bool operator != (ReferenceCounted^ v1, ReferenceCounted^ v2);
 
-   bool Drop();
+   virtual bool Drop();
    void Grab();
 
    property String^ DebugName { String^ get(); }
 
We actually updated 4 files, but we can override Drop() for any certain class for future needs.
greenya
Posts: 1012
Joined: Sun Jan 21, 2007 1:46 pm
Location: Ukraine
Contact:

Re: Irrlicht Lime is a .NET wrapper for Irrlicht Engine

Post by greenya »

I would add such change in Lime with no doubts if there wasn't one big problem with that approach.

This scenario shows how this will memleak:
- suppose Irrlicht has method witch takes IReadFile*, it written correctly, it do grabbing and dropping properly;
- we created out managed ReadFile object, we passed to that method our pointer (which is nothing more than something like readFile->m_ReadFile, where m_ReadFile is actually a native pointer -- IReadFile*);
- now we call readFile.Drop(), everthing goes OK, this Drop() will not actually drop the object, it will return false and of cause our memory will not be freed;
- right now, the only pointer on IReadFile has internally Irrlicht, i say even more, it doesn't know anything about managed pointer, its Drop() method which will never be called; Irrlicht will call drop() on native pointer and it will be correctly processed and free, except our memory;

So as you see its not 100% solution. We can use it in such cases like L05 example has, we create, we use, we drop. We can use it anywhere when we are sure we Drop after all others. I mean managed Drop() must be the last call, not native one.

Well, I guess the code can be improved to the point when upper scenario will pass with no memleak. We just need to create kind of operator class -- the class which has native roots (declared as native, and therefore can actually inherit native IReferenceCounted), and it will also contain managed pointer, which it will use to call managed methods we need. I'm not sure if its viable approach, still needs more thinking and testing.
figment
Posts: 3
Joined: Sat Feb 08, 2014 4:51 pm

Re: Irrlicht Lime is a .NET wrapper for Irrlicht Engine

Post by figment »

I've already made the change request for the change I'm interested in Irrlicht (link in previous post). If they accept then I think it manages the resources properly for this case and you can adopt it then. If they don't then of course it will require clumsy workarounds for people trying to avoid it. I'm content with forks of the projects but ideally would like my changes back in the master repositories when they make sense.

I suspect that part of your problem with automatic reference disposal is that you are not using Grab consistently when acquiring native pointers so if you Drop a resource that is acquired like say VideoDriver from the driver its counter is not incremented so you cannot drop it or it will be deleted if you try while other people are still using it. I ran into this in my first attempt and fixing the code.

Basically if when you Wrap a pointer that is not part of a create then you should Grab otherwise it already has one reference count from the Create. or alternately always Grab during a wrap but then Drop after a Create when you have passed the pointer along. Now you can Dispose of the pointer through either the Dispose or Finalize methods of the managed reference counter. This would be a sweeping change to your library so I've not tried to do that on my local code yet and may not if its not really a problem.

Instead I've made a simple change on my local build to add the IDisposable interface to the ReferenceCounted object. What I've left for now is that Finalize method does not drop but you can use it in a using statement in C# or with statement in IronPython to ensure resource cleanup. Link to my implementation https://github.com/figment/Irrlicht-Lim ... ec1ae5a810

The code can then be used like the following. Again its stylistic. I prefer the using as its autowrapped in try/finally and ensures drop is called if exception occurs. Ultimately though if Grab were used then finalize could be used and memory leaks should be less of an issue (baring issues like memory being disposed in other threads and other possible issues).

Code: Select all

 
            LogLevel o = device.Logger.LogLevel;
            try {
                device.Logger.LogLevel = LogLevel.Error; // we hide all those "Loaded texture" messages in console {{
                using (ReadFile f = device.FileSystem.CreateMemoryReadFile("screenTexture", c))
                    return device.VideoDriver.GetTexture(f);
            } finally {
                device.Logger.LogLevel = o; // }}
            }
 

Code: Select all

 
        o = device.Logger.LogLevel
        device.Logger.LogLevel = LogLevel.Error # we hide all those "Loaded texture" messages in console {{
        with device.FileSystem.CreateMemoryReadFile("screenTexture", c) as f: 
            t = device.VideoDriver.GetTexture(f)
        device.Logger.LogLevel = o # }}
        return t
 
render_noob
Posts: 2
Joined: Wed Feb 26, 2014 7:16 am

Re: Irrlicht Lime is a .NET wrapper for Irrlicht Engine

Post by render_noob »

Sorry for the incredibly noob question, but I'm not sure where else to ask.

I'm trying to get the screen space coords of a point in world space.

So this is what I'm trying:

Code: Select all

 
var nodePt = new Vector3Df(10,10,-10);
cam.ViewMatrix.TransformVector(ref nodePt);
cam.ProjectionMatrix.TransformVector(ref nodePt);
 
var driver = device.VideoDriver;
 
// convert to screen coords
nodePt += new Vector3Df(1, 1, 0);
nodePt /= 2;
nodePt.X *= driver.ViewPort.Width;
nodePt.Y *= driver.ViewPort.Height;
driver.SetTransform(TransformationState.World, Matrix.Identity);
driver.Draw2DPolygon((int)Math.Round(nodePt.X), (int)Math.Round(nodePt.Y), 15, Color.OpaqueMagenta, 5);A
 
So what am I doing wrong? I also tried multiplying the nodePt vector by the inverse of the camera transform matrix (ie: cam.AbsoluteTransformation.MakeInverse().TransformVector(ref nodePt))

Any help would be greatly appreciated.
Post Reply