# libs3d - The S3D API

## Using the s3d library

### Setting s3d up

Install the lib using the usual usual mechanism:

     cmake .
     make
     make install

You might need to have superuser rights in order to do make install. You should now have the server, the library and some applications installed somewhere.

### Getting started

After having s3d installed, you can write your own s3d programs (yeah, that is what this guide is about ;)

     #include <s3d.h>

should be enough to access the 3d functions. If you want to use keyboard interaction, do

     #include <s3d_keysym.h>

for the keycode table. Now you can compile your program with

     bash$  gcc program.c -ls3d -o program
     That wasn't that hard, wasn't it?

## function reference

### s3d_init

    #include <s3d.h>

int `s3d_init` int *argc, char ***argv, const char *name

This will initialize the s3d-library and the connection to the Server. It will return 0 on success in Server initializion. name specifies the your programs name.

    int main(char argc, char **argv)
    {
    	if (!s3d_init(&argc, &argv, "Hello world"))
    	{
    		...
    		s3d_quit();
    	}
    	return(0);
    }

### s3d_quit

    #include <s3d.h>

int `s3d_quit` void

closes the connection and cleares the event-stack. it can also be used to leave the s3d_mainloop.

### s3d_usage

    #include <s3d.h>

void `s3d_usage` void

Prints the possible parameter for the client library (which can be passed in s3d_init())

### s3d_mainloop

    #include <s3d.h>

int `s3d_mainloop` void (*f)(void)

takes a function as argument. it will loop this function until a quit-event is received. you can pass NULL if you have no function to be looped, but its better to sleep some time if you have nothing to do anyway to save cpu-time.

    void mainloop()
    {
        usleep(1000); // sleep 1 ms in every cycle
    }
    ...

    s3d_mainloop(mainloop());

### s3d_push_vertex

    #include <s3d.h>

int `s3d_push_vertex` int object, float x, float y, float z

pushes a vertex onto the vertex stack. make sure that you count how many vertices you've pushed because you'll need that for referencing when you push your polygons.

### s3d_push_vertices

    #include <s3d.h>

int `s3d_push_vertices` int object, const float *vbuf, uint16_t n

push some vertices from an array. that's much better for performing than using s3d_push_vertex() if you have a lot of vertices (and that's probably the usual case).

    float vertices[] = { 0.0, 0.0, 0.0,
                         1.0, 2.0, 3.0,
                         3.0, 2.0, 1.0};
    s3d_push_vertices(object, vertices, 3); /* pushing 3 vertices */

### s3d_push_material

    #include <s3d.h>

int `s3d_push_material` int object, float amb_r, float amb_g, float amb_b, float spec_r, float spec_g, float spec_b, float diff_r, float diff_g, float diff_b

pushes a material for an object. you will have to count them yourself too, as polygons will ask for the material index number. the material properties are given in rgb (red/green/blue) color codes, in float. 0.0 is the minimum, 1.0 is the maximum a color value can be. the specular color is the color which is directly reflected from the light source. the diffuse color is the color which can be seen in the bright side of the object, and the ambience color is the color of the shadow side of the object.

### s3d_push_material_a

    #include <s3d.h>

int `s3d_push_material_a` int object, float amb_r, float amb_g, float amb_b, float amb_a, float spec_r, float spec_g, float spec_b, float spec_a, float diff_r, float diff_g, float diff_b, float diff_a

Same as s3d_push_material, but color has alpha value added. Use s3d_push_materials_a() if you have a lot of materials to push.

### s3d_push_materials_a

    #include <s3d.h>

int `s3d_push_materials_a` int object, const float *mbuf, uint16_t n

Pushes a buffer of Materials. Those Materials are in the format float[n*12], with

- mbuf[n*12 + 0-3] - ambience

- mbuf[n*12 + 4-7] - specular

- mbuf[n *12 + 8-11] - diffusion values

of each entry. n is the number of materials pushed. The values are in the order r,g,b,a. If you only want to push one material, use the more easy s3d_push_material_a() function.

    /* each line has r,g,b,a value */
    float bla[24]=
    	{1, 0, 0, 1,
    	 1, 0, 0, 1,
    	 1, 0, 0, 1,
    	 0, 1, 1, 1,
    	 0, 1, 1, 1,
    	 0, 1, 1, 1};

    s3d_push_materials_a(object, mbuf, 2); /* push a red and a cyan material */

### s3d_push_polygon

    #include <s3d.h>

