prevnext   » SZS: Wiimms SZS Toolset » Guides » KCL: Guide to export and import object files

KCL: Guide to export and import object files

Contents

1.   Introduction

Since version v0.35a the SZS tool wkclt support exporting of Wavefront OBJ files and since v0.37a importing. The Wavefront OBJ format can be used as gateway to and from external 3D tools.

You can find technical information about KCL files in the Custom Track Wiiki:

A KCL or OBJ file can also used to adjust points of different KMP sections. See »KCL-FALL« for details.

2.   Decode (Export)

For all SZS tools, DECODE means: Convert data to an external file format. KCL files will be decoded (exported) into Wavefront OBJ files.

Compatible tools:

2.1   Commands

Decoding is automatically done, if a SZS file is extracted with one of the following commands:
wszst extract --decode <TRACK_FILE.szs> ...
wszst extract --all    <TRACK_FILE.szs> ...
wszst xdecode          <TRACK_FILE.szs> ...
wszst xall             <TRACK_FILE.szs> ...
The new directory contains the binary KCL file (e.g. course.kcl) and also an object file (e.g. course.kcl.obj). The disadvantage of the commands above is, that all files are extracted from the archive. The following commands will only decode the KCL and do not touch other files:
wkclt decode <TRACK_FILE.szs>
wkclt decode <KCL_FILE.kcl>
wkclt copy   <TRACK_FILE.szs> <EXPORT>.obj
wkclt copy   <KCL_FILE.kcl>   <EXPORT>.obj

There are also several commands to decode a KCL to standard output;

wszst kcl <TRACK_FILE.szs>
wszst cat <TRACK_FILE.szs/course.kcl> --decode
wkclt cat <TRACK_FILE.szs>

It is also possible, to inlcude KMP elements into the OBJ export. See command wkmpt DRAW for details.

2.2   Groups and Materials

If creating the OBJ file, the triangles are grouped by the KCL flag. For each existing KCL flag, a group name <CLASS>_<TYPE>_F<FLAG> is created. CLASS is a generic classification of the type like 'wall' or 'road'. TYPE are 2 hexadecimal digits in the range of 00..1f representing is the 5 lowest bits of the flag. FLAG are 4 hexadecimal digits in the range of 0000..ffff representing the complete flag. These 4 digits are used by the encoder, to identify the flag.

The default is to create also a material file with adequate colors. The material file can be disabled by clearing the parameter MTL.

The first example shows a part of a Maple Treeway export in SketchUp:

Maple Treeway in SketchUp

The second example shows a part of a Koopa Cape export in 3ds max:

Koopa Cape in 3ds Max

3.   Encode (Import)

For all SZS tools, ENCODE means: Convert data to an internal file format. For the KCL-encoder it means: Create a new KCL file including an octree. The source may be another KCL file or a Wavefront OBJ file. The ENCODE command creates a complete new KCL binary file of any size from scratch.

Compatible tools:

3.1   Commands

If you create a new SZS file and a KCL exists and also a related OBJ file, and this OBJ file is younger than the KCL file, the OBJ file is used to create a new KCL is before assembling the SZS file. Options --no-encode and --encode-all control this behavior. An example command is:
wszst create TRACK_DIR.d

To create a binary KCL file, use the command wkclt ENCODE or wkclt COPY:

wkclt encode OBJ_FILE.obj
wkclt copy   OBJ_FILE.obj COURSE.kcl
Configuration parameters are also possible:
wkclt encode OBJ_FILE.obj --const kcl_max_depth=7 --kcl round
The following command cleans the KCL and recreates the octree and saves the result by replacing the source file:
wkclt encode course.kcl --kcl drop,new

3.2   Defining KCL flags

While scanning the triangles of a Wavefront OBJ file, group names are scanned to define the KCL flag. Each single KCL flag is resolved in up to 6 steps, until it is found:
  1. First, the group name is searched literally, but ignoring case, in the flag file (see below). If found, the defined KCL flag is used and searching is aborted. A negative value means: Ignore the triangles of this group and exclude them from the KCL.
  2. Second, the group name is searched in the pattern definitions of the flag file, ignoring the case. Patterns are strings combined with the following wildcards: '*' for any number of characters, '#' for any number of decimal digits (0..9), '?' for any single character, '[...]' for exact one of the entered character, and '{...,...}' for a comma separated list of alternatives.

    If found, the defined KCL flag is used and searching is aborted. A negative value means: Ignore the triangles of this group and exclude them from the KCL.

  3. If the 6 last characters of the group name are in the format '_Fxxxx' (literal '_F' and 4 hex digits), then the numeric value of the hex digits is used as KCL flag.

    Example: group_F1234

  4. If the 5 last characters of the group name are in the format '_ffff' and all 'f' are hexadecimal digits, then the numeric value of the digits is used as KCL flag.

    This old kind of definition is only accepted, if parameter HEX4 is set, either by option --kcl or by defining a variable in the flag file.

    Example: group_1234

  5. If the 7 last characters of the group name are in the format '_tt_vvv' and all 't' and 'v' are hexadecimal digits and 'tt' is a type in the range 00..1f and 'vvv' is a variant in the range 000..7ff, then the correct combination of both values is used as KCL flag.

    This old kind of definition is only accepted, if parameter HEX23 is set, either by option --kcl or by defining a variable in the flag file.

    Example: group_12_345

  6. If all other fails, a generic KCL flag is created. Therefor the unusual values 0xFFE0, 0xFFC0, 0xFFA0 and so on (all type 0x00 (road), each 0x20 lower as the one before) are used in this order. This makes the groups discriminable in the KCL.
Steps 4 and 5 are only defined for compatibility with prior versions of the tools. To use them, enable them explicitly by setting the parameters HEX4 and HEX23.

3.2.1   Flag File

