Decal cursor in MET. [Solved]

Chulein

28-11-2008 08:02:30

Hi guys.

Im experimenting with ogre and building a kind of map editor application.
I found an example og decal projection of the cursor to the Ogre C++ ETM.

http://www.ogre3d.org/phpBB2addons/view ... sc&start=0

I didnt find a C# version of this and was wondering if anyone has got this decal projection to work with MET for Mogre?



Thanks.

Chulein

Bostich

28-11-2008 16:59:04

Hello Chulein,

This should do the trick ;)


using System;
using System.Collections.Generic;
using System.Text;
using Mogre;
#region - DecalCursorClass -
/// <summary>
/// This class represents a decal cursor.
/// </summary>
public class DecalCursor
{
const float METER_SCALE = 1.0f;

#region - Properties -
#region - Size -
Vector2 m_Size;
/// <summary>
/// Size of the DecalCursor
/// </summary>
public Vector2 Size
{
set { }
get { return m_Size; }
}
#endregion

#region - Position -
Vector3 m_Pos;
/// <summary>
/// Position of the Decal
/// </summary>
public Vector3 Position
{
set
{
m_Pos = value;
if (this.ProjectionNode != null)
this.ProjectionNode.SetPosition(m_Pos.x, m_Pos.y + (10.0f * METER_SCALE), m_Pos.z);
}
get { return m_Pos; }
}
#endregion

#region - TextureName -
string m_TexName;
/// <summary>
/// Texture to apply
/// </summary>
public string TextureName
{
set { m_TexName = value; }
get { return m_TexName; }
}
#endregion

#region - ProjectionNode -
SceneNode m_NodeProj;
/// <summary>
/// The Projection Node.
/// </summary>
public SceneNode ProjectionNode
{
set { m_NodeProj = value; }
get { return m_NodeProj; }
}
#endregion

#region - ProjectionFrustum -
Frustum m_FrustProj;
/// <summary>
/// the projection frustum
/// </summary>
public Frustum ProjectionFrustum
{
set { m_FrustProj = value; }
get { return m_FrustProj; }
}
#endregion

#region - TextureState -
TextureUnitState m_TexState;
/// <summary>
/// pointer to the texture unit state in the pass
/// </summary>
public TextureUnitState TextureState
{
set { m_TexState = value; }
get { return m_TexState; }
}
#endregion

#region - Pass -
Pass m_Pass;
/// <summary>
/// pointer to the decal pass
/// </summary>
public Pass Pass
{
set { m_Pass = value; }
get { return m_Pass; }
}
#endregion

#region - TerrainMaterial -
MaterialPtr m_TerrainMat;
/// <summary>
/// sharedptr to the terrain material
/// </summary>
public MaterialPtr TerrainMaterial
{
set { m_TerrainMat = value; }
get { return m_TerrainMat; }
}
#endregion

#region - SceneManager -
SceneManager m_SceneMgr;
/// <summary>
/// Pointer to the application's Mogre.SceneManager
/// </summary>
SceneManager SceneManager
{
set { m_SceneMgr = value; }
get { return m_SceneMgr; }
}
#endregion

#region - IsVisible -
bool m_IsVisible;
/// <summary>
/// true if the decal visible, otherwise false
/// </summary>
public bool IsVisible
{
set { m_IsVisible = value; }
get { return m_IsVisible; }
}
#endregion

#endregion

#region - Constructor, Desturctor -
/// <summary>
/// Standard Constructor. Sets the necessaty values, an inits the Cursor.
/// </summary>
/// <param name="SceneManager"></param>
/// <param name="TerrainMaterial"></param>
/// <param name="Size"></param>
/// <param name="TextureName"></param>
public DecalCursor(SceneManager SceneManager, MaterialPtr TerrainMaterial,
Vector2 Size, String TextureName, bool UnSelectable)
{
this.IsVisible = false;
this.SceneManager = SceneManager;
this.TerrainMaterial = TerrainMaterial;
this.Position = Vector3.ZERO;
this.Size = Vector2.ZERO;
this.Init(Size, TextureName, UnSelectable);
}
~DecalCursor()
{
this.Hide();
if (this.Pass != null)
{
//this.TerrainMaterial.GetBestTechnique(0).RemovePass(this.Pass.Index);
this.Pass.Dispose();
}
//delete Frustum
this.ProjectionNode.DetachAllObjects();
this.ProjectionFrustum.Dispose();
//destroy Node
this.ProjectionNode.ParentSceneNode.RemoveAndDestroyChild(this.ProjectionNode.Name);
}
#endregion

#region - Public Methods -

#region - SetSize -
public void SetSize(Vector2 Size)
{
if (m_Size != Size)
{
m_Size = Size;
this.ProjectionFrustum.AspectRatio = m_Size.x / m_Size.y;

//set fovy so that tan = 1, so 45 degree
this.ProjectionFrustum.FOVy = new Degree(45);
//set near clip plane according to fovy
this.ProjectionFrustum.NearClipDistance = m_Size.y;
}
}
#endregion

#region - Show -
/// <summary>
/// Show the Cursor!
/// </summary>
public void Show()
{
if (!this.IsVisible)
{
this.IsVisible = true;
this.ShowTerrainDecal();
this.Position = m_Pos;
}
}
#endregion

#region - Hide -
/// <summary>
/// Hides the Cursor!
/// </summary>
public void Hide()
{
if (this.IsVisible)
{
this.IsVisible = false;
HideTerrainDecal();
}
}
#endregion

#endregion

#region - Private Methods -

#region - Init -
/// <summary>
/// Initialize the DecalCursor.
/// </summary>
/// <param name="Size">Size of the Cursor.</param>
/// <param name="TextureName">The Texturename of the Texture, used by this Cursor</param>
private void Init(Vector2 Size, String TextureName, bool UnSelectable)
{
//create a new pass int the Material to render Decal.
this.Pass = this.TerrainMaterial.GetTechnique(0).GetPass("Decal");
if (this.Pass == null)
{
Technique techPref = this.TerrainMaterial.GetTechnique(0);
this.Pass = techPref.CreatePass();
this.Pass.Name = "Decal";
this.Pass.LightingEnabled = false;
this.Pass.SetSceneBlending(SceneBlendType.SBT_TRANSPARENT_ALPHA);
this.Pass.SetDepthBias(2.5f, 2.5f);
this.Pass.SetFog(true);
this.Pass.CreateTextureUnitState("decalBase.png");
}

//Init projective decal
//set up the main decal prjection frustum
this.ProjectionFrustum = new Frustum();
this.ProjectionNode = this.SceneManager.RootSceneNode.CreateChildSceneNode();
this.ProjectionNode.AttachObject(this.ProjectionFrustum);
this.ProjectionFrustum.ProjectionType = ProjectionType.PT_ORTHOGRAPHIC;
this.ProjectionNode.Orientation = new Quaternion(new Degree(90), Vector3.UNIT_X);

if (UnSelectable)
this.ProjectionFrustum.QueryFlags = 0;

SetSize(Size);
//Texture to apply
this.TextureName = TextureName;
//load the images for the decal and the filter
TextureManager.Singleton.Load(this.TextureName, "ET", TextureType.TEX_TYPE_2D, 1);
this.IsVisible = false;
}
#endregion

#region - ShowTerrainDecal -
/// <summary>
///
/// </summary>
private void ShowTerrainDecal()
{
if (this.TextureState == null)
{
//set up the decal's texture unit
this.TextureState = this.Pass.CreateTextureUnitState(this.TextureName);
this.TextureState.SetProjectiveTexturing(true, this.ProjectionFrustum);
this.TextureState.SetTextureAddressingMode(TextureUnitState.TextureAddressingMode.TAM_CLAMP);
this.TextureState.SetTextureFiltering(FilterOptions.FO_POINT, FilterOptions.FO_LINEAR, FilterOptions.FO_NONE);
this.TextureState.SetAlphaOperation(LayerBlendOperationEx.LBX_ADD);
}
}
#endregion

#region - HideTerrainDecal -
/// <summary>
///
/// </summary>
private void HideTerrainDecal()
{
if (this.TextureState != null)
{
this.Pass.RemoveTextureUnitState(this.Pass.GetTextureUnitStateIndex(this.TextureState));
this.TextureState = null;
}
}
#endregion
#endregion
}
#endregion