int `s3d_push_polygon` int object, uint32_t v1, uint32_t v2, uint32_t v3, uint32_t material

push one polygon on the polygonstack of the object. it takes 3 vertex-index- numbers and one material material-index-nr. as argument.

    int oid=s3d_new_object();   /* create a new object */
    s3d_push_vertex(oid, 0.0, 0.0, 0.0);
    s3d_push_vertex(oid, 0.0, 1.0, 0.0);
    s3d_push_vertex(oid, 1.0, 0.0, 0.0);
    s3d_push_material(oid, 0.3, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0);
    s3d_push_polygon(oid, 0, 1, 2, 0);
    /* this will create a red polygon */

### s3d_push_polygons

    #include <s3d.h>

int `s3d_push_polygons` int object, const uint32_t *pbuf, uint16_t n

as for vertices, you can push arrays of polygons to have greater performance. the pbuf should contain n polygons which consist of 4 uint32_t values of 3 vertices indices and 1 material index.

    uint32_t pbuf[] = { 0, 1, 2, 0};
    int oid=s3d_new_object();   /* create a new object */
    s3d_push_vertex(oid, 0.0, 0.0, 0.0);
    s3d_push_vertex(oid, 0.0, 1.0, 0.0);
    s3d_push_vertex(oid, 1.0, 0.0, 0.0);
    s3d_push_material(oid, 0.3, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0);
    s3d_push_polygons(oid, pbuf, 1);
    /* push one polygon with the pbuf data */

### s3d_push_line

    #include <s3d.h>

int `s3d_push_line` int object, uint32_t v1, uint32_t v2, uint32_t material

Push one line on the linestack of the object. It takes 2 vertex-index- numbers and one material material-index-nr. as argument. If you have a lot of lines to push, use s3d_push_lines()

### s3d_push_lines

    #include <s3d.h>

int `s3d_push_lines` int object, const uint32_t *lbuf, uint16_t n

Pushing n lines on the linestack of the object, each lbuf has a size of n*3, each entry has the index number of the first vertex, second vertex and material number just as in s3d_push_line().

### s3d_push_texture

    #include <s3d.h>

int `s3d_push_texture` int object, uint16_t w, uint16_t h

Adds a new texture with height w and height h on the texturestack.

### s3d_push_textures

    #include <s3d.h>

int `s3d_push_textures` int object, const uint16_t *tbuf, uint16_t n

As for vertices, you can push arrays of textures on the texture stack to have greater performance. The tbuf should contain n texture sizes which consist of 2 uint16_t values for width and height for each texture.

### s3d_pop_vertex

    #include <s3d.h>

int `s3d_pop_vertex` int object, uint32_t n

Deletes the latest n vertices from the vertex stack of the object.

### s3d_pop_polygon

    #include <s3d.h>

int `s3d_pop_polygon` int object, uint32_t n

Deletes the latest n polygon from the polygon stack of the object.

### s3d_pop_material

    #include <s3d.h>

int `s3d_pop_material` int object, uint32_t n

Deletes the latest n material from the material stack of the object.

### s3d_pop_texture

    #include <s3d.h>

int `s3d_pop_texture` int object, uint32_t n

Deletes the latest n textures from the texture stack of the object.

### s3d_pop_line

    #include <s3d.h>

int `s3d_pop_line` int object, uint32_t n

Deletes the latest n lines from the line stack of the object.

### s3d_pep_polygon_normals

    #include <s3d.h>

int `s3d_pep_polygon_normals` int object, const float *nbuf, uint16_t n

Adds normal information to polygons, giving each vertex of a polygon a normal information. With this, you can achieve smoothed edge effects.

nbuf should contain n * 9 float values, for each vertex a normal vector (x,y,z), and you have 3 Vertices for each Polygon so that makes 9 float values per Polygon in Total. Don't worry if you don't use this, it's kind of hard to calculate and the server will always use some proper normal values (same for every vertex, calculated by the plane which is defined by the 3 points of the polygon.

### s3d_pep_polygon_tex_coord

    #include <s3d.h>

int `s3d_pep_polygon_tex_coord` int object, float x1, float y1, float x2, float y2, float x3, float y3

Pimp the last polygon pushed with some textures coordinates, x and y values for each vertex point respectively. Those values may be between 0 and 1 and are vertex points on the texture defined in the material of the polygon. If you have more polygons which should get a texture, use s3d_pep_polygon_tex_coords()

### s3d_pep_polygon_tex_coords

    #include <s3d.h>