The flag file is searched in different places. The default is the filename of the OBJ file with the new extension .flag (my_track.objmy_track.flag). See option --flag-file for more details.

The flag file is searched for lines in the format: name = expression. Names and expression results are stored in an internal literal name list as data base for step 1. A later definition overrides the previous one. If the name contains one or more wildcards, it is additionally stored in a pattern list as data base for step 2. Here is the order important, because each group name is compared to each pattern in the defined order until a pattern matches the group name.

The text parser is used for scanning the flag file. This means you have the power of if..then..else, loops, variable definitions, macros, functions and numeric expressions. It's also possible, to use extern defined constants for conditional execution.

Example for a simple flag file:

# KCL Flag assignment for MYTRACK (yes, comments are possible)

# First, we define a flag function named f().
# This allows us to define type and variant as 2 values.
@function f # (type,variant)
    @return $1 | $2 << 5
@endfunction

# group_name	= type,variant # comment
#-----------------------------------------------------------------------
  *nokcl*	= -1             # ignore all groups marked with 'nokcl'
  main_road	= f(0x00,0x005)  # this is the main road
  side_way     = 0x0200         # define a KCL directly as 16 bits
  offroad	= f(0x03,0x002)  # mud road
  *road*	= f(0x01,0x000)  # all other groups marked with 'road'
  *boost*	= f(0x06,0x000)  # all groups marked with 'boost'
  *		= f(0x0f,0x000)  # all others are walls

# Here we can override the global settings made by --kcl HEX4,HEX23.
# Set HEX4 and/or HEX23 to 0 (disable) or 1 (enable) to accept group
# names in the formats '_ffff' and/or '_tt_vvv' for defining KCl flags,
# if all other rules fail. Uncomment to activate:
#@def hex4  = 1
#@def hex23 = 1

3.2.2   CFF (Create Flag File)

Command CFF (an abbreviation of »Create Flag File«) is a flag file creation helper. It reads a KCL or an OBJ file and creates a new flag file as template. If the flag file already exists, it is scanned and only new groups are appended at the end of the existing file.

3.3   Creating the octree

The creation of the octree is done fully automated, but it can be controlled and fine tuned by the configuration parameters (in alphabetic order): KCL_BITS, KCL_BLOW, KCL_MAX, KCL_MAX_TRI, KCL_MAX_DEPTH, KCL_MIN, KCL_MIN_SIZE and KCL_MAX_SIZE.

For the octree, the world is divided into equal sized cubes. The world is the smallest cuboid that contains all triangles of the KCL model. The parameters KCL_MIN and KCL_MAX may override the automatic calculation. Remember, a cube is also a cuboid, but with 6 equal square sides and 12 equal edges.

For the octree operations, all coordinates are rounded to integers and a well defined minimal 3D-point (see above) is used as origin. The edge length of a base cube is always a power of 2. The number of base cubes of each direction is also a power of 2. All base cubes together are the cube world, which is usually larger than the triangle word, but never smaller.

If option CENTER is enabled, then adjust the octree entrance coordinates, so that thetriangle world is centered inside the cube world.

For a given point, a fast hash value is calculated form the highest bits of each coordinate. The hash value is used as first index into the octree to find the related base cube. The parameter KCL_BITS defines the maximal number of hash bits for the new octree. The number of base cubes is exact 2bits.

Now it becomes recursive: For each cube count the number of triangles that collide with the current cube. For this collision calculations the cube is blown up (see parameter KCL_BLOW) to integrate triangles of the neighborhood. The recursion is stopped, if one of the following 3 conditions becomes true:

If the recursion stopped, store the triangle list into the octree. Otherwise divide the current cube into 8 equal sub-cubes and start the next recursion step for each of the 8 sub-cubes.

3.4   Limits

There are only some limits while creating the KCL file: A new KCL file is always created from scratch. So the KCL is garbage free.

4.   Detection of OBJ files

4.1   File types

If reading any file, the tools try to identify its file type by reading and analyzing the first 2 KiB of a file. Command wkclt FILETYPE shows the result of this analysis:

 # wkclt filetype *

 type   file name
 ---------------------------
 KCL    course.kcl
 KCLTXT course.obj
 SKPOBJ sketchup-orig.obj
 WAVOBJ sketchup-plugin.obj

For KCL processing, there are 4 relevant file types:

KCL
A real and binary KCL file. The 3 other formats are different variants of an OBJ file.
KCLTXT (KCL text file)
An OBJ file exported by Wiimms SZS Tools. It may contain additional commands (e.g. TRIANGLES), that are incompatible with official OBJ files. A KCLTXT file is deteced by its magic and because of the magic, it is very simple, fast and nonambiguous to identify this type of OBJ files.
SKPOBJ (SketchUp OBJ)
An export by the internal exporter of SketchUp. This is a special variant of a Wavefront OBJ file and don't support groups. The recommended OBJ exporter plugin creates WAVOBJ files.
WAVOBJ (Wavefront OBJ)
A general Wavefront OBJ file, that is not one of the other formats. This kind of OBJ files is exported by the most 3D tools.

4.2   Detection algorithm

Wavefront OBJ files are simple text files. To distinguish OBJ files from other text files, the tools try to find some prominent strings at special places. It is done by the following algorithm:

  1. A byte order mark (BOM) is skipped.
  2. If the very first 4 characters are '#KCL', the file is deteced as KCLTXT (KCL text file = OBJ file, created by the tools).
  3. Empty lines and lines beginning with a 'g' (group line) are ignored.
  4. If the first non emtpy line is a comment line and contains the keywords 'OBJ' and 'WAVEFRONT' it is detected as WAVOBJ (Wavefront OBJ) file.
  5. If the first non emtpy line is a comment line and contains the keywords 'OBJ' and 'MODEL' it is detected as SKPOBJ (SketchUp OBJ) file.
  6. If the first non comment line starts with 'mtllib' or 'usemtl', it is detected as WAVOBJ file.
  7. If the first non comment line starts with 'v' followed by 3 floating numbers, it is detected as WAVOBJ file.