Bostich

Chulein

02-12-2008 08:58:53

Yes!
Thank you Bostich.

Im still having some problems though. in addition to the working decal there is a static decal texture over the whole terrain, more like it was one of the splattings.

take a loookie.



do you know what im doing wrong.?


Chulein

Bostich

04-12-2008 13:57:06

Hi Chulein,

i'am sorry, but i'am not sure what kind of problem you have :oops: .

Can you show some code or be more specific?

Bostich

Chulein

04-12-2008 14:53:02

Hey Bostich

im using your class code above for the decal. and using it like this:



terrainManager = new MET.TerrainManager(sceneManager,"terr1");
terrainManager.SetLodErrorMargin(1, (uint)viewport.ActualHeight);
terrainManager.SetUseLodMorphing(false, 0.1f, "morphFactor");


float[] hm = new float[1025 * 1025];
for (int i = 0; i < 1025 * 1025; i++)
hm[i] = 0.5f;
terrainInfo = new MET.TerrainInfo(1025, 1025, hm);



Mogre.MaterialPtr material = Mogre.MaterialManager.Singleton.GetByName("ETTerrainMaterial");
decal = new DecalCursor(mgr, material, new Vector2(50, 50), "decal.png", false);


terrainInfo.Extents = new Mogre.AxisAlignedBox(0.0f, -390.0f, 0.0f, 1000, -220, 1000);