int `s3d_pep_polygon_tex_coords` int object, const float *tbuf, uint16_t n

Pimp the latest n polygons with texture coordinates. tbuf has 6*n float values for its entries, which are supplied in the order as in s3d_pep_polygon_tex_coord()

### s3d_pep_material_texture

    #include <s3d.h>

int `s3d_pep_material_texture` int object, uint32_t tex

Assign the latest material a texture referenced by the index tex. Of course, you will have pushed this texture with s3d_push_texture

### s3d_pep_vertex

    #include <s3d.h>

int `s3d_pep_vertex` int object, float x, float y, float z

Alter the latest pushed vertex, overwriting with the supplied values.

### s3d_pep_vertices

    #include <s3d.h>

int `s3d_pep_vertices` int object, const float *vbuf, uint16_t n

Alter the latest n pushed vertex. vbuf holds the values which are used to overwrite the old data, n entries with each 3 floats specifying x,y,z of the vertices.

### s3d_pep_line

    #include <s3d.h>

int `s3d_pep_line` int object, int v1, int v2, int material

Alter the latest pushed line, overwriting with the supplied values.

### s3d_pep_lines

    #include <s3d.h>

int `s3d_pep_lines` int object, const uint32_t *lbuf, uint16_t n

Alter the latest n pushed lines. lbuf holds the values which are used to overwrite the old data, n entries with each 3 uint32_t specifying first, second vertex and material of each line.

### s3d_pep_line_normals

    #include <s3d.h>

int `s3d_pep_line_normals` int object, const float *nbuf, uint16_t n

Adds normal information to lines, giving each vertex of a line a normal information. This makes lines somewhat nicer, you'll need that especially when you're going to build wireframe models.

nbuf should contain n * 6 float values, for each vertex a normal vector (x,y,z), and you have 2 Vertices for each line so that makes 6 float values per line in Total.

### s3d_load_line_normals

    #include <s3d.h>

int `s3d_load_line_normals` int object, const float *nbuf, uint32_t start, uint16_t n

Just as s3d_pep_line_normals(), with the difference you won't alter the latest n lines but n lines starting with index start.

### s3d_pep_material

    #include <s3d.h>

int `s3d_pep_material` int object, float amb_r, float amb_g, float amb_b, float spec_r, float spec_g, float spec_b, float diff_r, float diff_g, float diff_b

Overwriting the latest pushed Material, overwriting the current value with the specified one. See s3d_pep_materials_a if you want to pep more materials.

### s3d_pep_material_a

    #include <s3d.h>

int `s3d_pep_material_a` int object, float amb_r, float amb_g, float amb_b, float amb_a, float spec_r, float spec_g, float spec_b, float spec_a, float diff_r, float diff_g, float diff_b, float diff_a

Overwriting the latest pushed Material, overwriting the current value with the specified one, with alpha value in contrast to s3d_pep_material See s3d_push_materials_a if you want to pep more materials.

### s3d_pep_materials_a

    #include <s3d.h>

int `s3d_pep_materials_a` int object, const float *mbuf, uint16_t n

Alters the last n pushed Materials. See s3d_push_materials_a() for more information how mbuf should look like. Use s3d_pep_material_a() if you only want to alter the latest material.

### s3d_load_materials_a

    #include <s3d.h>

int `s3d_load_materials_a` int object, const float *mbuf, uint32_t start, uint16_t n

Loads n materials starting from index position start into the Material stack. See s3d_push_materials_a for more informatino about the values in mbuf.

### s3d_load_polygon_normals

    #include <s3d.h>

int `s3d_load_polygon_normals` int object, const float *nbuf, uint32_t start, uint16_t n

Just as s3d_pep_polygon_normals(), with the difference you won't alter the latest n polygons but n polygons starting with index start.

### s3d_load_polygon_tex_coords

    #include <s3d.h>

int `s3d_load_polygon_tex_coords` int object, const float *tbuf, uint32_t start, uint16_t n

Just as s3d_pep_polygon_tex_coords(), with the difference you won't alter the latest n polygons but n polygons starting with index start.

### s3d_load_texture

    #include <s3d.h>

int `s3d_load_texture` int object, uint32_t tex, uint16_t xpos, uint16_t ypos, uint16_t w, uint16_t h, const uint8_t *data

This will load an 32bit rgba image supplied in data at position xpos,ypos of the texture tex. The image has the width w and height h. This can be used to update only parts of the texture. It's no problem to supply big textures, as the image will be sent to server in fragments. Of course, you will have created the texture with s3d_push_texture, have an material assigned to the texture with s3d_pep_material_texture() and have your polygons set sane polygon texture coords using s3d_pep_polygon_tex_coord().