Otherwise it is neither detected as any kind of OBJ file and the file is not accepted as source for KCL processing.

5.   Debugging

There are several commands to debug KCL files. All commands can be used for binary KCL files and also for OBJ files. In the later case, a virtual KCL file is created first from the OBJ data.

5.1   Debug listing

The command wkclt DUMP dumps the content of the internal triangle database and the octree in a human readable format. In combination with option --brief (-B), it prints only statistics about the KCL and it's octree.

5.2   Traverse the octree

The command wkclt TRAVERSE traverses the octree to find specific points. This command helps to understand the octree and to verify it.

Another way to traverse the octree is the command wkclt FALL. For each entered point, a cube with edge length 100.0 is created and dropped. The cube falls until a KCL collison is found. The new position is printed to standard output. The cube size can be changed by setting the constant WIDTH. The relavent KCL tpye for this collison can be set by the constant MASK, the default is to collide with all types.

5.3   Print a flag summary

The command wkclt FLAGS prints a summary of the flag usage of a KCL file. Use this command to verify your flag assignment file.

Example: wkclt flags TRACK.obj

6.   Options

6.1   --kcl list

Set global options for KCL processing. Parameter 'list' is a comma separated list of keywords. A minus sign before a keyword disables a setting. Each occurrence of the option will only change entered settings and all other settings are untouched. Keyword DEFAULT resets the default settings and CLEAR disables all. Keywords SMALL, MEDIUM and CHARY select the default parameters for the octree creation. The other allowed keywords are: FAST, NEW, CENTER, ROUND, NORMALS, MTL, WIIMM, TRIANGLES, OUT-SWAP, G, USEMTL, CLIP, IN-SWAP, AUTO, HEX4, HEX23, HEX, DROP-UNUSED, DROP-FIXED, DROP-INVALID, DROP, RM-FACEDOWN, RM-FACEUP, FIX-ALL, TINY-0 ... TINY-7, CONV-FACEUP, WEAK-WALLS, SORT, INPLACE, SILENT and LOG.
The option --kcl expects a comma separated list of keywords to define global settings for the KCL processing. If a keyword is preceded by a minus sign, it is disabled. Each occurrence of the option will only change the current settings. To reset all settings, use either CLEAR or DEFAULT.

The following table shows all user keyword (there are some more hidden keywords for development). Some few keywords are enabled by default; see the description.

Keywords for option --kcl
keyword Description
CLEAR This keyword clears (disables) all other keywords.
DEFAULT This keyword resets all keywords to their default status: MEDIUM and MTL are set, all others are cleared.
SMALL
MEDIUM
CHARY
These keywords decide the default values for the configuration parameters KCL_BLOW and KCL_MAX_TRI and some more settings:
  • SMALL set the parameters to values to get a relative small KCL file. Until now I have not found any disadvantage of SMALL. Try it, if you have slow motion problems.

    If you plan a track with a speed factor larger than 1.5, then don't use SMALL.

    If SMALL is active, FAST is disabled and ROUND is enabled.

  • CHARY set the parameters to Nintendo like values, that are very careful. This blows up the octree significant because of the large KCL_BLOW value. Use it only for experiments or if MEDIUM fails.
  • MEDIUM, the default, is anywhere in the middle between SMALL and CHARY.
FAST If creating a binary KCL file, the tools try to find duplicate vertex and normal entries. For the octree creation, the tools try to find duplicate triangle lists. These duplicates will share the same memory to reduce the file size. If FAST is set, this optimization is disabled and the creation is faster.

However, if a source has more than 16383 (0x3FFF) triangles (see limits), the fast modus for the creation of the vertex and normal lists is disabled to avoid a list overflow.

If keyword SMALL is active, FAST is ignored.

NEW Force the creation if a new octree. This keyword has only impact, if input and output are binary KCL files.
CENTER After calculating the octree parameters and before creating a new octree, adjust the octree entrance coordinates, so that the triangle world is centered in the octree relevant area.
ROUND On calculating normals, each coordinate is rounded to the nearest multiple of 2-17 (=~7.629*10-6). Nintendo uses multiples of 21*2-21 (=~1.001*10-5) for it tracks. This makes the vertex and normal lists smaller because of more duplicates.

Parameter ROUND is automatically set, if SMALL is active.

NORMALS If creating an OBJ file and NORMALS is set a list with normals ('vn ...') is exported too.

The default since version v1.30a is to do not export the normals. This setting is the best for the free SketchUp OBJ importer, because othwerwise it misinterprets some face directions.

MTL
MATERIALS
If creating an OBJ file and MTL ist set (=default), then a material file (*.mtl) is created too and 'mtllib' and 'usemtl' commands are inserted into the OBJ file. The idea is to define adequate colors.
WIIMM Normally, each created OBJ file has its own material file with the same filename, but with extension .mtl. The material file itself has always the same content for all exports.

If this option is set, the material file is called wiimm.mtl for all OBJ exports. The advantage is, that you have only 1 material file for many exports.

TRIANGLES If creating an OBJ file, the triangles are stored as vertices and faces, like other tools do and understand it.

But if TRIANGLES is set, each triangle is stored as an line in the format:
  'TRI' FLAG '|' POINT1 '|' POINT2 '|' POINT3
The advantage and only usage is, to mix triangles of different object files using a simple text editor and copying single lines. This is sometimes (or most?) more effective than using complicated export, import and filter functions of 3D tools.

If TRIANGLES is set, MTL and WIIMM are ignored and a material file is not created. The OBJ file itself becomes incompatible (invalid), because TRI lines are not supported by any other tool.