terrainManager.CreateTerrain(terrainInfo);
terrainInfo.Dispose();
terrainInfo = terrainManager.TerrainInfo;


splattingManager = new MET.SplattingManager("ETSplatting", "ET", 1025, 1025, 3);
splattingManager.NumTextures = 6;

terrainManager.Material = material;

loadBrush(0);//Standard Brush.
loadTexture(2);//Standard Paint



The problem is that a a decal texture projects 1:1 on the terrain as well as the one that follows the cursor.. I cant get that one to disappear. its either both or none.


Thank you Bostich for helping me out.




[edit] btw.. i havent touched anything on the material files ETTerrainMaterial and the shaders that followed MET.

Bostich

04-12-2008 16:39:06

Hi Chulein,

coz iam really out of source (long time no use of mogre :P ) here is my entire et class:


public class ETTerrain
{
float m_PaintStrength;
public float PaintStrength
{
set { m_PaintStrength = value; }
get { return m_PaintStrength; }
}
static ETTerrain m_Instance;
public static ETTerrain Instance
{
set { m_Instance = value; }
get { return m_Instance; }
}
TerrainManager m_TerrainManager;
TerrainInfo m_TerrainInfo;
public TerrainInfo TerrainInfo
{
set { }
get { return m_TerrainInfo; }
}
SplattingManager m_SplattingManager;
Brush m_PaintBrush;
SceneManager m_SceneManager;

DecalCursor m_TerrainCursor;
public DecalCursor TerrainCursor
{
set { }
get { return m_TerrainCursor; }
}
Viewport m_Viewport;
Vector2 m_TerrainCursorSize;
float[] m_TerrainData;
MaterialPtr m_TerrainMaterial;
MaterialPtr m_TerrainCursorMaterial;
Image m_Image;
bool m_Init;
uint m_CurrentTexture;
public uint CurrentTexture
{
set { m_CurrentTexture = value; }
get { return m_CurrentTexture; }
}
bool m_Deform;
public bool Deform
{
set { m_Deform = value; }
get { return m_Deform; }
}
bool m_LeftDown;
public bool LeftDown
{
set { m_LeftDown = value; }
get { return m_LeftDown; }
}
bool m_DoPaint;
public bool DoPaint
{
set { m_DoPaint = value; }
get { return m_DoPaint; }
}
bool m_RightDown;
public bool RightDown
{
set { m_RightDown = value; }
get { return m_RightDown; }
}
public ETTerrain(SceneManager SceneManager, Viewport Viewport, Vector2 TerrainCursorSize, float[] TerrainData)
{
if (Instance == null)
Instance = this;
m_SceneManager = SceneManager;
m_Viewport = Viewport;
m_TerrainCursorSize = TerrainCursorSize;
m_TerrainManager = new TerrainManager(m_SceneManager, "TerrainManager");
m_TerrainData = TerrainData;
Init();
}
private void Init()
{
m_TerrainManager.SetLodErrorMargin(2, (uint)m_Viewport.ActualHeight);
m_TerrainManager.SetUseLodMorphing(true, 0.2f, "morphFactor");
if (m_TerrainData == null)
{
m_TerrainData = new float[1025 * 1025];
for (int i = 0; i < 1025 * 1025; i++)
m_TerrainData[i] = 0.5f;
}

m_TerrainInfo = new TerrainInfo(1025, 1025, m_TerrainData);
m_TerrainInfo.Extents = new AxisAlignedBox(0, 0, 0, 4000, 513, 4000);
m_TerrainManager.CreateTerrain(m_TerrainInfo, 33, 255, false, false);
m_TerrainInfo.Dispose();
m_TerrainInfo = m_TerrainManager.TerrainInfo;
m_SplattingManager = new SplattingManager("ETSplatting", "ET", 512, 512, 3);
m_SplattingManager.NumTextures = 6;
m_TerrainMaterial = MaterialManager.Singleton.GetByName("ETTerrainMaterial");
m_TerrainManager.Material = m_TerrainMaterial;
m_TerrainCursor = new DecalCursor(m_SceneManager, m_TerrainMaterial, new Vector2(50, 50),
"decal.png",
true);
m_TerrainCursor.Show();
m_Image = new Image();
m_Image.Load("brush.png", "ET");
m_Image.Resize(16, 16);
m_PaintBrush = Brush.LoadBrushFromImage(m_Image);
m_PaintStrength = 1.0f;
m_Init = true;
}

public void Update(Vector3 MousePosition)
{
if (!m_Init)
return;
float delta = Timer.Delta();
if (Deform && LeftDown || Deform && RightDown)
{
float intens = delta * 0.2f * ((this.LeftDown) ? 1.0f : -1.0f);
int x = m_TerrainInfo.PosToVertexX(MousePosition.x);
int z = m_TerrainInfo.PosToVertexX(MousePosition.z);
m_TerrainManager.Deform(x, z, m_PaintBrush, intens);
}
else if (DoPaint && LeftDown || DoPaint && RightDown)
{
float intens = delta * 3f * ((this.RightDown) ? 1.0f : -1.0f);
int x = m_TerrainInfo.PosToVertexX(MousePosition.x);
int z = m_TerrainInfo.PosToVertexX(MousePosition.z);
m_SplattingManager.Paint(this.CurrentTexture, x, z, m_PaintBrush);
m_SplattingManager.Paint(this.CurrentTexture, x, z, m_PaintBrush, PaintStrength);
}
}
public System.Drawing.Bitmap GetBitmap(int Index)
{
TexturePtr ptr;
ptr = m_TerrainMaterial.GetTechnique(0).GetPass(0).GetTextureUnitState((ushort)Index)._getTexturePtr();
return MogreUtils.Converter.TexturePtrToBitmap(ptr, "png", "ET");
}
public List<System.Drawing.Bitmap> GetKnownBitmaps()
{
TexturePtr mTexPtr;
List<System.Drawing.Bitmap> mTemp = new List<System.Drawing.Bitmap>();
uint mTexAmount = m_SplattingManager.NumTextures;
for (int i = 0; i < (int)mTexAmount; i++)
{
ushort index = (ushort)(i + 2);
mTexPtr = m_TerrainMaterial.GetTechnique(0).GetPass(0).GetTextureUnitState(index)._getTexturePtr();
mTemp.Add(Converter.TexturePtrToBitmap(mTexPtr, "png", "ET"));
}
return mTemp;
}

public void Dispose()
{
m_SplattingManager.Dispose();
m_PaintBrush.Dispose();
m_TerrainInfo.Dispose();
m_TerrainManager.Dispose();
m_TerrainMaterial.Dispose();
m_Image.Dispose();
m_TerrainCursor = null;
}
}


