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);
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
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
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.
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
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?
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