
                        * Neverball Mapping *


Neverball  environments are  defined using  GtkRadiant.   Knowledge of
GtkRadiant is  prerequisite to  this document.  Users  unfamiliar with
radiant usage  are encouraged to  study the radiant  documentation and
craft a  few maps  for Quake, Wolf,  or Half-Life before  attemping to
create content for Neverball.

GtkRadiant, documentation, and tutorials may be found at

    http://www.qeradiant.com



* CONTENTS

    - Overview          ... How Neverball compares to Quake et al
    - Setting Up        ... Getting GtkRadiant to work with Neverball
    - Tutorial          ... The map compilation process
    - Entities          ... Adding active elements to the map
    - Decals            ... Adding visual elements to the map
    - Adding Materials  ... Creating custom textures and materials
    - Level Shots       ... Snapping screenshots for level selection
    - Caveats           ... Problems and things to avoid



* OVERVIEW

So now that we all know  everything about Quake engine mapping, we can
go ahead and  forget most of it.  Neverball  mapping has significantly
fewer restrictions than Quake mapping.


Some of what you know from Quake mapping still applies:

  - Geometry  should  be  "caulked"  to minimize  polygon  count.   In
    Neverball,  the  caulking texture  is  called  "invisible" and  it
    appears within radiant as a white grid pattern.

  - Detail brushes add  visual complexity without adding computational
    complexity.  If  there is geometry  that the ball will  never hit,
    mark it as detail.

  - T-intersections cause polygon cracks, especially on low resolution
    displays.

  - Coincident faces cause Z-fighting.  This is a shooting offense.


Some of the important differences are as follows:

  - The scale  differs.  In  Quake there  are 8 units  to a  foot.  In
    Neverball there are  64 units to a meter.   The default major grid
    in radiant marks 64 units, so meters are easy to work with.

  - Neverball  maps need  not be  closed.  Neverball  environments are
    generally entirely visible  all of the time, so  all the attention
    paid to visibility by Quake becomes unnecessary.  Maps don't leak.

  - Brushes are refered to as  "lumps". They may overlap.  In fact, it
    is often advantageous to overlap lumps.

  - Shaders do not modify geometry.  The lumps you place are the lumps
    that the  ball impacts.  The  textures you apply are  the textures
    that appear in Neverball.

  - No curves.  Neverball physics doesn't consider them.

  - Most of Quake's  entities are meaningless in Neverball.   A few of
    them are used, but in modified form.  These are documented below.

  - No lights.  All lighting is dynamic.




* SETTING UP

Most any  version of  radiant will suffice.   To install  radiant, you
will need  to have  one of the  supported games installed.   Demos MAY
suffice.   For  this discussion,  we  assume  that  Quake 3  Arena  is
installed, and that it is located in

    /usr/local/games/quake3/

We assume that Neverball data directory is

    ~/neverball/data

This may change depending on how Neverball is installed.

We must  first make radiant  aware of the Neverball  materials.  Under
Linux, we can simply create a symbolic link from within the Quake data
directory to the within Neverball data directory.

    cd /usr/local/quake3/baseq3/

    ln -s ~/neverball/data/mtrl             textures/mtrl
    ln -s ~/neverball/data/mtrl/mtrl.shader scripts/mtrl.shader

Setup under Windows is similar, though it may be necessary to copy the
mtrl directory and mtrl.shader script into the Quake directory, rather
than use a shortcut.

Now, the  mtrl shaders should  appear in radiant's Textures  menu. You
may need to  set "shaderlist.txt only" to OFF  in the radiant Textures
menu.  Be sure that ONLY mtrl shaders are used for Neverball maps.



* TUTORIAL

Here we gloss over all the details and try to get custom geometry into
the game a quickly as possible.

Go ahead and create a simple  map.  Just toss in some brushes and plop
some mtrl shaders  down on them.  Forget the  entities for now, except
drop in one info_player_start.  Save the map anywhere.