### s3d_new_object

    #include <s3d.h>

int `s3d_new_object` void

Creates a new object, returning the object id.

Of course, you won't forget to toggle it visible, won't you?

### s3d_del_object

    #include <s3d.h>

int `s3d_del_object` int oid

Deletes the object referenced by oid.

### s3d_clone

    #include <s3d.h>

int `s3d_clone` int oid

Clones an already exisiting object. They get just look the same as the parent-object and will change when the parent-object changes. Cloning especially makes sense if you want to use the same object a lot of times. Move and transform is independent from the parent. The function returns the childs object id.

### s3d_clone_target

    #include <s3d.h>

int `s3d_clone_target` int oid, int toid

Changes the clone target of oid to another object (toid). This assumes you've got oid from s3d_clone before.

### s3d_link

    #include <s3d.h>

int `s3d_link` int oid_from, int oid_to

A linked object will move along with it's link parent. For example if you have a book on a table, you can link the book to the table so the book will "keep on the table" if you move the table around in space. It will also rotate with the table etc.

### s3d_unlink

    #include <s3d.h>

int `s3d_unlink` int oid

Remove the link of object oid to its target.

### s3d_import_model_file

    #include <s3d.h>

int `s3d_import_model_file` const char *fname

Imports an 3d object file and returns the object number. Quite a number of formats are supported, like 3D Studio (.3ds, .prj), Lightwave (.lw, .lwb, .lwo), Quake Models (.md3), or simply everything libg3d supports. :)

Of course, you won't forget to toggle it visible, won't you?

### s3d_select_font

    #include <s3d.h>

int `s3d_select_font` const char *mask

This selects a font for the s3d_draw_string() function.

Of course, you won't forget to toggle it visible, won't you?

        s3d_select_font("vera"); /* will use the vera font face */

### s3d_draw_string

    #include <s3d.h>

int `s3d_draw_string` const char *str, float *xlen

Renders the string str with in Truetype format with the height 1, returns the length of the rendered string in *xlen (or set len=NULL to disable this).

    	char str="hello world!";
    	float len;
    	s3d_select_font("vera");
    	s3d_draw_string(str, len);

    	/* not interested in the length? do that:
    	 * s3d_draw_string(str, NULL); */

### s3d_strlen

    #include <s3d.h>

float `s3d_strlen` const char *str

Returns the length of the string if it were rendered with the currently selected font. That might be useful to estimate the size used for a text and render the background or bounding box before inserting the text.

### s3d_open_file

    #include <s3d.h>

int `s3d_open_file` const char *fname, char **pointer

This opens the file fname, setting *pointer to it's memory position. the function will return the size of buffer. you can free() the pointer when you're finished.

### s3d_flags_on

    #include <s3d.h>

int `s3d_flags_on` int object, uint32_t flags

turn some flags on for object.

if you don't toggle OF_VISIBLE on, you won't see your object. usually you want this. (at least after you *push()d all your content)

### s3d_flags_off

    #include <s3d.h>

int `s3d_flags_off` int object, uint32_t flags

turn some flags off for object.

### s3d_translate

    #include <s3d.h>

int `s3d_translate` int object, float x, float y, float z

Move the object to some position in space. when you create an object, it's always located at 0.0 , 0.0, 0.0.

Translation is absolute, not relative!

    s3d_translate(object, 2, 0, 0);
    s3d_translate(object, 4, 0, 0);
    /* object will end up at 4,0,0 and not 6,0,0!! */

### s3d_rotate

    #include <s3d.h>

int `s3d_rotate` int object, float x, float y, float z

rotate an object around the x, y and z-axis respectively. x,y,z may have values between [0,360] degrees.

You will usually only rotate around one axis, leaving the unused fields on 0, I guess. If you want to rotate around more than one axis, please note: The order of the rotation applies is y-axis, x-axis, and then z-axis. You can think of it as the earth position coordinates: x is the longitude, y is the latitude, and z is the rotation at this point of the earth around your bodies axis. (I wonder if that makes it any clearer ;)

Rotate is absolute, not relative!

    s3d_rotate(object, 90,  0, 0);
    s3d_rotate(object, 180, 0, 0);
    /* object will be rotated 180 degrees around the x-axis, not 270 degress! */

### s3d_scale

    #include <s3d.h>

int `s3d_scale` int object, float s