On scanning, TRI-lines are recognized and can be combined with standard OBJ lines. The flag of a TRI command overrides the group flag. With TRI-lines, adding points or mixing OBJ files is much easier.

OUT-SWAP
OUTSWAP
OSWAP
If set, the second and third points (1-based counting) of the triangles are exchanged while creating an OBJ file.
IN-SWAP
INSWAP
ISWAP
If set, the second and third points (1-based counting) of the triangles are exchanged while reading an OBJ file.
AUTO If this keyword is set while an OBJ file is scanned, then all points with a defined normal for point 1 are analyzed to find the optimal order of the second and third triangle point.
G
USEMTL
If reading an OBJ file, the faces are divided into groups and a KCL flag value is assigned to each group using a flag file. The groups and its names are derived from the OBJ commands 'g' and 'usemtl'.
  • If only 'G' is set, only 'g' commands are used to derive groups.
  • If only 'USEMTL' is set, only 'usemtl' commands are used to derive groups.
  • If both are set, both commands are used to derive groups.
  • If none of both is set (the default), 'usemtl' is used for SKPOBJ files (created by the internal exporter of SketchUp) and 'g' for all other OBJ file types. See »Detection of OBJ files« for details about file types.
CLIP Some custom tracks were created by overwriting some data into an existent KCL file. Sometimes, triangles are not overwritten, but some of their related source data (vertex or normals). As result, the triangle points are far away from the main world.

If CLIP is set, a border is used to find invalid triangles. See constant KCL_CLIP for more details. And also see keyword DROP-UNUSED for a more intelligent method to find waste.

HEX4 If this keyword is set and no flag is defined for an OBJ group, and if the 5 last characters of the group name are in the format '_ffff' and all 'f' are hexadecimal digits, then the numeric value of the digits is used as KCL flag.

This global setting can be overridden by defining a integer variable in the flag file named HEX4.

HEX23 If this keyword is set and no flag is defined for an OBJ group, and if the 7 last characters of the group name are in the format '_tt_vvv' and all 't' and 'v' are hexadecimal digits, then the numeric values of the digits are used as type and variant of a KCL flag.

This global setting can be overridden by defining a integer variable in the flag file named HEX23.

HEX Keyword HEX is s short cut for HEX4,HEX23.
DROP-UNUSED
DROPUNUSED
In some custom tracks you can find triangles that are not used by the octree. And that means, that they are useless. If keyword DROP-UNUSED is set, these useless triangles are searched and removed from the KCL.
DROP-FIXED
DROPFIXED
If using KCL_CLIP to find extreme values, some triangles may be marked internally as fixed. If keyword DROP-FIXED is set, these triangles are searched and removed from the KCL and the octree becomes invalid.
DROP-INVALID
DROPINVALID
While reading data, the tools look for invalid numbers (NAN and INFINITE for example). Also calculations of the triangle points may result in invalid numbers (examples: 2 points at the same position or 3 points in a line or triangle to small or large). If keyword DROP-INVALID is set, these triangles are searched and removed from the KCL and the octree becomes invalid.
DROP DROP is a short cut for DROP-UNUSED,DROP-FIXED,DROP-INVALID. The command will drop all bad triangles.

If exporting a KCL to an object file and no DROP-Mode is specified, DROP is automatically set.

RM-FACEDOWN
RMFACEDOWN
RM-FACEDOWN removes all face down drivable triangles with a face direction ≥30 degree towards the botton. Drivable are all kinds of roads, boost and trick ramps.

Face down roads are usually not needed and are the reason for a lot of glitches:

  • Unwanted jumps while driving over the road.
  • Hard changing of the driving direction if jumping down to the road.
  • Barrel rolling.
  • Curious camera jumping effects.
  • Underground views of cameras.
RM-FACEUP
RMFACEUP
RM-FACEUP removes all face up walls with a face direction ≥80 degree towards the sky.

Horizontal face up walls are like prisons, if a player reach it. Because of a wall, a player can't move. And because of the horizontal direction, the player don't slip to any direction.

This feature is available since v1.49a.

FIX-ALL
FIXALL
FIX-ALL is a short cut for NEW, all DROP-* and all RM-* parameters.
CONV-FACEUP
CONVFACEUP
CONV-FACEUP converts all face up walls with a face direction ≥80 degree towards the sky to a simple road. CONV-FACEUP has a higher pririty than RM-FACEUP.

Horizontal face up walls are like prisons, if a player reach it. Because of a wall, a player can't move. And because of the horizontal direction, the player don't slip to any direction.

This feature is available since v1.49a.

WEAK-WALLS
WEAKWALLS
Set the most significant bit (bit 15, 0x8000) of KCL flag of all walls. It stops hard bumping at the edges and has similar effects like lowering the walls.
SCRIPT If SCRIPT is set, the scripts defined by option --kcl-scipt are executed before removing and converting triangles and before transforming. Otherwise they are executed behind. See »Execution Order« for more details.
INPLACE If a KCL file withing a SZS file is replaced by a new version, the SZS file is rearanged (sub files are moved) to give the new KCL optimal space.

If INPLACE is set, no other files are moved and the new KCL size must be smaller or equal as the old size. If the new file is smaller, the SZS file receives an usused hole. This was the behaviour of old tool versions.

SORT This debugging keyword sort the triangles by length and positions to make all dumps more and easier comparable.
SILENT If set, the KCL status lines about the set keywords and more are suppressed.
LOG This is a debugging keyword. If set, the tools create a trace log about the main KCL reading, modifying and writing steps.

See also »Configuration Parameters« for parameters with values.

6.2   --kcl-flag joblist