Assume the  map is named funkyball.map.   Process it into  a .sol with
the following  command.  The first  file specified is the  input .map,
the second is the output .sol.  The third option gives the location of
the mtrl directory.  Output should be similar.

    mapc funkyball.map funkyball.sol ~/neverball/data

    mtrl  vert  edge  side  texc  geom  lump  path  node
       9   320   616   267   214   412    49     0     4
    body  coin  goal  view  jump  swch  ball  char  indx
       2    10     1     1     0     0     1    17  2070

To test  your map, add it  to a data/levels.txt file.  Include a level
shot path, a background path, and the level time in seconds.  Paths in
levels.txt  are  relative  to  the  data directory  (the  location  of
levels.txt). Then, run the game as normal.




* ENTITIES

Only  a few Quake  entities are  supported, and most of  the supported
entities behave differently in some way.  All unsupported entities and
unsupported  attributes  of   supported  entities  are  ignored.   The
Neverball  entities  follow.   All  applicable entity  attributes  are
documented here.

info_player_start

    The info_player_start entity defines a ball in a .sol file.  While
    multiple balls  may be defined,  Neverball uses only the  first of
    them.

    The  "radius" attribute  gives  the ball  radius  in meters.   The
    default radius is "0.25".

    The "origin" attribute gives the ball location.  The bottom of the
    entity in the editor will correspond  to the bottom of the ball in
    Neverball.

    Note  that the "angle"  attribute does  NOT determine  the initial
    facing direction.  The player begins each level looking down the Y
    axis.  If your level begins wrong, you must rotate your map.

info_player_deathmatch

    The info_player_deathmatch  entity defines a goal in  a .sol file.
    The  "radius" attribute  gives  the goal  radius  in meters.   The
    default radius is "0.75".  The ball must fall entirely within this
    radius to trigger a goal.

    The  "origin" attribute gives  the goal  location.  Like  the ball
    entity, the bottom  of the editor's entity box  will correspond to
    the base of the goal.

light

    The  light entity  defines a  coin in  a .sol  file.   The "light"
    attribute gives the  value of the coin.  Neverball  draws coins in
    denominations of 1, 5, and 10.

    The  "origin" attribute  gives  the coin  location.  Consider  the
    radius of your ball and place coins within reach from the floor.

path_corner

    The path_corner entity  defines a segment of the  path of a moving
    object.  The "origin" attribute gives the point location.

    The "targetname" attribute gives  the name by which other entities
    will refer to  this point.  The default name  generated by radiant
    is usually fine.

    The "target"  attribute gives the  destination of the  path.  This
    attribute may be  automatically specified using radiant's "Connect
    Entities" feature.  To make a path  from point A to point B, first
    select  path_corner A,  then  select path_corner  B, then  Connect
    Entities (control-k).

    The "speed"  attribute gives the  duration of the trip  along this
    path segment.  Note that this attribute has a different meaning to
    Neverball than it does to Quake.   In Quake, it gives the speed in
    units  per second.   In  Neverball  it gives  the  travel time  in
    seconds,  regardless of  the distance  between one  point  and the
    next.  The default is "1.0".

    The "state"  attribute determines whether the path  is enabled.  A
    func_train will only  move along an enabled path.   A train may be
    stopped and started by toggling the  state of the path to which it
    is attached.  "0" means no, "1" means yes. The default is 1.

    To  create a  pause  in  a path.   Simply  position two  connected
    path_corner entities at  the same point.  The trip  will have zero
    length but the object will  still spend "speed" seconds making the
    journey.


func_train

    The  func_train entity defines  the geometry  of a  moving object.
    Think  of it as  a container  or a  grouping mechanism  for lumps,
    rather than an object in-and-of itself.

    To create a func_train, first  select all of the brushes that form
    the moving object, then  select func_train from the entities popup
    (right click) menu.

    To assign  a func_train  to a path,  first select  the func_train,
    then select the first path_corner entity of the path, then Connect
    Entities.  Multiple func_trains may be assigned to one path.

    To destroy a func_train  leaving only the original brushes, select
    the  func_train, and  choose Ungroup  Entities from  the Selection
    menu.

    Note that func_trains are positioned differently in Neverball than
    in Quake.  Quake ignores the  placement of the func_train in space
    and requires  an origin specification.  Neverball  simply uses the
    location  of the  first path_corner  to define  the  origin.  When
    creating a  moving object, just place  it at the  beginning of its
    path and everything should work out.