Scales the object. about factor s. s=1 will be the original size, -1 will mirror it.

s=0 is forbidden and will be ignored! s3d_scale is also absolute, not relative!

### s3d_push_event

    #include <s3d.h>

void `s3d_push_event` struct s3d_evt *newevt

Pushes an event onto the event-stack. Usually you don't need to do this manually.

### s3d_pop_event

    #include <s3d.h>

struct s3d_evt *`s3d_pop_event` void

Pops the latest event from the stack. Don't forget to free() both the event and its buffer! Returns a pointer to struct s3d_evt.

### s3d_find_event

    #include <s3d.h>

struct s3d_evt *`s3d_find_event` uint8_t event

Finds the latest occurence of an event, giving the event type as argument. Returns a pointer to struct s3d_evt.

### s3d_delete_event

    #include <s3d.h>

int `s3d_delete_event` const struct s3d_evt *devt

deletes an event, the argument is the pointer to the event which is to be deleted (maybe obtained from s3d_find_event).

### s3d_set_callback

    #include <s3d.h>

void `s3d_set_callback` uint8_t event, s3d_cb func

sets a callback for a certain event. this is very useful for event-oriented applications. event callbacks will not interrupt each other or the mainloop.

Defining callbacks will only work after calling s3d_init()

     #include <inttypes.h>

    void obj_click(struct s3d_evt event)
    {
    	printf("object id %"PRIu32" got clicked", *((uint32_t *)event->buf));
    }
    ...
    	s3d_set_callback(S3D_EVENT_NEW_OBJECT, obj_click);

    /* this will tell you when a object got clicked */

### s3d_ignore_callback

    #include <s3d.h>

void `s3d_ignore_callback` uint8_t event

Sets the callback on ignore, that means it won't be queued up for later use. An incoming event of this type will simply be skipped.

### s3d_clear_callback

    #include <s3d.h>

void `s3d_clear_callback` uint8_t event

Clears the callback which is associated with the event.

### s3d_get_callback

    #include <s3d.h>

s3d_cb `s3d_get_callback` uint8_t event

Returns the Callback-function of the event.

    	struct s3d_evt e;
    	...
    	s3d_get_callback(S3D_EVENT_KEY)(e);
    	/* will call the key-handling function with argument e.  */

### s3d_process_stack

    #include <s3d.h>

void `s3d_process_stack` void

This function goes through all function of the event-stack and will call functions. this is useful when you define a new function but still have a lot of events of this type on the stack.

This is probably obsolete

### s3d_vector_length

    #include <s3d.h>

float `s3d_vector_length` const float vector[]

Calculates and returns the length of the given vector (which should be of the type float[3]). More info on wikipedia.

### s3d_vector_subtract

    #include <s3d.h>

void `s3d_vector_subtract` const float vector1[], const float vector2[], float result_vector[]

Subtracts vector1 from vector2, writing result into result_vector. All vectors should have the format float[3]. More info on wikipedia.

### s3d_vector_dot_product

    #include <s3d.h>

float `s3d_vector_dot_product` const float vector1[], const float vector2[]

Calculates and returns the dot product of vector1 and vector2. All vectors should have the format float[3]. More info on wikipedia.

### s3d_vector_cross_product

    #include <s3d.h>

void `s3d_vector_cross_product` const float vector1[], const float vector2[], float result_vector[]

Calculates and returns the cross product of vector1 and vector2. All vectors should have the format float[3]. More info on wikipedia.

### s3d_vector_angle

    #include <s3d.h>

float `s3d_vector_angle` const float vector1[], const float vector2[]

Calculates and returns the angle between vector1 and vector2. Please note that the resulting angle is between 0 and PI, therefore not covering the whole period! To convert in degrees just do result*180/M_PI. All vectors should have the format float[3]. More info on wikipedia.

### s3d_angle_to_cam

    #include <s3d.h>

float `s3d_angle_to_cam` const float obj_pos[], const float cam_pos[], float *angle_rad

Given obj_pos and cam_pos in the format float[3], angle_rad about which angle the object should be rotated around the y-axis so that it faces the camera. This might become handy if you have some text floating in space and want it to face the camera.

### s3d_mcp_focus

    #include <s3d.h>

int `s3d_mcp_focus` int object

This is an mcp-only function. It gives focus (for receiving key-strokes etc.) to an app referenced by it's mcp-object-id.

### s3d_net_check

    #include <s3d.h>

int `s3d_net_check` void

