XML:ONLV: Difference between revisions

From OniGalore
Jump to navigation Jump to search
No edit summary
m (adding exported ENVP, deleting akev notes)
Line 1,204: Line 1,204:
|-
|-
| <ENVP id="...">
| <ENVP id="...">
|
| integer
|
| Instance Id.
|-
|-
| <Particles>
| <Particles>
|
| -
|
| This is an int16 array for the <ENVPParticle> tags. If there's no content <Particles /> is used.
|-
|-
| <ENVPParticle>
| <ENVPParticle>
|
| -
|
|
|-
|-
| <Class>
| <Class>
|
| char[64]
|
| <font color="#777777">BINA3RAP</font>file<font color="#777777">.oni</font> <font color="#777777">(don't use file prefix/suffix)</font>
|-
|-
| <Tag>
| <Tag>
|
| char[48]
|
| particle's name for BSL commands, see [[OFGA#tags|OFGA]] for more information on name composition
|-
|-
| <Transform>
| <Transform>
|
| matrix
| the last 3 values are the position (x, y, z)
| Float 3*3 + 3 more float for X Y Z position of the particle. For more information on the matrix see [[OBD:CRSA]].
|-
|-
| <DecalScale>
| <DecalScale>
|
| int32, int32
|
| X Y
|-
|-
| <Flags>
|valign="top"| <Flags>
|
|valign="top"| flag
|
|  
: None
: None
: NotInitiallyCreated  
: NotInitiallyCreated  
Line 1,351: Line 1,351:
: Read on [[XML:M3GM#PNTA|HERE]].
: Read on [[XML:M3GM#PNTA|HERE]].
|}
|}
==temporary AKEV notes==
This goes later to XML:AKEV
'''(Copied from hex page. Is this still up to date ?)'''
;Triangles
:Many quads are in fact triangles: the last two vertices have the same [[OBD:PNTA|PNTA]] and [[OBD:TXCA|TXCA]] entries, and the ARGB color is (255, 205, 205, 205) (80% gray, 100% opaque). There is also a flag specifying that.
;Ghost, StairsUp, StairsDown
:These flags are used for BNV adjacencies, see [[AKAA]]. Stairs up/down are used instead of Ghost when the quad is placed at the bottom/top of the stairs. These quads are not visibile. The script variable env_show_ghostgqs is intended to control the visibility of such quads but it requires "debug" level files.
:There are a couple of ghost quads that aren't referenced from [[AKAA]]. It's likely that those quads are useless.
;DoorFrame
:This appears to be another type of "ghost" quad (its visibility is controlled by the same env_show_ghostgqs variable). Sometimes it is used together with the Ghost flag but not always. Only the door frames that also have the Ghost flag are used as adjacencies so it's unclear if the rest of the door frames serve any purpose. In fact it appears that this flag has no effect other than making the quad invisible.
;Stairs
:This is applied to the invisible ramp quad that covers the stairs. In general this flag is also applied to the visible stairs geometry but there are some exceptions (errors? see level 19 stairs).
;NoOcclusion
:This flag tells the octtree raycaster to ignore the quad when doing ray/quad intersections. This is tipically used for small quads that are unlikely to affect the overall environment visibility.
;ProjectionBit
:These 2 flags can be 00, 01, 10 and 11. That means the values 0,1,2 and 3 which have the following meanings:
:*0 - No projection plane specified. One can be computed if needed. Never used in files, may slow down the game if used.
:*1 - Project quad on XY plane.
:*2 - Project quad on XZ plane.
:*3 - Project quad on YZ plane.
:The projection plane is used to determine if a point is in a quad (this point is usually the result of an intersection between a ray and the quad plane).
;GridIgnore
:Appears to be unused. Its likely purpose is to mark quads that don't count as obstacles in the pathfinding grid.
;Danger
:Appears to be unused. Its likely purpose is to create danger areas in the pathfinding grids. Usually there's a trigger volume nearby that hurts/kills the character. This quads are always invisible.
;Invisible
:Invisible quads have a couple of different uses:
:* block player access to some parts of the environment
:* stairs ramp
:* collision geometry (used by some "complex" furniture)
:* danger quads (see above)
:* some other apparently useless quads
;Furniture
:Set for all quads that belong to a furniture object. It doesn't appear to be used. It is also redundant since all the furniture quads have an object id.
;NoDecals
:Prevents the creation of decals on the quad. Set for door quads because the decals would disappear when the door opens. That's why shooting a door doesn't leave a mark.
;Impassable
:Probably used by forcefields and end of level boundaries (like in state archive level).





Revision as of 11:11, 30 April 2013

ONLV : Oni Game Level
XML modding tips
  • See HERE to start learning about XML modding.
  • See HERE if you are searching for information on how to handle object coordinates.
  • See HERE for some typical modding errors and their causes.
XML.png
XML

ONLD << Other file types >> ONSK

switch to OBD page

Unfinished building-60px.jpg

This page is unfinished. Can you fill in any missing information?
If it is not clear which part of the page is unfinished, ask on the talk page.

Aged parchment-60px.jpg

This page contains information that is out of date.
Please update this information to reflect where the community is at today.

Todo list
  • tips with cutscene charas: sync pelvis OBAN and partner TRAM
  • notes on camera and film import ?
  • more information / updates for exported xml files



Level releases, forum threads and wiki pages

Custom levels that have been created so far
OCF threads about level creation
Wiki pages about levels
Free texture resources


Concept phase

Be aware of limitation of level and engine.

  • triangle limit of a game level: ca. 520.000 (500.000 to be on save side)
  • when the triangles are packed too tight then the cam will look at too many of them and glitches appear: the visible GQs limit is ca. 16.000, sooner or later higher numbers will cause render bugs and call BSL message "Exceeded max visible GQs number" (you can decrease the gs_farclipplane_set value to avoid that problem)
  • characters are visible only within 4099|4099|4099 and -4099|-4099|-4099 world units
  • geometry stops at ca. X=4228|Z=4228 and -4228|-4228 (height not tested)
  • chr_debug_spheres = 1 visualizes collision spheres of characters, then you can check if they fit through a new entrance


Level import with onisplit 0.9.82.0

Demo files

Demo files can be downloaded here.

First put the new "OniSplit.exe" into the second "lab" folder alongside the xml files.

There's a "build.cmd" file. Those two are the important lines:

onisplit -create:level out lab.xml
onisplit -import:pc out level3_Final.dat

The first line create the *.oni files from a master.xml file, in this case "lab.xml". If final, the oni files can be put into a new AE package.

The second line creates level archives which can be used for fast tests. They don't require you to install a package.

Instead of "nosep" you can now also use "pc" for the import. Mac does still use "sep".

If the game crashes while loading (at ca. 5-10% progress), check if all textures were inside the "out" folder.

You can extract the AKEV file to xml, then search for the TXMP array.

"TXMP_marker_door" and "TXMP_marker_ghost" will be missing in the demo's "out" folder.

You can add this between the other two lines in the build.cmd to prevent a crash.

onisplit -create:txmp out env/markers/*.tga


The master xml file

File paths can be either absolute or relative.

The master xml file name determine the bsl folder name and the AKEV and ONLV file name in the output folder.


Mandatory files for level import:

  • level_environment.dae
  • level_bnv.dae
  • level_textures.tga/jpg
  • Character.xml or AISA with player
  • ONSK name in <Sky> (can be fake name)


XML tag content type description
<?xml version="1.0" encoding="utf-8"?> float, flag Ignore this.
<Oni> -
<Level SharedPath="..."> link The master xml file can link to other xml files, most of them are BINACJBO files. The file type gets declared inside the file, so the file name itself doesn't have to contain the type. Ergo, "BINACJBOCharacter.xml" can be given a simpler name like "Character.xml".

Some resources used by those xml files can be found in a "shared" folder. OniSplit copies textures and "physics" objects into the output folder; furniture objects will be integrate into the AKEV. Unused resources in the shared folder will be ignored. That way the final level archive / AE package contains only necessary files which saves the end-user space.

In the demo are various subfolders in shared folder: consoles, doors, furniture, triggers and turrets. Following file types comes there without their file prefixes: CONS, DOOR, TRIG, OFGA. OniSplit recognize them nonetheless.

<Environment> -
<Model> - See HERE for detailed information.
<Import Path="..."/> link
<Node Id="..."> string informative (space for notes so to say)
<ScriptId> integer Tested with BSL command ...
env_show Id 1 (use 0 to hide)
env_broken Id [Id] (if also second Id is used then objects in that range get counted e.g. 3001, 3018 = 18)
env_texswap Id texture (no file prefix/suffix allowed)
env_shade Id Id R G B
<GunkFlags> flag
AGQG (Gunk) flags (trimmed list)

see onisplit -help enums for more flags

None
NoCollision
NoObjectCollision
NoCharacterCollision
NoDecal
TwoSided
Invisible
<Rooms> - For detailed information see HERE.

For Google Sketchup BNV tutorial see HERE.

<Import Path="..."/> link File path to *.dae file. BNV data, used to create pathfinding.
<Textures> -
<Texture Name="..."> string TXMP file name to generate.
<Flags> flag Optional tag. For list of flags see HERE.
<Format> flag
BGR
RGBA
BGR555
BGRA5551
BGRA4444
<GunkFlags> flag
AGQG (Gunk) flags (trimmed list)

see onisplit -help enums for more flags

None
NoCollision
NoObjectCollision
NoCharacterCollision
NoDecal
TwoSided
Invisible
<Image> link File path to *.tga/jpg file.
<Sky> string ONSKfile.oni (without file pre- and suffix)

The import doesn't work with an empty tag. <Sky>clear</Sky> helps here; any other fictional name will also do.

For detailed information see HERE.

<Objects> -
<Import> link File path. Supported files:
Character.xml (has to contain player character if there's no AISA file with it)
Console.xml
Door.xml
Flag.xml
Furniture.xml
Neutral.xml
Particle.xml
PatrolPath.xml
Physics.xml
PowerUp.xml
Sound.xml
Trigger.xml
TriggerVolume.xml
Weapon.xml
<Films> -
<Import> link File path to *.xml file. OniSplit creates a FILM file from it. Used for characters in cutscenes.
<Cameras> -
<Camera Path="..."> link File path to *.dae file. OniSplit creates an OBAN file from it. Used for cutscenes.
<Animation Name="..."/> string Name for the OBAN file.


This is a trimmed version of the master file "lab.xml" from the demo. It's meant to give you a first impression. -- We might upload a smaller demo someday with all features nonetheless.

<?xml version="1.0" encoding="utf-8" ?>
<Oni>
   <Level SharedPath="../shared">
       <Environment>
           <Model>
               <Import Path="env/lab_env.dae"/>
               <Import Path="env/lab_bomber_window.dae"/>
               <Import Path="env/lab_motorcycle.dae">
                   <Node Id="motorcycle">
                       <ScriptId>9</ScriptId>
                       <GunkFlags>NoCollision</GunkFlags>
                   </Node>
               </Import>
           </Model>
           <Rooms>
               <Import Path="env/lab_bnv.dae"/>
           </Rooms>
           <Textures>
               <Texture Name="GOO">
                   <Format>bgra4444</Format>
                   <GunkFlags>NoCollision</GunkFlags>
                   <Image>env/images/GOO.tga</Image>
               </Texture>
           </Textures>
       </Environment>
       <Sky>sunset</Sky>
       <Objects>
           <Import>Character.xml</Import>
           <Import>Furniture.xml</Import>
           <Import>TriggerVolume.xml</Import>
           <Import>Physics.xml</Import>
       </Objects>
       <Films>
           <Import>films/BomberKonRun01.xml</Import>
           <Import>films/BomberKonRun02.xml</Import>
       </Films>
       <Cameras>
           <Camera Path="cameras/BomberCam01.dae">
               <Animation Name="BomberCam01"/>
           </Camera>
           <Camera Path="cameras/BomberCam02.dae">
               <Animation Name="BomberCam02"/>
           </Camera>
       </Cameras>
   </Level>
</Oni>


<Model>

This tag is mandatory (it must be present to avoid errors); the model section contains one import path to the AKEV (level) geometry (*.dae) and can contain additional import paths for exceptions (*.dae).

Data from the demo:

               <Import Path="env/lab_env.dae"/>
               <Import Path="env/lab_motorcycle.dae">
                   <Node Id="motorcycle">
                       <ScriptId>9</ScriptId>
                       <GunkFlags>NoCollision</GunkFlags>
                   </Node>
               </Import>

The motorcycle has here script id 9. You can show and hide the object with bsl command env_show whereby the second parameter means true or false.

env_show 9 1
env_show 9 0


EdT demonstrates here env_show. The objects have collision.


The last original level (syndicate mountain compound) has a big satellite dish platform that can be made hidden. Obviously, such objects/areas can be made to have pathfinding too.


More possible applications of env_show
  • grids in front of ventilation shafts (a little door object could be an alternative)
  • ground/ceiling/objects for cutscenes that become partially destroyed
  • destrucable walls like in Deus Ex 3 (trigger volume, replacing punch anim with punch-through-wall anim)


Breakable glass with BSL recognition

Broken env objects can be recognized by bsl command env_broken (ID_1, ID_N). However, this whole thing requires additional code to work.

An example is the training level. Let's determine how we can set up such a thing.

First we need a trigger volume like in level 1.

       <TRGV Id="11495">
           <Header>
               <Flags>Locked</Flags>
               <Position>-714.6615 -298 -555.2073</Position>
               <Rotation>0 0 0</Rotation>
           </Header>
           <OSD>
               <Name>tv75</Name>
               <Scripts>
                   <Entry></Entry>
                   <Inside>targets_gone</Inside>
                   <Exit></Exit>
               </Scripts>
               <Teams>255</Teams>
               <Size>400 31 270</Size>
               <TriggerVolumeId>75</TriggerVolumeId>
               <ParentId>0</ParentId>
               <Notes></Notes>
               <Flags>PlayerOnly</Flags>
           </OSD>
       </TRGV>

Now we need some BSL code.

var int inside_target_function;

func void enter_target_function(void)
{
   dprint enter_target_function
   inside_target_function = 1;
}

func void exit_target_function(void)
{
   dprint exit_target_function
   inside_target_function = 0;
}

func void targets_are_not_gone(void)
{
	# CB: turn off the trigger volume and sleep for a second
	# so as not to cause hideous performance loss
	trigvolume_enable tv75 0
	sleep 60
	trigvolume_enable tv75 1
}

func void targets_gone(string ai_name)
{
	if(inside_target_function eq 0)
	{	
		enter_target_function() # catch other "targets_gone" functions to let them do nothing

		var int num_broken = env_broken(3001, 3018);
		# if you only one target use scheme: env_broke(3001, 3001)

		if (num_broken eq 18)
		{
			targets_are_gone();
		}
	
		if (num_broken < 18)
		{
			targets_are_not_gone(); # to set check interval to one second
		}

		exit_target_function
	}
}

func targets_are_gone
{
	trigvolume_enable tv75 0
	# [...]
}
Explanation

Player enters the TV, "targets_gone" gets triggered. The variable "inside_target_function" should be 0 be default, so we are entering now the first if statement. Next, we can assume that the player didn't destroy all glass objects, so "num_broken" will be less than 18: "targets_are_not_gone" gets called.

The TV function "targets_gone" would be triggered every frame but "targets_are_not_gone" increases the pause between checks: The TV gets deactivated for 60 frames. Then the TV becomes enabled again and will start anew until all glass objects got destroyed or player left the TV.

Unnecessary "targets_gone" functions will do nothing because "inside_target_function" was set to 1 by the first one.

"targets_are_gone" eventually disables the TV to prevent memory overflow, the function contains also all things "[...]" that you want to happen after the glass target broke.


Texture exchange

BSL command supported by PC and Mac:

env_texswap ID texture

Might be useful to switch on/off static and animated textures. (News screen: running or off or smashed. Lava stream: flowing or stagnating or cooled down. Etc.)


Vertex coloring

Observation: The sniper tower from level 19 Syndicate Mountain Compound can be isolated and re-imported as it is. It will appear quite dark.

If we remove "_color" from the object the shadows will be gone next time we import the tower.

Mod Tool: Explorer [8]

Object
 |
 +-- Polygon Mesh
       |
       +-- Cluster
             |
             +-- Polygon
             |     |
             |     +-- [...]
             |
             +-- NodeProperties
                   |
                   +-- _color
                   +-- texcoord (Explicit UVWs)
                         |
                         +-- Vertex_Color_Def

So, how do we modify that data?


Single object shading

If there's already a vertex color property you can use Shift + W to activate "Paint Vertex Color Tool". With Control + W you can change the brush color. R + Hold Click + Move Mouse let you change the Brush size. The more vertices (points) you have the more detailed you can make the shadows/colors. But keep in mind that too many polygons can destroy collision which make characters fall through the ground.

If there's no vertex color property the first use of Shift + W will create that property. But you can also manually create it via Property > Color at Vertices Map.

Here you can see one of my early attempts of vertex coloring. --paradox-01 (talk) 18:18, 16 March 2013 (CET)


Level-wide shading

light_test_modtool_tn_zps9a3a3f2e.png

light_test_ingame_tn_zps967c06a9.png

To get a general shading/lightning you can set up light sources. "Infinite" lights are useful as global lighting while "Light Box", "Point", "Neon" and "Spot" are more suitable as local light sources. They can be accessed via Primitives > Light.

By default a Mod Tool scene has one Infinite light but it doesn't shine in every direction so you might want to add more Infinite lights. Let's say one Infinite light for each direction (+X, -X, +Y, -Y, +Z, -Z) with an intensity of circa 0.25 (night) or 0.75 (day).

The illumination of those lights can be integrated into the vertex color property. There's some information at OCF, the quoted information is somewhat triple so don't get confused by it: at first detailed, then summarized, then a checklist.

Basically you can go with the checklist:

  • Property > Color At Vertices Map
  • Property > Render Map
  • In render map property page, under Sampling select Vertices Only
  • Under Surface Color choose Enable, then in the box below select Vertex _Color, if that option does not appear click on the New button next to it.
  • Under Map select Illumination only
  • Finally, click on the button Regenerate Maps...

This must be done for all objects separately.

There's a script which can apply vertex color and render maps to all selected objects. Load it into the script editor [alt] + [4] and hit [F5] to run it. (Be sure the script language was set to vb script.)
The variable "overwrite_VC" can be changed.
With "1" all existing CAV maps of selected objects will be overwritten. This can take some time.
With "0" only selected objects without CAV maps will be the script's target.


Notes on ModTool view modes

  • "Constant" let you see the colors of the vertex coloring only.
  • "Textured Decal" let you see object textures only.
  • "Shaded" let you see the illumination only.
  • "Textured" let you see the textured object with illumination and vertex coloring.


env_shade

If you use env_shade use it with caution. It completely overwrites the vertex coloring.

# BSL command
# env_shade obj_id obj_id R G B

# examples
env_shade 7 7			# object 7 will be black
env_shade 7 7 0 0 0		# object 7 will be black
env_shade 7 7 .31 .999 .5	# object 7 will be quite green
env_shade 7 10 1 1 1		# object 7, 8, 9, 10 lose all their shading


Shadow casting objects

Advantage: this can give the level a more realistic impression.

Disadvantage: High amount of new textures needed.

How to create shadow maps:

Notes on map options:

  • "Surface color and illumination": outputs used texture with added shadows
    • can be used to replace original texture
  • "illumination only": output a texture that only contains the shadows
    • can be used on a new overlying, transparent surface

For other approaches see HERE.


<Rooms>

The Room tag is mandatory. It contains an import path to BNV data (*.dae) which is used to create pathfinding grids. For technical information on BNV see HERE.

For example:

<Import Path="env/lab_bnv.dae"/>

BNV consist of 2 parts: rooms and ghost quads. (What again does BNV stand for?)

  • Those rooms are in fact horizontal planes, they are used to determine the area where pathfinding will be calculated. Areas without rooms won't have pathfinding at all.
  • Ghosts are vertical planes. You need a ghost to connect two parallel rooms.
  • Actually, those horizontal and vertical planes can have any name and don't need any texture.
  • During pathfinding calculation OniSplit creates a new folder called "temp" and a subfolder "grids". There again is a file "levelname_grids.dae". That file contains rooms with textures "bnv_grid_N.tga" marking obstacles in the pathfinding. Ghosts will have a transparent texture "_marker_ghost.tga". You get those things also when you export a level. Transparent ghosts make it easier to see the rest of your level if you have many of those planes.
  • In Mod Tool ghosts and rooms can be grouped under a null object. Right-click the null object to select all its children, then use "Selection Only [x]" as saving option. That way all the planes can be quickly saved to a *.dae file.


Danger quads

You can influence the pathfinding creation of dangerous zones with danger quads. Read on HERE.

Another kind of influence is the gunk flag IgnoreGrid. It can be used to let OniSplit ignore the object during pathfinding creation. The grids in that place will be white.


Tolerance values
  • horizontal distance from room to ghost: 1
  • vertical distance from room to ghost: 18
  • ghost horizontal dimension must be bigger than 0
  • under optimal circumstances pathfinding works on a plane that is +4 world units above or -0,5 beneath the pathfinding grid
  • normally characters can't pass low verticals like at staircases/curbs if those don't have a ramp, near ground level Y=0 is an exception where characters are allowed to step on a plane that is 4 world units above pathfinding grid; higher planes need a ramp
  • max degree of ramp you can go on is 70°; bigger degrees make characters slide down a bit and then fall through to death


File:Pathfinding grid.JPG
ai2_showgrids = 1 in action
BSL commands
  • chr_show_bnv = 1
shows number of bnv the player is standing on
  • ai2_showgrids = 1
shows pathfinding grids
  • ai2_chump
spawns a friendly striker that follows the player if possible, makes also pathfinding grids visible


<Textures>

... used for exceptions

This tag is mandatory. AEKV textures will be imported by the master xml file automatically. Their formats will be DXT1 and BGRA4444 (for transparent ones). If you want them in better quality use the <Textures> tag. But if you are okay with the standard import you can write </Textures> to close the section.

Example of an exception (overwriting the standard format):

               <Texture Name="GOO">
                   <Format>RGBA</Format>
                   <GunkFlags>NoCollision</GunkFlags>
                   <Image>env/images/GOO.tga</Image>
               </Texture>
  • There you can give a texture a special format, for example "bgra4444", to make it transparent.
  • Use gunkflag "TwoSided" to make surfaces visible from both sides.
  • If the texture comes with gunkflag "NoCollision" then all objects with that texture will have no collision. Characters would fall through it.

Both makes sense, let's say, for a water-like substance. The biolab use this for an area with green acid.

making_a_surface_transparent_and_twosided_tn_zpsae6709f0.png


TwoSided and transparent objects

It's also possible to set this in Mod Tool. Use one image source for diffuse and transparency.

It won't work with two image sources even if both sources use the same image. See screenshot if you are still unsure about this.


Regular textures

OniSplit automatically imports textures of objects in the <Model> section. Those objects could be considered as AKEV core geometry.


one texture per object

Furniture and Physics objects are allowed to have only one texture per object.

AKEV core geometry can have one texture or multiple textures - that's up to you to decide.


multiple textures per object

one object with multiple textures, one per polygon cluster
ingame test, blue: twosided
glass: twosided and transparent
random metal: no flag (onesided)

Question: How do we apply multiple textures to an AKEV core object?

Answer: Once again this is a list for ModTool guys:

  • select some polygons
  • goto Material > Phong
  • hit [7] to open Render Tree
  • add a texture and connect "Image" with "Phong", choose "diffuse" as illumination mode
  • double-click "Image" to open Material page
  • choose texture and UV, fine-tune UV via [alt]+[7]

Repeat this for each cluster you create.


Caution: textures will be fixed to one set of flags. You can't use the same texture A for an onesided cluster/object B and twosided cluster/object C. You would need to create a different named clone of that texture and apply that to cluster/object C.


Marker textures

Marker textures are used to import certain objects with special flags. Import those object alongside AKEV core geometry.

Marker textures aren't imported automatically. Add those textures to the final package / plugin, e.g. by some sort of batch code.

onisplit -create:txmp out env/markers/*.tga


The flags Transparent TwoSided NoOcclusion are only set if the same texture source is used for diffuse and transparency and if transparency setting are enabled. See subsection of "... used for exceptions": "TwoSided and transparent objects".


danger quads

The pathfinding grids can have different colors with different meanings.

  • white/gray - clear space
  • green light - nearwall
  • green - semipassable
  • green dark - stairs
  • blue very light - border 1
  • blue light - border 2
  • blue - border 3
  • blue dark - border 4
  • orange - danger
  • red - impassable

For detailed information on colors see HERE.

Normally, OniSplit decide how to color the grids. But it's possible to add own danger quads to fine tune zones of great danger. Those orange areas will be generated with the 4 different blue borders around it.

Danger quads must have "_marker_danger" as texture name.

Results in flags: Transparent TwoSided NoCollision Invisible NoOcclusion Danger


collision boxes

AIs can get stuck in detailed geometry. This can be prevented with collision boxes.

Just create a box or other simple geometry around the problematic object and apply a textured to it named "_marker_barrier". Ingame the box will be invisible and has collision so characters can't get through. The pathfinding grid will be red where it comes in contact with the box, red is followed by a light green and then green.

Results in flags: Transparent TwoSided Invisible NoObjectCollision NoOcclusion


stairs

texture: _marker_stairs

Normally, characters can't move on stairs if they contain verticals. In this case you can use a sloping quad that is above or inside the staircases. It's possible to set the desired flags at the <Model> section but doing so and exporting self-made stair ramps is wasted time. So apply simply _marker_stairs to that quad, characters will move on that surface.

Results in flags: Stairs Transparent TwoSided Invisible NoObjectCollision NoOcclusion

No effect to pathfinding creation. Regularly textured stair geometry (that intersect the marker quad) will be flagged as NoCharacterCollision.


impassable

texture: _marker_impassable

Results in flags: Transparent TwoSided Invisible NoOcclusion

Impassable walls are very similar to collision boxes except that particle can also collide with it. The pathfinding grids will be also red, light green, and green.


blackness a.k.a. jello fix

texture: _marker_blackness

Results in flags: TwoSided NoCollision

Simply black walls. No effect to pathfinding creation.


doors

texture: _marker_door

Results in flags: DoorFrame Transparent TwoSided NoCollision NoOcclusion

Don't use this.


<Objects>

Information on regular object collections can be looked up here:

Character.xml (has to contain player character if there's no AISA file with it)
Console.xml
Door.xml
Flag.xml
Neutral.xml
Particle.xml
PatrolPath.xml
PowerUp.xml
Sound.xml
Trigger.xml
TriggerVolume.xml
Weapon.xml


Furniture.xml

The AKEV core geometry is more or less unique while this furniture file adds standard objects (e.g. crates and desks) to it.

XML tag content type description
<?xml version="1.0" encoding="utf-8"?> float, flag Ignore this.
<Oni> -
<Objects> - This tags marks the file as BINACJBO.
<Furniture> - This tags marks the file as FURN.
<Header>
<Flags> flag Optional tag. Ignore it. Those flags were used in the past.
None
Locked
PlacedInGame
Temporary
Gunk
<Position> float x3 Optional tag. X Y Z position.
<Rotation> float x3 Optional tag. X Y Z rotation.
<OSD> -
<Class> link File path to an OFGA (*.oni) file. Make sure that the OFGA comes also with the files it needs: M3GM and TXMP.

OFGA can hold multiple M3GM. That 3d content will be integrate into the AKEV.

<Particle> string This name gets written into <Tag> inside ONLV (ENVP section) and can be used with BSL commands.

E.g. you can take control over a particle via "particle BSL_name start". For more commands see HERE.

Caution with new OFGA files. The particle name will be composed of 2 parts and always includes an "_" underscore. Examples:

FURN <Particle>test</Particle> + OFGA <Tag>streetlight</Tag> = test_streetlight
FURN <Particle></Particle> + OFGA <Tag>streetlight</Tag> = _streetlight
FURN <Particle>test</Particle> + OFGA <Tag></Tag> = test_


Example
<?xml version="1.0" encoding="utf-8"?>
<Oni>
   <Objects>
       <Furniture>
           <Header>
               <Flags>Gunk</Flags>
               <Position>-62.692 -29 108.35</Position>
               <Rotation>181.522 356.021 178.114</Rotation>
           </Header>
           <OSD>
               <Class>furniture/V_tctf_bigvan.oni</Class>
           </OSD>
       </Furniture>
   </Objects>
</Oni>


Physics.xml

This file is for objects with "physics". Unlike AKEV core geometry or furniture, those objects can be animated.

XML tag content type description
<?xml version="1.0" encoding="utf-8"?> float, flag Ignore this.
<Oni> -
<Physics> -
<Object Name="..."> string Use an unique name for each object.
<ScriptId> integer Tested with BSL command ...
obj_create Id [Id]
obj_kill Id [Id]
env_anim Id [Id]
env_setanim Id [Id]
<Flags> flag
Object setup flags
None
InUse
NoCollision
NoGravity
FaceCollision
<Physics> flag Optional tag of Object.
None
Static
Linear
Animated
Newton (used with <Flags> FaceCollision to make object pushable)
For a pushable object don't use import sub-tags such as animation name, flags, etc. Just use <Import Path="..." /> or <Import Url="..." />
<Position> float x3 Optional tag of Object. Only used for non-animated objects. X Y Z position.
<Rotation> float x3 Optional tag of Object. Only used for non-animated objects. X Y Z rotation.
<Scale> float Optional tag of Object. Only used for non-animated objects.

<Import Path="...">

<Import Url="...">

link This tag comes in two variants. It doesn't matter what variant you use.
<Animation Name="..."> link File path to *.dae file.
<Flags> flag Optional tag of Animation. For more information on those flags look OBAN page.
Object animation flags
None
Loop
PingPong
RandomStart
AutoStart
Local
<End> integer Optional tag of Animation. Frame number. Used to define the end of an OBAN from an *.dae file.
<Start> integer Optional tag of Animation. Frame number. Used to define the start of an OBAN from an *.dae file.


Example

For documentation purpose the file here has been trimmed down.

<?xml version="1.0" encoding="utf-8"?>
<Oni>
   <Physics>
       <Object Name="motorcycle">
           <ScriptId>8</ScriptId>
           <Flags>FaceCollision</Flags>
           <Import Url="motorcycle/export.dae">
               <Animation Name="motorcycle02">
                   <Flags>AutoStart</Flags>
                   <End>880</End>
               </Animation>
               <Animation Name="motorcycle02_stop">
                   <Start>881</Start>
               </Animation>
           </Import>
       </Object>
   </Physics>
</Oni>

In this example OniSplit takes the "export.dae" file, looks what parts it contains and creates geometry files from it.

  • M3GMhubs_rear.oni
  • M3GMhubs.oni
  • M3GMmotocycle.oni

It's a nice feature that hierarchies are supported here.

The motorcycle is made of 3 parts so 3 object animations (OBAN) will be created up to frame 880. Then OniSplit creates 3 more OBANs starting from frame 881.

The reason for the interruption at frame 880 is probably to give barabas a few more frames of glory in the cutscene.

  • OBANmotorcycle0200.oni
  • OBANmotorcycle0201.oni
  • OBANmotorcycle0202.oni
  • OBANmotorcycle02_stop00.oni
  • OBANmotorcycle02_stop01.oni
  • OBANmotorcycle02_stop02.oni


Notes about BSL usage

The bio lab script file use the motorcycle objects and animations like this:

	env_show 9 0		# hide solid motorcycle parts (because they get visible at level start)
	# in the original game the motorcycle is separated in object 8, 9 and 10
	# also the OBAN files have a bit different names

	# static and animated objects are totally independent from each other
	# so their script ids might not be the same

	obj_create 8 10		# create animation-ready motorcycle parts
	env_anim 8 10		# animate those parts (not necessary if OBAN flag is "AutoStart")

	# the first animations would loop because of "AutoStart"
	# so get the right timing to apply the other animations
	# "motorcycle02_stop00" and the others will not loop because they don't have "AutoStart"
	env_setanim 8 motorcycle02_stop00 # motorcycle
	env_setanim 9 motorcycle02_stop01 # hubs
	env_setanim 10 motorcycle02_stop02 # hubs_rear

	obj_kill 8 10		# delete animated parts
	env_show 9 1		# show solid motorcycle parts


Level reimport

Correct export

After export the extraction of objects can fail if their textures can't be found. Those objects probably use textures stored in level 0.

In that case use the "-search" argument to make correct extractions. In total the commands will look like this:

onisplit -export level0_files level0.dat
onisplit -export levelX_files levelX.dat
onisplit -extract:dae levelX_geometry levelX_files/AKEV*.oni -search level0_files

Recycle object collections

You only need this or that file in xml format if you want to extend it. If you decide to use them via a master xml and experience a crash then remove the instance IDs, e.g. <CONS Id="7087"> becomes <CONS> .


Locklights

Door locklights must be transfered by hand from old ONLV (ENVP instance) to new furniture file.


CJBO and vertex coloring

  • Object (xml) import via <Object> tag (xml master file) will get you objects without vertex coloring. (onisplit will pick *.oni class files from the shared folder.)
  • Object (dae) import via <Model> tag (xml master file) should get you objects with vertex coloring but no functions. In that case add corresponding CJBO files by hand.


Level export

The most parts of an Oni level are made of ONLV and AKEV. For AKEV's xml tags see HERE.

You would only want to export those two files as xml if you want to check if a texture or an object really made it into the level or not.


ONLV

XML tag content type description
<ONLV id="..."> integer ONLV's instance number. Should be 0.
<Name> char[64] Name of BSL folder.
Save game slot and level number are defined inside ONLD.
<Environment> link Link to AKEV via file name (AKEVname), don't use file suffix .oni
Level geometry.
<Objects> link Link to OBOA via instance number (#N).
The OBOA instance holds doors, animated objects (usually for cut scenes) and pushable object (they are not used the original game).
<SkyBox> link Link to ONSK via file name (ONSKname), don't use file suffix .oni
This is the sky box.
<Characters> link Link to AISA via file name (AISAname), don't use file suffix .oni
This "AI Setup Array" is an alternative character collection. CHAR is more powerful.
<ObjectQuadMap> link Link to ONOA via instance number (#N).
This "Object Array" holds functional objects - doors, furniture, turrets, triggers and consoles - in addition it appears that the engine only searches for door type.
<Particles> link Link to ENVP via instance number (#N).
Those "Environment Particle" contains traditionally only door lock lights and particles used by OFGA.
<Corpses> link Link to CRSA via instance number (#N).
This is a "Corpse Array". It's used to 'spawn dead characters' like Chung in level 1.


OBOA

Used for movable/moving objects.

XML tag content type description
<OBOA id="..."> integer Instance Id. Should be 1.
<Objects> - Array of <OBOAObject> tags.
<OBOAObject> - There are always 32 empty objects plus those that are actually used.
<Geometry> "#" + integer Link to M3GA instance. -- Doors are made of two parts: an animated and a static part. If this <Geometry> links to a door it will be the animated part.
<Animation>
<Particle>
<Flags> flags
None
InUse
NoCollision
NoGravity
FaceCollision
<DoorGunkId>
<DoorId>
<PhysicsType> flags
None
Static
Linear (?)
Animated (animated via OBAN)
Newton (pushable object)
<ScriptId>
<Position>
<Rotation>
<Scale>
<Transform>
<Name>


ONOA

Used by static objects (imported by object collections).

XML tag content type description
<ONOA id="..."> integer Instance Id.
<Elements> - This is an int32 array for the <ONOAElement> tags.
<ONOAElement> -
<ObjectId> integer Object Id and type to which this quad belongs (see AKEV's AGQG for details).
Actual object Ids can also be found in BINA/OBJC/####.
<QuadList> "#" + integer Link to IDXA instance. Each object has its own IDXA instance.

Where do the links go to again?

ONOA <ObjectId> -> AKEV AGQG -> BINA/OBJC/#### by type and Id
ONOA <QuadList> -> ONOA IDXA -> AKEV AGQG by order


ENVP

XML tag content type description
<ENVP id="..."> integer Instance Id.
<Particles> - This is an int16 array for the <ENVPParticle> tags. If there's no content <Particles /> is used.
<ENVPParticle> -
<Class> char[64] BINA3RAPfile.oni (don't use file prefix/suffix)
<Tag> char[48] particle's name for BSL commands, see OFGA for more information on name composition
<Transform> matrix Float 3*3 + 3 more float for X Y Z position of the particle. For more information on the matrix see OBD:CRSA.
<DecalScale> int32, int32 X Y
<Flags> flag
None
NotInitiallyCreated


CRSA

Wanted: "how to add corpses" tutorial

XML tag content type description
<CRSA id="..."> integer
<FixedCount>
<UsedCount>
<Corpses>
<CRSACorpse>
<CharacterClass>
<Transforms> - There are 19 <Matrix4x3> for each <Transforms>.
<Matrix4x3>
<BoundingBox>
<Min>
<Max>


M3GA

One M3GA instance per animated object.

Animated meshes of doors are embedded in ONLV. All other animated meshes are stored outside as M3GM files.

XML tag content type description
<M3GA id="..."> integer
<Geometries> - This is an int32 array for the <Link> tags.
<Link> link
#N (instance number) (for non-door)
M3GMname (for door)


M3GM

Read on HERE.

Note that M3GMs have their own instances: PNTA, VCRA (x2), VCRA (x2), TXCA, IDXA (x2), IDXA.

Doors store their animated geometry in ONLV while the static part comes from BINACJBODOOR.oni.


IDXA

XML tag content type description
<IDXA id="..."> integer Instance Id.
<Indices> - This is an Int32 array for the <Int32> tags.
<Int32> int32
From ONOA to AGQG elements
Link to <AGQGQuad> in AGQG by order. (The array in AGQG starts with 0, so for example <Int32>6</Int32> would link to 7th <AGQGQuad>.)
From M3GM to PNTA elements
Read on HERE.
From M3GM to VCRA elements
Read on HERE.


Ideas to test out

None ATM.


Ideas that has been tested

Sky dome - it's a fail

sky box
ugly_skybox_lines_tn.jpg
sky dome
sky_dome_512x512_tn.jpg

Maybe it's possible to create a very big sphere or dome that covers the entire level (and let Oni's skybox unused). If it's doable it could avoid ugly lines of the skybox coming from OpenGL rendering.


Update: 12 June 2012

New issues appeared that need to take care about:

  • brightness:
The brightness can be somewhat influenced by BSL commands like with gl_fog_..., gs_farclipplane and must be set adequately.
  • texture size:
The dome seen in the screenshot has a texture size of 512x512 and hence looks quite pixelated.
The problem might be solved by splitting the dome into sectors and giving each sector its own texture.


gl_fog_start=.99999
sky4sectors_b_tn.jpg
test level over HERE
sky4sectors_a_tn.jpg

Update: 14 June 2012

  • texture boarder and distortions:
Texture boarders have darker pixels so the UV must not reach them. Also after splitting the textures inside the editor there will be little distortions but they are still noticeable enough to make the sky look odd. Fine-tuning the UVs didn't really help.
  • The gs_farclipplane max value makes the size of the dome quite limited: I think that the max radius here is somewhere between 2500 and 5000 world units.

I consider this as a fail. Oni would need bigger view range and a texture support of 2096x2096.


Ideas for onisplit

Neo might update OniSplit so that it is searching specific strings in object names of a dae level file.


Cutscene cams

  • string "cutsceneN" (e.g. cutscene231) -> OBAN


Doors

  • string "door*" (e.g. doorBlastDoorMX2000) -> DOOR + BINACJBODoor + OBAN
    • but if the string is "door*cloneN" then the DOOR and OBAN creation gets skipped (e.g. doorBlastDoorMX2000clone3), only class name, rotation and position get written into BINACJBODoor


Animated objects

  • string "*_BeforeAnim": that's first static object with collision data (e.g. BlueCar1_BeforeAnim)
  • string "*_InAnim": that's the animated cutscene object (e.g. BlueCar1_InAnim)
  • string "*_AfterAnim": that's the second static object with collision data (e.g BlueCar1_AfterAnim)


Fake-destructible objects

  • string "*_BeforeAnim": that's first static object with collision data (e.g. ConcreteWall2_BeforeAnim)
  • string "*_FragmentN": that's the group of animated cutscene objects (fragments of the static object) (e.g. ConcreteWall2_Frag5)
  • string "*_ColFragN": that's the group of static objects with collision data (e.g. ConcreteWall2_ColFrag5)
  • string "*_NoColFragN": that's the group of static objects without character collision (e.g. ConcreteWall2_NoColFrag5)
    NoColFrag would be useful if the fragments are quite numerous and small and hence would pose a problem to the pathfinding