target_teleporter

    The target_teleporter  entity defines a  teleporter.  The "radius"
    attribute gives the teleporter radius.  The default is "0.5".  The
    ball  must  fall  entirely  within  this  radius  to  trigger  the
    teleport.

    The "origin"  attribute gives the teleporter  location. Unlike the
    goal entity,  the center  of the editor's  entity box  defines the
    origin. So to define a  teleporter flush with the floor, embed the
    entity box halfway in the floor.

    The "target" attribute refers to a target_position entity defining
    the destination of the teleporter.

info_camp

    The  info_camp entity defines  a switch.   A switch's  behavior is
    similar to a teleporter.   The "radius" attribute gives the radius
    and defaults to "0.5".  The "origin" attribute gives the location.
    The "target"  attribute refers to the path_corner  that the switch
    controls.

    The "state" attribute gives the  initial state of the switch.  "0"
    is off, "1" is on.  The  default is off.  This parallels the state
    attribute of  the path_corner.  An info_camp  entity should always
    have the same initial "state" value as the path_corner it targets.

    The "timer" attribute defines a  delay time.  The time begins when
    a switch is toggled to  its non-initial state.  The switch toggles
    back to its  initial state when the timer  expires.  A timer value
    of zero indicates  an untimed switch.  The default  is zero.  This
    may be used  to define a door that opens only  for a moment before
    closing, or  a func_train  that moves along  its path  in discrete
    activated steps.

info_player_intermission

    The info_player_intermission entity defines the camera position at
    the beginning of a level fly-in.  The "origin" attribute gives the
    location, and the "target" attribute refers to the target_position
    defining the view direction.

target_position

    The target_position entity defines the initial view direction of a
    level fly-in,  as well  as the destination  of a  teleporter.  The
    "origin" attribute  gives the location.  To define  a two-way pair
    of teleporters, place the  target_position of each coincident with
    the target_teleporter of the other.

worldspawn

    The worldspawn  entity is  the root of  the world.   The "message"
    attribute gives the intro text  that appears as a level begins.  A
    '\' character in the text marks  the end of a line.  Limited space
    is available.  Wrapping text within  the intro text box is often a
    process of trial and error.



* DECALS

There are a number of occasions where you'll want to apply one texture
overtop another.  Examples include goals, jumps, switches, and arrows.
It's common  to have a  goal texture appearing  in green turf,  or red
turf, etc,  but it is inefficient  to use a different  texture map for
each ground/decal combination.

To accomplish  this, we  apply the decal  texture just above  the base
texture using a second lump.  Mark the top of this lump with the decal
texture and mark the other 5 sides with the invisible texture.

Position the decal  lump 1 unit above the base  lump.  Do not position
the top of the decal lump  coincident with the base lump, as this will
cause depth buffer artifacts.

Very important: mark the decal  lump as detail using the "Make Detail"
menu item.   If the decal  lump is allowed  to be structural  then the
ball will bump into it, as it is 1/64th of a meter from the floor.



* ADDING MATERIALS

Neverball  uses  the standard  OpenGL  lighting  model  rather than  a
script-based shading system  like Quake's.  So, to add  a new material
you  must  create  both  a   texture  image  and  an  OpenGL  material
specification.

1)  The texture  must be an  image in JPEG  format.  It may  come from
    anywhere.  Its width and height must both be powers of two.

    For  this  discussion, let  us  assume  you  have an  image  named
    wood.jpg.  Place in it mtrl/.

2)  Create a material file in mtrl/, in this case mtrl/wood. This name
    must match the texture name, minus the image suffix. The file must
    contain 17 values,  explained below.  If you don't  care about the
    material  properties, the  following  values suffice  in most  any
    case.

       1.0 1.0 1.0 1.0
       1.0 1.0 1.0 1.0
       0.2 0.2 0.2 1.0
       0.0 0.0 0.0 1.0
       0.0