This functions is for programs which do not employ a mainloop, hence they need to check for new events on their own. Programs like these must make sure to call this function from time to time to convince the server that they did not freeze or bail out.

## Data types

### struct s3d_but_info

    struct s3d_obj_info {
    	uint32_t object;
    	uint32_t flags;
    	float trans_x, trans_y, trans_z;
    	float rot_x, rot_y, rot_z;
    	float scale;
    	float r;
    	char name[256];
    };

Can be used on the buffer of an event of type S3D_EVENT_OBJ_INFO. name will usually contain nothing for usual objects, but mcp objects will contain the applications names here. r is the radius of the convex sphere an object, which will also be interesting for the mcp.

Special objects like camera, pointer will have the "sys_" prefix in the name and will be named "pointer0", "pointer1" ... or "cam0", "cam1" ... For cam object, scale will contain the aspect ratio.

### struct s3d_but_info

    struct s3d_but_info {
    	uint8_t button;
    	uint8_t state;
    };

Can be used on the buffer of an event of type S3D_EVENT_MBUTTON.

### struct mcp_object

    struct mcp_object {
    	uint32_t object;
    	float trans_x, trans_y, trans_z;
    	float r;
    	char name[256];
    };

obsolete, deprecated, don't use, to be removed soon (use struct s3d_but_info). ;)

### struct s3d_evt

    struct s3d_evt {
    	uint8_t event;
    	int length;
    	char *buf;
    	struct s3d_evt *next;
    };

This is the event information holder.

event

  gives the event type

length

  gives the length of the buffer *buf

*buf

  is the pointer to the multiple purpose buffer, which will have more specific information about the object

*next

  can be safely ignored ;)

Depending on the event, buf can contain the keycode pressed on keyboard event, the mouse button state on a mouse event, object information etc.

### typedef s3d_cb

    typedef void (*s3d_cb)(struct s3d_evt *);

This defines the callback format. Each callback should return void and take an argument of struct s3d_evt *. Callbacks can be defined with s3d_set_callback().

    /* a callback handler could look like this: */
    void my_key_handler(struct s3d_evt *event_data)
    {
    	...
    }

## Definitions

### S3D events

This defines the callback format. Each callback should return void and take an argument of struct s3d_evt *. Callbacks can be defined with s3d_set_callback().

S3D_EVENT_OBJ_CLICK

  An object got clicked (when you set the flag S3D_OF_SELECTABLE), buf will contain the object id of the object which got clicked (uint32_t)

S3D_EVENT_KEY

  A key was pressed, buf will contain a keycode. use #include <s3d_keysym.h> to have the keycodes available. buf is a 2 byte unsigned short keycode.

S3D_EVENT_MBUTTON

  A mouse button was clicked. Use struct s3d_but_info on buf to get more info.

S3D_EVENT_NEW_OBJECT

  deprecated, will use S3D_EVENT_OBJ_INFO

S3D_EVENT_OBJ_INFO

  Something happened to an object. This can happen if the camera was moved, the mouse (pointer) was moved or an application appeared/changed in the mcp

S3D_MCP_OBJECT

  As the name suggests, those will only happen to the MCP. This tells it about new/changed application object. struct mcp_object can be used on buf. To be removed in the future.

S3D_MCP_DEL_OBJECT

  As the name suggests, those will only happen to the MCP. This tells it about deleted application object. struct mcp_object can be used on buf. To be removed in the future.

S3D_EVENT_QUIT

  Server sent the quit signal, or the connection was terminated. Usually, this is only processed internally.

    /* a callback handler could look like this: */
    void my_key_handler(struct s3d_evt *event_data)
    {
    	...
    }

### S3D Object Flags

Objects can have several flags to change their behaviour in the server and can be set with s3d_flags_on() and s3d_flags_off()

S3D_OF_VISIBLE

  default:off

  Obviously, if this flag is toggled the user can see it, if not it will be hidden. ;)

  When an object is created it's turned off, so you will be able push your geometry data and turn it on after you're done. That avaoids flickering and stuff.

S3D_OF_SELECTABLE

  default:off

  When this is toggled on, you will receive click events. Don't use it if you don't need it, it will eat performance.

S3D_OF_POINTABLE

  default:off

  Placeholder for pointer (onmouseover-event enabler) events. Not implemented yet.

## Additional Notes

### About alpha transparency

Alpha transparency works, but polygons don't get ordered in view direction on the server yet. So please don't use this feature yet. If you have an easy idea how to do that with opengl please drop me a line.