Projective Textures and Decals

From NeoAxis Engine Wiki

Jump to: navigation, search

Work in progress

Please add any reference material you know about here, just a link a short description or whatever you can manage

  • At the end for example, under Suggestions



Contents

Background

  • Many people seem to want selector rings which are on the ground around a unit for their projects/games.
  • I want them (mrexcessive)


  • However, it is not sufficient
  • to use a light linked to a unit and projecting downwards because it will be shadowed by the unit and also light the unit from above
  • to create a billboard because even if it is aligned with its normal parallel to the terrain normal at the unit's position it will still potentially be cut off under local terrain changes and not be displayed on ingame objects e.g. steps
  • to create something purely on the terrain, because of e.g. steps
  • it may not be easy... all input welcome, this means You!



Reference material

Forum threads

  • How to create a game effect like this using NeoAxis



  • Moving Decals
    • http://www.neoaxisgroup.com/phpBB2/viewtopic.php?t=1715
    • Has a useable workaround using particles (not projective)
    • Betauser says (in the forum)
      • Decals can't moving in realtime. Decals is always static.
      • Better way to create a new special type for your task.
      • You need create entity with dynamic geometry.
      • As example of making dynamic geometry you can see decals source code and yellow blinking panel (See panel above mirror in the RenderDemo).
    • Does anyone understand how to do these things... I (mrexcessive) looked at the blink panel code (GameEntities/BlinkGrid.cs, I think) but don't claim to understand it yet.



Other wiki pages

Websites (external to NeoAxis)

  • The OGRE3D intermediate tutorial 6 - which seems to be
  • a) exactly what we want, or close to it
  • b) using OGRE (which underlies NeoAxis) so it should be possible
  • If someone can describe or indeed complete a NeoAxis version of the essence of this tutorial, then, well, they'll be at least worthy of a big High Five!



Step zero: How to create a decal projection without firing a bullet

Decals are normally created when a bullet hits something

  • The code in GameEntities/DecalCreator.cs is normally invoked by a chain of events
    • A Bullet.cs collides with something and 'dies'
    • Dynamic.cs contains code which creates the objects listed in the type
      • For example if you look in SDK\Game\Bin\Data\Types\Bullets\ShotgunBullet\ShotgunBullet.type

you will find

	dieObjects
	{
		particle
		{
			particleName = ShotgunBulletHitParticle
		}
		sound
		{
			soundName = Types/Bullets/ShotgunBullet/Die.ogg
			volume = 0.5
		}
		mapObject
		{
			type = DefaultBulletDecalCreator
		}
	}