Do a "Flush & Reload Shaders"  in radiant and your new material should
appear among the mtrl shaders.


Those 17  values define the material  in terms of  the stardard OpenGL
material model.  They define not only  the color of  the material, but
how it reacts  to different types of lighting  and different points of
view.  Their meaning is a follows:

  - The first line  gives the diffuse material color  (R G B A).  This
    is  the basic  color of  the material  resulting  from directional
    light falling upon it.  The fourth component is the alpha channel.
    0 is transparent, 1 is opaque.

  - The second  line gives  the ambient material  color. It  gives the
    color  of the  material  resulting from  nondirectional light.  It
    doesn't make much of a contribution in practice.

  - The third  line gives  the specular material  color.  This  is the
    color of the material  when directional light is glinting directly
    off of it into the eye of  the user. A bright white here will make
    an object look shiny, while a  darker color will give the object a
    matte appearance.

  - The  fourth line gives  the emissive  material color.   This color
    contributes  to the  appearance of  the object  regardless  of the
    light falling  upon it.  A bright  color here will  make an object
    appear to glow in darkness, or at least appear to be unaffected by
    external light.

  - The  fifth  line gives  the  material  shinyness.  Simply put,  it
    defines the size of the  specularity on an object.  0 will produce
    a dull finish, while 128 will produce a very tight specularity.
 
The five of  these togather determine the base  color of the material.
This base color is then blended with (added to) the texture color.



* LEVEL SHOTS

A level shot is a screenshot of  a level without the ball or any coins
visible.  It is used to preview a level in the level selection screen.
Level shots are  listed along with their SOL  files, background files,
etc in  the levels.txt  file. There  are two ways  to acquire  a level
shot: per level, and per set.

To acquire a single level shot, press F12 at the level's intro screen.
This will clear  the hud and all entities.  Then, press  F10 to take a
screenshot normally.   Rename the screenshot as needed  and prepare it
as described below.

To capture  level shots for an  entire set, go to  the set's selection
screen  and press  F12.   This  will iterate  through  all levels  and
automatically take a screenshot of each.  The resulting BMP files will
have the same name as the  source SOL file as listed in the levels.txt
file.

NOTE: If  the SOL file has  the name "sol/foo.sol"  then the resulting
screenshot  will have  the name  "sol/foo.bmp".  Thus, if  your normal
screenshot  directory is  your home  directory, you  must  ensure that
$(HOME)/sol exists and that the level shots may be written there.

To be usable  in level selection, a level  shot must have power-of-two
size.  Screenshots  generally don't,  thus they must  be non-uniformly
scaled.   256x256 is  usually a  good choice.   JPG is  usally  a good
format, as it  is compact.  Both the size and format  of the image are
optional.

The author uses  the following ImageMagick command line  to convert an
entire set of level shots to JPG.

    mogrify -resize 256x256! -format jpg -quality 90 *.bmp



* CAVEATS

The Neverball physics  engine can take pretty much  anything you throw
at it without breaking down, but there are a few problem areas.

If a  ball gets squished by a  moving object, it will  probably end up
moving  into  and  through  a  solid, possibly  getting  stuck  there.
There's just no  easy solution to this problem.  The physical analogue
would be  to have the offending  moving object stop  moving.  But then
what?   Nothing  moves, nothing  changes,  and  the problem  certainly
doesn't resolve itself.

Currently, the best solution is to stick with the unreal behavior.  At
least it keeps things  moving.  Mappers should actively avoid creating
situations in which this unreal behavior is made apparent.

  - If you have an elevator moving  up and down, prevent the ball from
    standing  underneath.   Either make  the  elevator  shaft a  solid
    (potentially invisible) object, or make it a bottomless pit.

  - If  you have platforms  moving horizontally,  for example  a ferry
    across a gap, ensure that a ball falling off the platform into the
    gap falls all the way out of the platform's path by making the gap
    deep.

  - If you have a Quake-ish crusher, delete it.  There's just no place
    for  something like  that in  Neverball because  the  ball doesn't
    "die", it merely falls.


Have fun.  Problems?  Contact <rlk@snth.net>