Modify the KCL flag of KCL files. A comma separated job list in the format 'srclist=dest' is expected. 'srclist' is a plus sign separated list with single values like <val>, T<type> and <val>/<mask> or ranges like <val>:<val>, T<type>:<type> and <val>:<val>/<mask>. '<val>' is a complete KCL flag in the range of 0..0xffff. '<type>' are only the base types in the range of 0..0x1f. If <mask> is present, it marks the relevant bits. For the T<type> variant, the mask is set to 0x1f. All KCL flags of the source list are assigned to the new value 'dest', but only the set bits of '<mask>' are modified. A later definition overrides the previous one.
The idea of this option is to give the user an easy interface to change KCL flags of the triangles. However, the user can also use complicate rules. Sometimes it is easier to write a script and use the option --kcl-script.

Let's start with easy rules: We want to find all triangles with KCL flag 0x1234 and want to set the new KCL flag 0x5678: --kcl-flag 0x1234=0x5678. In the next examples we don't write the option name and we use spaces to make reading easier. The example above: 0x1234 = 0x5678.

You don't need to write leading zeros and it's always possible to add more rule separated by a comma: 0x111 = 0x333, 0x222 = 0x333.

In the last example, 2 flags are replaced by the same value. This can also be written as: 0x111 + 0x222 = 0x333.

More usual is to replace the base type without changing the variant bits. In the following example we replace type 0x01 (road) by 0x17 (another road). We do this by using a 'T' as prefix: T0x01 = 0x17.

You can also enter you codes in decimal notation: T1 = 0x17 or T1 = 23.

Now we want to replace all roads of types 0..4 to type 0x17: T0 + T1 + T2 + T3 + T4 = 0x17. You can simplify such ranges by using a colon: T0:4 = 0x17.

You can use also the mask notation VALUE/MASK, but this is very complicated. Since the appearance of option --kcl-script there is a much easier way to change flags under complicated conditions. Another advantage of --kcl-script is, that it can also use the triangle positions as condition to change the flags.

An existing octree is untouched, if only KCL flags are changed. To force the creation of a new octree, use parameter NEW.

6.3   --kcl-script script

After reading a KCL source file and executing all transformations, the text file 'script' is executed by the internal text parser. The script should use the parser functions tri$*() to read and modify the triangle positions and flags, or to add or remove complete triangles. If this option is used multiple times, each script is executed in the entered order.
The user can define a list of scripts with this option. The scripts are executed after loading the KCL or OBJ file and after command line driven transformations (see »Execution Order« for details). The scripts are executed by the internal text parser.

The main goal of a KCL script is to iterate through all items and to modify positions or KCL flags, or to add or remove complete triangles.

The following script shows an example for lowering walls to avoid the hard edges:


# Setup
@def start	= mSec()	# start time, for the status line
@def mod_count	= 0		# modification counter

# Get the value for lowering the walls.
# If 'lower' is defined as number by option --const, use it.
# Otherwise use the default of 50.
@def lower = isNumeric(lower) ? lower : 50

# Define a function to test the KCL flag for walls
@function isWall # flag
    @pdef t = $1 & 0x1f
    @return t == 0x0c || t == 0x0d || t == 0x0f
    >    || t == 0x14 || t == 0x1e || t == 0x1f
@endfunction

# Main loop: Iterate through all triangles
@for t=0;tri$n()-1
    @if isWall(tri$flag(t))
	# Is it a wall?
	# If yes, lower the wall & increment the counter
	@def status = tri$shift(t,-vy(lower))
	@def mod_count = mod_count+1
    @endif
@endfor

# Print a little status line
@echo "  - " mod_count " of " tri$n() " triangles lowered by " lower
	> " in " (mSec()-start) " msec."

The following table shows the special triangle function. All other parser functions are also available:

Triangle Functions
File
Type
Return Value
& Function Name
& Parameters
Description
KCL int
tri$create
(kcl_flag,​pt0,​pt1,​pt2,​...)
This function appends new triangles at the end of the triangle list with the entered parameters. If more than 3 points are entered, all points must be in the same plane and the polygon is split into multiple (N-2) triangles. The function returns the index of the first new triangle or -1 if failed.
KCL int
tri$createAntiArrow
(flag,​pt1,​pt2,​ptX,​r,​n,​a_flag​[,a_size]​[,b_flag]​[,b_ht])
This function creates an antiprism based arrow with radius 'r' and N faces from 'pt1' to 'pt2', where 'pt2' is the place of the arrowhead. The point 'ptX' is used for the orientation (direction of first edge). 'flag', 'a_flag' and 'b_flag' are KCL flags to define the color. 'a_size' is the addition size factor of the arrowhead, the default is 1.0. If 'b_flag' is not set or @-1@, no base is drawn. If 'base_height' is set, a pyramid is drawn as base. The function returns the index of the first new triangle or -1 if failed.
KCL int
tri$createAntiPrism
(kcl_flag,​pt1,​pt2,​ptX,​r,​n​[,base_flag]​[,base_height])
This function creates an antiprism with radius 'r' and N faces from 'pt1' to 'pt2' by adding 2*N triangles. The point 'ptX' is used for the orientation (direction of first edge). If 'base_flag' is set and not @-1@, the base is printed with ths kcl flag value. If 'base_height' is set, a pyramid is drawn as base. The function returns the index of the first new triangle or -1 if failed.
KCL int
tri$createArrow
(flag,​pt1,​pt2,​ptX,​r,​n,​a_flag​[,a_size]​[,b_flag]​[,b_ht])
This function creates a prism based arrow with radius 'r' and N faces from 'pt1' to 'pt2', where 'pt2' is the place of the arrowhead. The point 'ptX' is used for the orientation (direction of first edge). 'flag', 'a_flag' and 'b_flag' are KCL flags to define the color. 'a_size' is the addition size factor of the arrowhead, the default is 1.0. If 'b_flag' is not set or @-1@, no base is drawn. If 'base_height' is set, a pyramid is drawn as base. The function returns the index of the first new triangle or -1 if failed.
KCL int
tri$createCuboid
(kcl_flag,​pos,​size​[,rot])
This function creates a cuboid by adding 12 triangles. If 'size' is a scalar, a cube with the entered edge length is created. If 'rot' is set, the cube is rotated. As last operation the center (origin) of the cube is shifted to 'pos'. The function returns the index of the first new triangle or -1 if failed.
KCL int
tri$createJoist
(kcl_flag,​length,​pt1,​pt2,​pt_dir​[,n_marker]​[,mark5_flag])
This function appends a triangular joist from 'p1' to 'p2' to at the end of the triangle list. 'length' the length of the body and 'pt_dir' is a helper point for its direction. If 'n_marker' is >0, markers representing the number are added. If 'mark5_flag' is >0, every 5 markers are replaced by one of the entered flag. The function returns the index of the first new triangle or -1 if failed.
KCL int
tri$createOctahedron
(kcl_flag,​pos,​radius​[,rot])
This function creates a octahedron by adding 8 triangles. If 'radius' is a scalar, a regular octahedron created. Otherwise it is a vector and define different radiuses for each axis. If 'rot' is set, the octahedron is rotated. As last operation the center (origin) of the cube is shifted to 'pos'. The function returns the index of the first new triangle or -1 if failed.
KCL int
tri$createPrism
(kcl_flag,​pt1,​pt2,​ptX,​r,​n​[,base_flag]​[,base_height])
This function creates a prism with radius 'r' and N faces from 'pt1' to 'pt2' by adding 2*N triangles. The point 'ptX' is used for the orientation (direction of first edge). If 'base_flag' is set and not @-1@, the base is printed with ths kcl flag value. If 'base_height' is set, a pyramid is drawn as base. The function returns the index of the first new triangle or -1 if failed.
KCL int
tri$createPyramid
(kcl_flag,​apex,​pt1,​pt2,​...)
This function creates a pyramid by adding N triangles. 'pt1'..'ptN' descibribes the base polygon, which is not created. The function returns the index of the first new triangle or -1 if failed.
KCL int
tri$defColor
(argb​[,alpha])
Define a new color. 'ARGB' is a bytes coded color: alpha,red,green,blue. If 'ALPHA' is not set, the highest byte of 'ARGB' is used. If this highest byte is null, 0xff (no transparency) is used. The function returns -1, if already 200 colors defined. Otherwise it returns the virtual KCL flag for the user defined color.
KCL int
tri$defColor
(red,​green,​blue​[,alpha])
Define a new color. If ALPHA is not set, 0xff (no transparency) is used. For the 3 colors, values between 0x00 and 0xff are expected. The function returns -1, if already 200 colors defined. Otherwise it returns the virtual KCL flag for the user defined color.
KCL int
tri$flag
(tri_index​[,mode])
This function returns the KCL flag of the triangle 'tri_index' (0..). If mode is '1', the original source value is returned. If mode is '2', the original source value transformed by --kcl-flag is returned; if --kcl-flag is not set, it is the same as mode '1'. Otherwise the current value is returned. The current value is initialized by the value of mode '2'. Values >0xffff are possible and represent internal drawings.
KCL int
tri$getColor
(index)
This function returns the color defined by a previous tri$defColor() call. INDEX is the virtual KCL flag for the user defined color. On error, the value NONE (type 'undefined') is returned.
KCL int
tri$hRot
(tri_index,​degree​[,origin])
This function rotates the triangle 'tri_index' (0..) horizontal counterclockwise by the angle 'degree' around the point 'origin'. If the origin is not set, v(0,0,0) is used instead.
KCL int
tri$isRemoved
(tri_index)
This returns the status of the 'REMOVED' marker of the triangle 'tri_index' (0..). The return value is -1 for an invalid index, 1 if the triangle is marked as removed or 0 if not.
KCL float
tri$length
(tri_index)
This function returns the length of triangle 'tri_index' (0..).
KCL vector
tri$n
()
This function returns the number of triangles.
KCL vector
tri$normal
(tri_index,​norm_index)
This function returns the normal with index 'norm_index' (0..3) of triangle 'tri_index' (0..).
KCL vector
tri$pt
(tri_index,​pt_index)
This function returns the point with index 'pt_index' (0..2) of triangle 'tri_index' (0..).
KCL int
tri$ptsInCuboid
(tri_index,​cube_min,​cube_max)
Parameters 'cube_*' are converted to vectors. They describe 2 diagonal corners of a rectangular cuboid, assuming that 'cube_min<=cube_max' is true for each coordinate. The functions returns the number of points of the triangle 'tri_index' (0..), that are inside of the cube including the border. If 'tri_index' is invalid, -1 is returned.
KCL int
tri$remove
(tri_index)
This function marks the triangle 'tri_index' (0..) as 'REMOVED'. The return value is -1 for an invalid index, 1 if the triangle was already removed or 0 if not.
KCL int
tri$scale
(tri_index,​scale​[,origin])
This function scales the triangle 'tri_index' (0..) by the vector 'scale' relative to point 'origin'. If the origin is not set, v(0,0,0) is used instead.
KCL int
tri$setFlag
(tri_index,​new_flag)
This function sets the new KCL flag of triangle 'tri_index' (0..). The function returns -1 for an invalid index or the previous value of the KCL flag.
KCL int
tri$setPt
(tri_index,​pt0,​pt1,​pt2)
This function sets the coordinates of all 3 points of the triangle 'tri_index' (0..) to the vectors 'pt*'.
KCL int
tri$setPt
(tri_index,​pt_index,​pt)
This function sets the coordinates of the single point with index 'pt_index' (0..2) of triangle 'tri_index' (0..). to the vector 'pt'.
KCL int
tri$shift
(tri_index,​shift)
This function adds the vector 'shift' to all 3 points of the triangle 'tri_index' (0..).
KCL int
tri$type
(tri_index​[,mode])
This function returns the KCL type of the triangle 'tri_index' (0..). It works like tri$flag(), but the flag is transformed to a type. The return value is in the range of 0x00..0x1f (5 lowest bits of the flag), if it is a real KCL flag (<0x10000), or -1 otherwise (special type).
KCL int
tri$unremove
(tri_index)
This function clears the 'REMOVED' marker of the triangle 'tri_index' (0..). The return value is -1 for an invalid index, 1 if the triangle was removed or 0 if not.