this is maybe also usefuel for you:


public class Converter
{
/// <summary>
/// Converts an Ogre image to System.Drawing.Bitmap.
/// </summary>
/// <param name="img">Mogre.Image to convert</param>
/// <returns>System.Drawing.Bitmap</returns>
public static Bitmap MogreImageToBitmap(Mogre.Image img)
{
Bitmap bmp = new Bitmap((int)img.Width, (int)img.Height);
for (int x = 0; x < bmp.Width; x++)
{
for (int y = 0; y < bmp.Height; y++)
{
Mogre.ColourValue color = img.GetColourAt(x, y, 0);
bmp.SetPixel(x, y, Color.FromArgb((int)color.GetAsARGB()));
}
}

return bmp;
}
/// <summary>
/// Converts an TexturePtr to an System.Drawing.Bitmap
/// </summary>
/// <param name="TexturePtr">Valid TexturePtr</param>
/// <param name="BitmapType">eg: PNG</param>
/// <param name="GroupName">the group where Mogre will find the image.</param>
/// <returns>System.Drawin.Bitmap</returns>
public static Bitmap TexturePtrToBitmap(Mogre.TexturePtr TexturePtr, String BitmapType, String GroupName)
{
Mogre.Image img = new Mogre.Image();
Mogre.DataStreamPtr dPtr = null;
String name = TexturePtr.Name;
if (TexturePtr.Name.StartsWith(GroupName))
name = TexturePtr.Name.Replace(GroupName, "");
if (name.Contains(".png"))
name = name.Replace(".png","");
try
{
dPtr = Mogre.ResourceGroupManager.Singleton.OpenResource(name + "." + BitmapType, GroupName);
}
catch
{
throw new Exception("Bitmap not found, or wrong image type.");
}
img.Load(dPtr, BitmapType);
return MogreImageToBitmap(img);
}
}


I'am sorry that some code is uncommented, but this was never finished. but the decal cursor was workin fine for me!

hope that helps a bit. if you have any further question, feel free to ask.


bostich

Chulein

08-12-2008 11:49:47

I finally figured it out.. I used the same decal for the decalBase.png and the main decal. :oops: After creating a 2px * 2px transparent .png for decalbase everything works great...


Thanks Bostich for the help!


Peace

Chulein