However, we don't want to fire bullets at players feet to create selection markers...

  • So we need another way to invoke a DecalCreator (we are experimenting with Decals as they exist already for now



I created some 'naive' code to do this... and failed miserably until I asked in the forums

See http://www.neoaxisgroup.com/phpBB2/viewtopic.php?t=2831 to follow our discussion

After considerable encouragement, and a lot of help from Wellu, we have the following starting point created by him :

  • This post is on page 3 of the forum conversation just above the large 'decals_on_group.JPG' picture, posted by Wellu.
  • The code as it stands here needs to be put into the Game project source code file ActionGameWindow.cs into the OnKeyDown event handler (at approximately line 151, just after the closing } from the block dealing with F7
           //decal practise in "protected override bool OnKeyDown(KeyEvent e)" 
           if (e.Key == EKeys.O) //key "o" was pressed 
           { 
               //create a DecalCreator from the DefaultBulletDecalCreator.type 
               DecalCreator dc = Entities.Instance.Create(EntityTypes.Instance.GetByName("ZombieBulletDecalCreator"), Map.Instance) as DecalCreator; 
               if (dc != null) // it went ok 
               { 
                   //this DecalCreator creates directional decals as it is set to do so in the .type 
                   //this means decals appear on StaticMesh located in DecalCreators position 
                   //it shoots a Ray to it's own direction to find the spot for decals. You can see this in DecalCreator.cs -> CreateDecals() 
                   //create decals in same direction my character points at 
                   dc.Rotation = GetPlayerUnit().Rotation; 
                   //set location to player for now 
                   dc.Position = GetPlayerUnit().Position; 
                   //get the Ray from Unit.Position downwards at least as long as CharacterType.Height 
                   Character chr = GetPlayerUnit() as Character; 
                   float height = chr.Type.Height; 
                   Ray floorLocator = new Ray(GetPlayerUnit().Position, new Vec3(0, 0, -height * 1.5f)); 
                   //get the piercing results if the ray hit a anything. This time it's piercing so many results!!! 
                   RayCastResult[] results = PhysicsWorld.Instance.RayCastPiercing(floorLocator, (int)ContactGroup.CastAll); 
                   foreach(RayCastResult res in results) 
                   { 
                       //if it's the unit self continue 
                       Body body = res.Shape.Body; 
                       if (MapSystemWorld.GetMapObjectByBody(body) == GetPlayerUnit()) continue; 
                       //we hit something else. Ask DecalCreator to create Decals on that location 
                       dc.Position = res.Position; //DecalCreator.cs has logic to create decals at this location 
                       //let's put this baby on the map and it will die when it's LifeTime goes to zero 
                       dc.PostCreate(); 
                       //Let's create only on one place so break here 
                       break; 
                   } 
               } 
           } 
  • When you press the "O" key then zombievomit (no really) will appear under your feet. Select the third-person camera and walk along pressing O... a trail of splats
  • Now obviously the behaviour of the zombievomit is not appropriate for a selection ring, there's the smell apart from anything else.
  • So Next we will try this code out with our new SelectionRingCreator class



Step one: Adding a SelectionRing and SelectionRingManager class to your application

Step by step in Visual Studio (2008)

  • Create the two new classes in GameEntities
    • right click on GameEntities, Add, Code File and type in name SelectionRing.cs and then SelectionRingManager.cs
I have uploaded a new version (01mar09A) of the SelectionRing.cs and SelectionRingManager.cs (http://www.neoaxisgroup.com/phpBB2/download.php?id=751)
These belong in the SDK\Game\Src\GameEntities directory, then build GameEntities

A selection ring highmaterial

This is simple and _very_ programmer art - so improvements from someone with art talents would be gratefully received and credited of course, download http://www.neoaxisgroup.com/phpBB2/download.php?id=752 and add this to the SDK\Game\Bin\Data\Types directory
  • All that remains is to modify ActionGameWindow.cs so that it invokes the new class SelectionRing

Of course I will get this working directly from the logic editor - I think that will not be too hard now

Add this after the check for EKeys.F7
 else if (e.Key == EKeys.O)      //  press "O" for SelectionRing
 {
   //create a SelectionRingCreator from the SimpleSelectionRingCreator.type 
   Unit unitPlayer = GetPlayerUnit() as Unit;
   SelectionRingManager.AttachSelectionRingTo(unitPlayer);
 }
 else if (e.Key == EKeys.P)      // press "P" to remove SelectionRing
 {
   Unit unitPlayer = GetPlayerUnit() as Unit;
   SelectionRingManager.RemoveSelectionRingsFrom(unitPlayer);
 }
  1. Start the game.
  2. When you press O a selection ring appears under your feet, view in third person camera (F7) to see clearly, but can just look down at your feet
  3. Move around
  4. Press P to hide it

SelectionRingView.png



Step two: How to create a simple projection which follows a new type of unit entity

Requirements

  • How we might isolate gameplay elements (such as timeouts on heals etc.) from the core functionality (projecting a coloured ring, changing the colour, hiding it again, not filling up all space with coloured rings... etc. etc.)


It is starting to look as though some of these requirements have been satisfied by the previous step... a refactoring of SelectionRingManager and SelectionRing will tell... more later



Step three: Units and Players

The current implementation of SelectionRingManager is starting to support the Unit generally as well as Player.



Step four: Decorative enhancements

  • Variable colours
  • Rotation
  • Embedded particle systems
  • an apparent effect, coordinating with rotation/colour




Step five: Beyond simple selection

Consider how and why these might be used on a client

  • To indicate a target unit of an action
  • To indicate an active 'over time' effect on a unit
  • To indicate that the player has been targetted by an AI/some other in-game entity
  • Priority, stacking, single or multiple



Server model

  • discussion only until networking examples from betauser in .60 release
  • This probably belongs in a different wiki page...
    • Maintaining a stack of effects on a unit (e.g. stacked heals/damage over time/self-buffs/group-buffs/area-debuffs)
    • Managing timeouts of each effect
    • Resolving which effect should receive the priority in display for all clients
      • Excepting a particular client may override this, e.g. if the unit in question is selected by that client's player
  • Perhaps an example healing system with simple server modelling of units being healed and client decisions about display only and interaction with unit selection



Authors

wellu for the 'creatable decals' code on which all is based
mrexcessive layout and SelectionRingManager, SelectionRing classes

Credits

Kudos to Wellu who has patiently explained things to me and provided example code.

Suggestions area

  • If you don't want to spend time editing the wiki,
but you have a great idea or some feedback,
then please email me mrexcessive _at_no_spam_at gmail _dot_ com or just add your comments and ideas here