6.4   --tri-area expr, --tri-height expr

Sometimes, the imported file contains very small triangles with an area smaller than 1 unit2. They were accidentally inserted into the model by the user. Because of the littleness, the user will not see them in the model view of its 3D Tool. However, machines like the KCL importer of these tools see them and insert them into the KCL — this is not a bug of the tools. The Wii has (mathematical) problems to use them in a correct way with the result of KCL glitches like mini walls on the road.

Since v1.58a there exist 2 new options: --tri-area=EXPR and --tri-height=EXPR to filter out too small triangles.

Option --tri-area=EXPR defines the minimal area size of KCL triangles. The intention is to ignore triangles that are generally to small. EXPR is a floating point number or expression. Triangles are invalidated if their area size is smaller than EXPR. Values between 0.01 and 4.0 are recommended. The careful value 1.0 is used as default. For some tracks, values greater than 1000 worked too. Value 0 disables this filter functionality.

Option --tri-height=EXPR defines the minimal height of KCL triangles. The intention is to ignore deformed triangles (very slim, but long). EXPR is a floating point number or expression. Triangles are invalidated if at least 1 of the 3 heights is smaller than EXPR. Values between 0.01 and 2.0 are recommended. The careful value 1.0 is used as default. Value 0 disables this filter functionality.

The tests for both options are executed after reading files, after transformations, and after calculating normals and lengths.

6.5   --flag-file filename

Define a flag file if scanning an OBJ file (KCL processing). The file name may contain %-escapes. Set it to an empty string to disable flag files at all. The tool search the flag file in the following order until found: File defined by --flag-file; OBJ file name with replaced extension ('a.obj' becomes 'a.flag'); OBJ file name with appended extension ('a.obj' becomes 'a.obj.flag').
This option allows to set an additionally path to search a flag file while scanning an OBJ file. The flag file is searched in the following order until found:
  1. If option --flag-file is set to a non empty string, the file is searched first. This string may contain %-escapes.
  2. File '%P/%N.flag'. This is the OBJ file name with the new replaced extension .flag (Example: my_track.objmy_track.flag).
  3. File '%P/%F.flag'. This is the OBJ file name with the appended extension .flag. (Example: my_track.objmy_track.obj.flag).
  4. This is an old and obsolete search: For a short time the file '%P/%N.flag.txt' is searched too. This is the OBJ file name with the new replaced extension .flag.txt (Example: my_track.objmy_track.flag.txt).
The searching and scanning of flag files can be disabled at all by defining and empty string ad flag file.

Examples:

# define a unique flag file:
--flag-file /path/to/flag-file.ext

# redirect only the search directory
--flag-file /path/to/directory/%N.flag

# use '.txt' as file extension
--flag-file %P/%N.txt

# disable flag files at all
--flag-file ""
Read »Escape Sequences« for more details about %-escapes.

6.6   --shift, --scale, --xss, --yss, --zss, --hrot, ...

The global transforming options --shift, --scale, --xss, --yss, --zss and --hrot are also available. Especially --scale is needed for scaling the KCL model.

Examples:

wkclt encode TRACK.obj --scale 100.0           # scale all 3 dimensions
wkclt encode TRACK.obj --scale "v(100,1,100)"  # scale only X+Z

7.   Configuration Parameters

All tools support the option --const name1=expr1,name2=expr2,... (or the short cut -c ...) to define constants, where expr* is a single value or a numerical expression. All tools can access these constants and the text parser allow access to them like variable names. The case of the variable names is ignored.

If decoding or encoding a KCL file, some constants are used, to define parameters and to override the defaults of the algorithms. And here is the list of all constants, that are relevant for KCL handling.

Examples:

--const kcl_clip=2.0
-c 'KCL_CLIP=v(1,3,2)'
--const KCL_BITS=4,KCL_MAX_TRI=20,KCL_MAX_DEPTH=6
See also option --kcl for global KCL parameters without values.

7.1   KCL_BITS

This constant defines the number of bits used for the hash part of the octree. The result is, that the world will be divided in 2bits base cubes. The number of bits is sometimes reduced because of technical limits.

The default value is calculated by using the total number of triangles and will be never larger than 10 (1024 base cubes). The user can set values in the range of 3..20@ (8..1048576 base cubes). The impact of this parameter for running a track is not clear now.

7.2   KCL_BLOW

For the octree, the world is divided into many cubes of equal size, normally 512*512*512 units. For collisions of an object (eg. driver or item) the octree is traversed to find a list with important triangles (faces) for the current positions. It is important, that near triagles of the neighbor cubes are also included into the triangle list.

While creating the octree, colliding triangles are searched for each cube. Therefor the cube will be temporary expanded by addding the value of KCL_BLOW on all 6 sides to find also colliding triangles in the neighborhood.

The default value depends on the --kcl options SMALL, MEDIUM and CHARY and is either 200 (small) or 400 (medium) or 600 (chary). The user can set any values between 0..10000.

7.3   KCL_CLIP

Some custom tracks has only overwritten some data in an existent KCL file and triangles are stored in veretex and normal components. Sometimes, triangles are not overwritten, but some of their source data (vertex or normals). As result, the triangle points are far away from the main world and will results in failures if importing with a 3D tool.

