Page 23 of 29

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

Posted: Fri Aug 09, 2013 1:18 pm
by greenya
Jonhson243 wrote:-Can you give me the one line statement to translate a camera ?
-The same but to rotate a camera
It depends on what you need it to be. If you need it to rotate without user input, you just use some RotationAnimator and the mode will be constantly rotated. If you need give user ability to navigate, you can check how its done in L04.ParticleEmitterViewer, it has a slider (a WinForms UI control) which user drags it sends particular messages to rendering thread using Viewport class:

Code: Select all

private void trackBarCameraView_Scroll(object sender, EventArgs e)
{
    viewport.EnqueueCommand(CommandType.CameraView, (float)trackBarCameraView.Value);
}
So you can use same approach. You can add more commands to CommandType enum if you need and process them in rendering thread.
Jonhson243 wrote:-And finally, I would just need to insert a background 2D image. So I just need the code to insert such background then I'll manage the rest myself. The idea is to position the 3D object on the background image.
There is an example L05.ScreenshotToTexture, which draw a texture on the background and rotates the cube with that texture. Generally all you need is to load the image file as texture and draw it before scene.DrawAll() call:

Code: Select all

device.VideoDriver.GetTexture( // loads the image file as a texture
device.VideoDriver.Draw2DImage( // draws the texture

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

Posted: Sun Aug 11, 2013 7:02 pm
by roxaz
By the way i crafted proof of concept code that fixes crash due to textures being deleted in another thread. Its a dirty hack. Idea is simple - when ref count is 1 and finalizer calls drop we push native object to the list, later on method called from main thread iterates list and drops final reference thus freeing up object. For some reason i bumped into weird internal compiler errors when i tried to use System::Windows::Threading::Dispatcher to invoke drop on main thread. Using that would be preferable to doing this manually. Anyway - please evaluate idea.

Code: Select all

Index: source/ReferenceCounted.cpp
===================================================================
--- source/ReferenceCounted.cpp (revision 493)
+++ source/ReferenceCounted.cpp (working copy)
@@ -3,6 +3,7 @@
 
 using namespace irr;
 using namespace System;
+using namespace System::Threading;
 
 namespace IrrlichtLime {
 
@@ -28,20 +29,59 @@
 ReferenceCounted::ReferenceCounted(irr::IReferenceCounted* referenceCounted_or_null)
 {
    m_ReferenceCounted = referenceCounted_or_null;
+   if( referenceCounted_or_null != nullptr )
+       Grab();
 }
 
 bool ReferenceCounted::Drop()
 {
    LIME_ASSERT(m_ReferenceCounted != nullptr);
-   return m_ReferenceCounted->drop();
+   GarbageCollect();
+   if(m_ReferenceCounted->drop())
+   {
+       m_ReferenceCounted = nullptr;
+       return true;
+   }
+   return false;
 }
 
 void ReferenceCounted::Grab()
 {
    LIME_ASSERT(m_ReferenceCounted != nullptr);
    m_ReferenceCounted->grab();
+   GarbageCollect();
 }
 
+ReferenceCounted::!ReferenceCounted()
+{
+   if( m_ReferenceCounted != nullptr )
+   {
+       if(m_ReferenceCounted->getReferenceCount() == 1 && Thread::CurrentThread->ManagedThreadId != m_MainThreadId)
+       {
+           Monitor::Enter(m_PendingDeletion);
+           IntPtr ptr((Void*)m_ReferenceCounted);
+           if(!m_PendingDeletion->Contains(ptr))
+               m_PendingDeletion->Add(ptr);
+           Monitor::Exit(m_PendingDeletion);
+       }
+       else
+           Drop();
+   }
+}
+
+void ReferenceCounted::GarbageCollect()
+{
+   if((Environment::TickCount - m_LastGarbageCollect) > 60000 && Thread::CurrentThread->ManagedThreadId == m_MainThreadId)
+   {
+       m_LastGarbageCollect = Environment::TickCount;
+       Monitor::Enter(m_PendingDeletion);
+       for each(IntPtr ptr in m_PendingDeletion)
+           ((irr::IReferenceCounted*)ptr.ToPointer())->drop();
+       m_PendingDeletion->Clear();
+       Monitor::Exit(m_PendingDeletion);
+   }
+}
+
 String^ ReferenceCounted::DebugName::get()
 {
    LIME_ASSERT(m_ReferenceCounted != nullptr);
Index: source/ReferenceCounted.h
===================================================================
--- source/ReferenceCounted.h   (revision 493)
+++ source/ReferenceCounted.h   (working copy)
@@ -4,6 +4,7 @@
 
 using namespace irr;
 using namespace System;
+using namespace System::Threading;
 using namespace IrrlichtLime::Core;
 
 namespace IrrlichtLime {
@@ -21,11 +22,21 @@
    property String^ DebugName { String^ get(); }
    property int ReferenceCount { int get(); }
 
+   ~ReferenceCounted(){this->!ReferenceCounted();}
+   !ReferenceCounted();
+
 internal:
 
    ReferenceCounted(irr::IReferenceCounted* referenceCounted_or_null);
 
    irr::IReferenceCounted* m_ReferenceCounted;
+
+   void GarbageCollect();
+
+   delegate bool DropDelegate();
+   static int m_MainThreadId = Thread::CurrentThread->ManagedThreadId;
+   static List<IntPtr>^ m_PendingDeletion = gcnew List<IntPtr>();
+   static int m_LastGarbageCollect = 0;
 };
 
 } // end namespace IrrlichtLime
\ No newline at end of file
 

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

Posted: Sun Aug 11, 2013 10:53 pm
by greenya
Thats some true street magic is going on at GarbageCollect() :)

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

Posted: Wed Aug 28, 2013 1:54 pm
by Pilo
Hi, I have been using IrrlichtLime for a few weeks now and I have to say I am truly impressed by how good it is.

Unfortunately, I hit a bump in the road and I can't undestand what I should do to get out of it: what I want to do is basically to have a plane with a texture repeated across it. Based on some examples around and the documentation, I am doing the following:

Code: Select all

 
var grid = ScreenManager.Scene.AddHillPlaneMesh("grid", DIMENSION2DF_ONE, DIMENSION2DI_ONE);
var gNode = ScreenManager.Scene.AddMeshSceneNode(grid, null, MY_ID);
 
gNode.Position = new Vector3Df();
gNode.Scale = new Vector3Df(20, 1, 20);
gNode.SetMaterialFlag(MaterialFlag.Lighting, false);
gNode.SetMaterialType(MaterialType.TransparentAlphaChannel);
gNode.GetMaterial(0).SetTexture(0, ScreenManager.Driver.GetTexture(MY_TRANSPARENT_TEXTURE_HERE));
gNode.GetMaterial(0).GetTextureMatrix(0).SetTextureScale(20, 20);
 
But I end up with a huge square with a scaled up texture, and not a repeated texture as I would like.


I also tried the following, based on example 12 (TerrainRendering)

Code: Select all

 
var terrain = ScreenManager.Scene.AddTerrainSceneNode(
    (string)null, 
    null, 
    MY_ID, 
    new Vector3Df(),
    new Vector3Df(), 
    new Vector3Df(20, 1, 20), 
    new Color(255, 255, 255), 
    5, 
    TerrainPatchSize._17, 
    0, 
    true); //should let me add the mesh even if the heightmap is null
terrain.SetMaterialFlag(MaterialFlag.Lighting, false);
terrain.SetMaterialType(MaterialType.TransparentAlphaChannel);
terrain.SetMaterialTexture(0, ScreenManager.Driver.GetTexture(MY_TRANSPARENT_TEXTURE_HERE));
         
terrain.ScaleTexture(0, 20);
 
And in this case I end up with nothing at all on screen.

Any idea on what I am doing wrong?

Thanks

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

Posted: Wed Aug 28, 2013 5:37 pm
by greenya
Pilo wrote:...a plane with a texture repeated across it.
Hello!

Well, your first approach was right, the second one i didn't tested. Anyway, the problem was that GetTextureMatrix() returns a copy of the matrix, so the intention is that you save it, make changes and call SetTextreMatrix(). I made next code with the screenshot.

Code: Select all

            var grid = smgr.AddHillPlaneMesh("grid", new Dimension2Df(100), new Dimension2Di(1));
            var gNode = smgr.AddMeshSceneNode(grid);
            gNode.SetMaterialFlag(MaterialFlag.Lighting, false);
            gNode.SetMaterialType(MaterialType.TransparentAddColor);
            gNode.SetMaterialTexture(0, driver.GetTexture("../../media/particlegreen.jpg"));
            Matrix m = gNode.GetMaterial(0).GetTextureMatrix(0); // here, while debugging, you can see "m.m_DeleteOnFinalize == true", which means that "m" contains a copy of texture matrix
            m.Scale = new Vector3Df(20);
            gNode.GetMaterial(0).SetTextureMatrix(0, m);
Image

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

Posted: Thu Aug 29, 2013 7:56 am
by Pilo
Thanks a lot, it works perfectly! I didn't know about m_DeleteOnFinalize.. I am still learning about all of this :D

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

Posted: Tue Sep 10, 2013 8:33 pm
by Jonhson243
Hi!
I'm facing what I believe will be my last issue on this project. I'm allowing the user to change the color of the node by clicking on a button in the WPF part of the UI. The problem I have is the following :

Not every node can be colored the same way, therefore the colours list for each node is generated in the Irrlicht Thread. I have to wait that this list is generated in the Irrlicht Thread so that I can generate a colored button for every color of the list in the WPF part of the UI.

My problem is that I can't wait ! I mean : every time I try to put a tempo in the window thread, the rendering in the viewport becomes terrible, not smooth at all. Looks like there is a problem with the vsync between WPF and the Irrlicht. What I'm saying is certainly not accurate but this is the my intuition, hope it will give you an idea. To elaborate this tempo, I tried several things :

Put

Code: Select all

 while(!(bool)viewport.checkState) ;
In the window_load function of my WPF window. checkState is a variable that I set to "true" in the Irrlicht Thread when I'm sure that the colours list have been generated. I use the thread safe techniques that greenya taught me to read and to set the variable (private read only object...). But it produces the same ugly rendering in the viewport.

Then, I also try to simply wait for some seconds in my window_load function with

Code: Select all

Thread.Sleep(2000)
But it produces the same distortion.

The problem is clearly with the fact of temporizing in the Window Thread, the viewport doesn't seem to like it.
Any idea of how I can handle it ? I checked the ParticleEmitter example but it seems that they don't need a tempo.

Image

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

Posted: Tue Sep 10, 2013 10:34 pm
by greenya
I don't really get what is the problem.
If generation time of some colors take so much than why you just don't pre-generate them all?
Why do you need to generate the colors in the Irrlicht thread? Maybe you can do it in WPF thread, when user selects a color, you just pass it to the Irrlicht thread.
And nothing like

Code: Select all

while(!(bool)viewport.checkState) ;
or

Code: Select all

Thread.Sleep(2000)
is correct in most cases. You force to wait the thread for something to happen. Instead, the logic should be next: you should check for example viewport.checkState and if its "not ready", you should continue the thread and do all the stuff (rendering in case of Irrlicht thread), and on next iteration you check viewport.checkState again and if its ready at that moment - you do the job.

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

Posted: Tue Nov 05, 2013 8:51 pm
by mrfireturkey
Hello, I've found the Irrlicht Lime wrapper to be quite excellent!

I'm having trouble converting this 2D image with rotate method, posted here, into the C# Lime equivalent:
http://irrlicht.sourceforge.net/forum/v ... =9&t=32388

I've attempted to extend this 2D example into my application.

Here is what I have so far, but it doesn't draw anything to the screen, where the standard Draw2d

Code: Select all

 
public class Sprite
{
        public Texture BaseTexture { get; set; }
        public float Rotation { get; set; }
        public Vector2Di Position { get; set; }
        public Vector2Di RotationPoint { get; set; }
        public Vector2Df Scale { get; set; }
        public Recti SourceRect { get; set; }
 
        public Sprite()
        {
            BaseTexture = null;
            Rotation = 0;
            Position = new Vector2Di();
            RotationPoint = new Vector2Di();
            Scale = new Vector2Df();
            SourceRect = new Recti();
        }
 
        // Works fine
        public void DrawSimple(VideoDriver driver)
        {
            driver.Draw2DImage(BaseTexture, Position);
        }
 
        // This is the trouble method //
        public void DrawRotate(VideoDriver driver, Color color, bool UseAlphaChannel)
        {
            // Store and clear the projection matrix
           Matrix oldProjMat = driver.GetTransform(TransformationState.Projection);
           driver.SetTransform(TransformationState.Projection, new Matrix());
 
            // Store and clear the view matrix
            Matrix oldViewMat = driver.GetTransform(TransformationState.View);
            driver.SetTransform(TransformationState.View, new Matrix());
 
            // Store and clear the world matrix
            Matrix oldWorldMat = driver.GetTransform(TransformationState.World);
            driver.SetTransform(TransformationState.World, new Matrix());
 
            // Find horizontal and vertical axes after rotation
            float c = (float)Math.Cos(-Rotation * 0.017453f);
            float s = (float)Math.Sin(-Rotation * 0.017453f);
 
            Vector2Df horizontalAxis = new Vector2Df(c, s);
            Vector2Df verticalAxis = new Vector2Df(s, -c);
 
            // First, we'll find the offset of the center and then where the center would be after rotation
            Vector2Df centerOffset = new Vector2Df(Position.X + SourceRect.Width / 2.0f * Scale.X - RotationPoint.X, Position.Y + SourceRect.Height / 2.0f * Scale.Y - RotationPoint.Y);
            Vector2Df center = new Vector2Df( (horizontalAxis.X * centerOffset.X) - (verticalAxis.X * centerOffset.Y), (horizontalAxis.Y * centerOffset.X) - (verticalAxis.Y * centerOffset.Y) );
            center.X += RotationPoint.X;
            center.Y += RotationPoint.Y;
 
            // Now find the corners based off the center
            Vector2Df cornerOffset = new Vector2Df(SourceRect.Width * Scale.X / 2.0f, SourceRect.Height * Scale.Y / 2.0f);
            verticalAxis *= cornerOffset.Y;
            horizontalAxis *= cornerOffset.X;
            Vector2Df[] corner = new Vector2Df[4];
            corner[0] = center + verticalAxis - horizontalAxis;
            corner[1] = center + verticalAxis + horizontalAxis;
            corner[2] = center - verticalAxis - horizontalAxis;
            corner[3] = center - verticalAxis + horizontalAxis;
 
            // Find the uv coordinates of the sourceRect
            Vector2Df textureSize = new Vector2Df(BaseTexture.Size.Width, BaseTexture.Size.Height);
            Vector2Df[] uvCorner = new Vector2Df[4];
            uvCorner[0] = new Vector2Df(SourceRect.UpperLeftCorner.X, SourceRect.UpperLeftCorner.Y);
            uvCorner[1] = new Vector2Df(SourceRect.LowerRightCorner.X, SourceRect.UpperLeftCorner.Y);
            uvCorner[2] = new Vector2Df(SourceRect.UpperLeftCorner.X, SourceRect.LowerRightCorner.Y);
            uvCorner[3] = new Vector2Df(SourceRect.LowerRightCorner.X, SourceRect.LowerRightCorner.Y);
            for(int i = 0; i < 4; i++)
            {
                uvCorner[i] /= textureSize;
            }
 
            // Vertices for the image
            Vertex3D []vertices = new Vertex3D[4];
            ushort []indices = { 0, 1, 2, 3 ,2 ,1 };
 
            // Convert pixels to world coordinates
            Vector2Df screenSize = new Vector2Df(driver.ViewPort.Width, driver.ViewPort.Height);
            for (int i = 0; i < 4; i++) 
            {
                vertices[i] = new Vertex3D();
                vertices[i].Position = new Vector3Df(((corner[i].X/screenSize.X)-0.5f)*2.0f,((corner[i].Y/screenSize.Y)-0.5f)*-2.0f,1);
                vertices[i].TCoords = uvCorner[i];
                vertices[i].Color = color;
            }
 
            // Create the material
            Material material = new Material();
            material.BlendOperation = BlendOperation.Add;
            material.Lighting = false;
            material.ZWrite = false;
            material.ZBuffer = ComparisonFunc.Disabled;
            material.BackfaceCulling = false;
            material.SetTexture(0, this.BaseTexture);
            
            /* can't find lime equivalent
            material.MaterialTypeParam = 
                irr::video::pack_texureBlendFunc(irr::video::EBF_SRC_ALPHA, 
                    irr::video::EBF_ONE_MINUS_SRC_ALPHA, 
                    irr::video::EMFN_MODULATE_1X, 
                    irr::video::EAS_TEXTURE | irr::video::EAS_VERTEX_COLOR); 
            */
 
            if(UseAlphaChannel)
                material.Type = MaterialType.OneTextureBlend;
            else
                material.Type = MaterialType.Solid;
 
            driver.SetMaterial(material);
            driver.Draw2DVertexPrimitiveList(vertices, indices);
 
            // Restore projection, world, and view matrices
            driver.SetTransform(TransformationState.Projection, oldProjMat);
            driver.SetTransform(TransformationState.View ,oldViewMat);
            driver.SetTransform(TransformationState.World, oldWorldMat);
           
        }
}
 
If I'm totally missing something, or there is a much easier way to rotate a 2d image, let me know. My previous games were done with the Haaf's Game engine. Unfortunately I can't mix 3D in with it, and Irrlicht Lime is otherwise awesome except not being able to rotate a 2d image intuitively.

Thanks.

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

Posted: Wed Nov 06, 2013 10:44 am
by greenya
Hello.
mrfireturkey wrote:

Code: Select all

 
            /* can't find lime equivalent
            material.MaterialTypeParam = 
                irr::video::pack_texureBlendFunc(irr::video::EBF_SRC_ALPHA, 
                    irr::video::EBF_ONE_MINUS_SRC_ALPHA, 
                    irr::video::EMFN_MODULATE_1X, 
                    irr::video::EAS_TEXTURE | irr::video::EAS_VERTEX_COLOR); 
            */
 
Right now, Lime has no pack_texureBlendFunc(), temporary you can write it yourself.
Here how it can be done:

Code: Select all

// Floating-point representation of an unsigned integer value.
public static float FR(uint x)
{
    return BitConverter.ToSingle(BitConverter.GetBytes(x), 0);
}
 
// MaterialType.OneTextureBlend: pack srcFact, dstFact, Modulate and alpha source to MaterialTypeParam
// alpha source can be an OR'ed combination of AlphaSource values.
public static float pack_textureBlendFunc(BlendFactor srcFact, BlendFactor dstFact, ModulateFunc modulate = ModulateFunc._1x, AlphaSource alphaSource = AlphaSource.Texture)
{
    uint x = (((uint)alphaSource) << 12) | (((uint)modulate) << 8) | (((uint)srcFact) << 4) | ((uint)dstFact);
    return FR(x);
}
Now your code can use it like:

Code: Select all

material.MaterialTypeParam = pack_textureBlendFunc(
    BlendFactor.SrcAlpha,
    BlendFactor.OneMinusSrcAlpha,
    ModulateFunc._1x,
    AlphaSource.Texture | AlphaSource.VertexColor);
Here is what I have so far, but it doesn't draw anything to the screen, where the standard Draw2d
Try my code above. If you don't see anything, then you should try step-by-step approach: first try do draw an image without special material blend functions and without rotations, then if you see it, you can go for the next step. Eventually you will stop seeing the image, and you will know what step causes it.

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

Posted: Wed Nov 06, 2013 4:41 pm
by NemoStein
greenya,

If you follow this thread you'll see that CuteAlien made a small (but precious) bugfix in the Collada loader.

He said that the fix won't come until 1.9, but that doesn't matter for me too much, as I use Lime and, as you use the IrrLicht trunk, I can have the fix faster.
Could you, by any chance, recompile Lime? :D

If not, I understand perfectly, but you'll make a kid very happy if you do! ^_^

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

Posted: Wed Nov 06, 2013 6:30 pm
by greenya
Next Lime version will be released sooner than Irrlicht 1.9. But not this week for sure, more likely 1-2 weeks later.

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

Posted: Wed Nov 06, 2013 7:32 pm
by NemoStein
I'm looking forward to it...

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

Posted: Fri Nov 15, 2013 1:38 am
by cra0kalo
I will be posting my winform viewport control which lets the user interact with irrlicht through a class I wrote which inherents the control.panel class ill release it once i release the tool im working on
Looking forward to the next lime release

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

Posted: Fri Nov 15, 2013 3:53 pm
by giulioz
It's not possible to inherit MeshLoader, is this a bug? How do I create a custom MeshLoader?
Thank you :)