The SZS Tools try to avoid this: If calculating the triangle points, borders are defined. Points outside this borders are set to the vertex point of the triangle. This border is only used, if setting CLIP is set.

The calculation is simple. Find the minimal and maximal predefined vertex positions, add a little value and expand the world by factor 3. The world is then again expanded by the vector value KCL_CLIP. The default for KCL_CLIP is v(1.0,1.0,1.0).

It is also possible to set each coordinate with a single assignment by using KCL_CLIP.X, KCL_CLIP.Y and KCL_CLIP.Z. This kind of definition has priority over the vector assignment.

BTW: --kcl DROP-UNUSED is a more intelligent method to find wasted triangles.

7.4   KCL_MAX

KCL_MAX is a vector value. If a coordinate is set, it is used as maximal coordinate for the collision detection. The default is the maximum of all triangle points. However, this value is only used for the base cube calculations (number and size).

The real upper border is then: MIN + N_CUBES * CUBE_SIZE.

It is also possible to set each coordinate with a single assignment by using KCL_MAX.X, KCL_MAX.Y and KCL_MAX.Z. This kind of definition has priority over the vector assignment.

7.5   KCL_MAX_DEPTH

KCL_MAX_DEPTH is 1 critieria of 3 to abort the cube recursion. The recursion is aborted and if the maximum octree depth KCL_MAX_DEPTH is reached; the default is 10. Nintendos tracks have values in the range of 3..6, but under the influence of KCL_MIN_SIZE. The user can set any value >0. The impact of this parameter for running a track is not clear now.

7.6   KCL_MAX_TRI

KCL_MAX_TRI is together with KCL_MAX_SIZE 1 critieria of 3 to abort the cube recursion. If creating the octree, a cube is divided into 8 equal sub cubes as long as the number of related triangles is larger than KCL_MAX_TRI. This condition is ignored, if the cube itself is larger than KCL_MAX_SIZE.

The average number of triangles in Nintendo tracks is 60 and the largest one is 180, but under the influence of KCL_MIN_SIZE.

The default value depends on the --kcl options SMALL, MEDIUM and CHARY and is either 40 (small) or 30 (medium) or 20 (chary). The user can set values in the range of 5..500. The impact of this parameter for running a track is not clear now.

7.7   KCL_MIN

KCL_MIN is a vector value. If a coordinate is set, it is used as minimal coordinate for the collision detection. The default is the minimum of all triangle points.

It is also possible to set each coordinate with a single assignment by using KCL_MIN.X, KCL_MIN.Y and KCL_MIN.Z. This kind of definition has priority over the vector assignment.

7.8   KCL_MIN_SIZE

KCL_MIN_SIZE is 1 criteria of 3 to abort the cube recursion. The recursion is aborted, if the new sub cube would become smaller than KCL_MIN_SIZE (edge length); the default value is 512. The base cubes are also never smaller than this setting.

The user can set values in the range of 1..KCL_MAX_SIZE (~1 million; for KCL_MAX_SIZE see below).

It seems, that this is the main recursion stop reason if creating an octree, because all Nintendo tracks have cubes with 512 units and no one have smaller cubes. The impact of this parameter for running a track is not clear now.

7.9   KCL_MAX_SIZE

KCL_MAX_SIZE is together with KCL_MAX_TRI 1 criteria of 3 to abort the cube recursion. The recursion is aborted, the cube size is smaller or equal KCL_MAX_TRI and the number of triangles is smaller or equal KCL_MAX_TRI.

The user can set values in the range of 256..0x100000 (~1 million). The impact of this parameter for running a track is not clear now.

8.   Execution Order

Last not least the execution order. It's a logical explanation and some points are done is one step for optimization reasons.
  1. First the input file is loaded and analyzed. If it is a binary KCL file or a valid OBJ file, it is scanned and the data is transferred into the internal format. For OBJ files, the point swapping is done here. The CLIP calculations for binary files is also done. If parameter NEW is set, the read octree becomes invalid.
  2. If option --kcl-flag is set, the new flags are calculated.
  3. If the file has an octree (is a KCL file) and parameter DROP-UNUSED is set, the original octree is analyzed and all non referenced triangles are removed. The 'invalid' status of the octree is not changed.
  4. If option --kcl-script and parameter SCRIPT is set, the scripts are executed in the entered order. After execution:
    1. All triangle marked as 'REMOVED' are removed.
    2. If triangle points were modified or triangles were added or removed, the octree becomes invalid.
  5. If any DROP* (except DROP-UNUSED), RM-* or CONV-* is set, triangles are removed or converted. If at least one triangle is removed, and the octree becomes invalid.
  6. If parameter SORT is set, all triangles are sorted by length, coordinates and flags.
  7. If at least one of the options --shift, --scale, --xss, --yss, --zss or --hrot is set, the transformation is done and the octree becomes invalid.
  8. If option --kcl-script is set, but not parameter SCRIPT, the scripts are executed in the entered order. After execution:
    1. All triangle marked as 'REMOVED' are removed.
    2. If triangle points were modified and parameter SORT is set, all triangles are sorted again.
    3. If triangle points were modified or triangles were added or removed, the octree becomes invalid.
  9. The check status is generated.
  10. If an octree is needed, but is either invalid or not existent, then a new octree is created. The elimination of duplicate vertex or and normal vectors is done unless parameter FAST is set and the number of triangles is less than 16384 (0x1000).
  11. The output is processed. This is either creating a binary KCL file, or exporting to an OBJ file or printing any info dump.

A special optimization is done, if input and output are binary KCL and parameter NEW is not set and only KCL flags were changed: In this case, the changed flags are written to the original binary data and the modified binary data is written to the output file.