[PD-cvs] externals/pdp/opengl/modules Makefile, 1.2, 1.3 README, 1.2, 1.3 pdp_3d_color.c, 1.2, 1.3 pdp_3d_context.c, 1.2, 1.3 pdp_3d_dlist.c, 1.2, 1.3 pdp_3d_draw.c, 1.2, 1.3 pdp_3d_drawmesh.c, 1.2, 1.3 pdp_3d_for.c, 1.2, 1.3 pdp_3d_light.c, 1.2, 1.3 pdp_3d_push.c, 1.2, 1.3 pdp_3d_snap.c, 1.2, 1.3 pdp_3d_state.c, 1.2, 1.3 pdp_3d_subcontext.c, 1.2, 1.3 pdp_3d_view.c, 1.2, 1.3 pdp_3d_windowcontext.c, 1.2, 1.3

Hans-Christoph Steiner eighthave at users.sourceforge.net
Fri Dec 16 02:05:37 CET 2005


Update of /cvsroot/pure-data/externals/pdp/opengl/modules
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6756/opengl/modules

Added Files:
	Makefile README pdp_3d_color.c pdp_3d_context.c pdp_3d_dlist.c 
	pdp_3d_draw.c pdp_3d_drawmesh.c pdp_3d_for.c pdp_3d_light.c 
	pdp_3d_push.c pdp_3d_snap.c pdp_3d_state.c pdp_3d_subcontext.c 
	pdp_3d_view.c pdp_3d_windowcontext.c 
Log Message:
checking in pdp 0.12.4 from http://zwizwa.fartit.com/pd/pdp/pdp-0.12.4.tar.gz

--- NEW FILE: pdp_3d_color.c ---
/*
 *   Pure Data Packet module.
 *   Copyright (c) by Tom Schouten <pdp at zzz.kotnet.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */


#include <GL/gl.h>
#include "pdp_3dp_base.h"
#include "pdp_opengl.h"


typedef struct _color_command
{
    t_pdp_dpd_command x_base;
    int x_context;
    float x_newcolor[4];
    float x_oldcolor[4];
} t_color_command;

typedef struct _pdp_3d_color
{
    t_pdp_3dp_base x_base;
    t_pdp_dpd_commandfactory x_cfact;

    float x_red;
    float x_green;
    float x_blue;
    float x_alpha;

} t_pdp_3d_color;



/* COMMAND METHODS */
static void pdp_3d_color_process_right(t_color_command *x)
{
    int p = x->x_context;
    if (pdp_packet_3Dcontext_isvalid(p)){
	pdp_packet_3Dcontext_set_rendering_context(p);

	/* save old color*/
	glGetFloatv(GL_CURRENT_COLOR, x->x_oldcolor);

	/* set new color */
	glColor4fv(x->x_newcolor);
    }

}

static void pdp_3d_color_process_left(t_color_command *x)
{
    int p = x->x_context;
    if (pdp_packet_3Dcontext_isvalid(p)){
	pdp_packet_3Dcontext_set_rendering_context(p);

	/* restore old color */
	glColor4fv(x->x_oldcolor);
	//glColor4f(1,1,1,1);
    }
    /* kill self */
    pdp_dpd_command_suicide(x);
}


/* PD OBJECT METHODS */
static void *pdp_3d_color_get_new_command(t_pdp_3d_color *x)
{
    t_color_command *c = (t_color_command *)pdp_dpd_commandfactory_get_new_command(&x->x_cfact);
    c->x_newcolor[0] = x->x_red;
    c->x_newcolor[1] = x->x_green;
    c->x_newcolor[2] = x->x_blue;
    c->x_newcolor[3] = x->x_alpha;
    c->x_context = pdp_3dp_base_get_context_packet(x);
    return (void *)c;
}


static void pdp_3d_color_set_r(t_pdp_3d_color *x, t_floatarg f) {x->x_red = f;}
static void pdp_3d_color_set_g(t_pdp_3d_color *x, t_floatarg f) {x->x_green = f;}
static void pdp_3d_color_set_b(t_pdp_3d_color *x, t_floatarg f) {x->x_blue = f;}
static void pdp_3d_color_set_a(t_pdp_3d_color *x, t_floatarg f) {x->x_alpha = f;}


t_class *pdp_3d_color_class;


void pdp_3d_color_free(t_pdp_3d_color *x)
{
    pdp_3dp_base_free(x);
}

void *pdp_3d_color_new(t_floatarg r, t_floatarg g, t_floatarg b, t_floatarg a)
{
    t_pdp_3d_color *x = (t_pdp_3d_color *)pd_new(pdp_3d_color_class);

    /* super init */
    pdp_3dp_base_init(x);


    /* input */
    pdp_base_add_gen_inlet(x, gensym("float"), gensym("r"));
    pdp_base_add_gen_inlet(x, gensym("float"), gensym("g"));
    pdp_base_add_gen_inlet(x, gensym("float"), gensym("b"));
    pdp_base_add_gen_inlet(x, gensym("float"), gensym("a"));

    /* output */
    pdp_3dp_base_add_outlet(x, (t_pdp_method)pdp_3d_color_process_left, 0);
    pdp_3dp_base_add_outlet(x, (t_pdp_method)pdp_3d_color_process_right, 0);

    x->x_red = r;
    x->x_green = g;
    x->x_blue = b;
    x->x_alpha = a;

    /* init factory */
    pdp_dpd_commandfactory_init(&x->x_cfact, sizeof(t_color_command));

    /* register command factory method */
    pdp_dpd_base_register_command_factory_method(x, (t_pdp_newmethod)pdp_3d_color_get_new_command);

    return (void *)x;
}


#ifdef __cplusplus
extern "C"
{
#endif


void pdp_3d_color_setup(void)
{


    pdp_3d_color_class = class_new(gensym("3dp_color"), (t_newmethod)pdp_3d_color_new,
    	(t_method)pdp_3d_color_free, sizeof(t_pdp_3d_color), 0, 
				   A_DEFFLOAT,  A_DEFFLOAT,  A_DEFFLOAT,  A_DEFFLOAT, A_NULL);


    pdp_3dp_base_setup(pdp_3d_color_class);

    class_addmethod(pdp_3d_color_class, (t_method)pdp_3d_color_set_r, gensym("r"),  A_FLOAT, A_NULL);  
    class_addmethod(pdp_3d_color_class, (t_method)pdp_3d_color_set_g, gensym("g"),  A_FLOAT, A_NULL);  
    class_addmethod(pdp_3d_color_class, (t_method)pdp_3d_color_set_b, gensym("b"),  A_FLOAT, A_NULL);  
    class_addmethod(pdp_3d_color_class, (t_method)pdp_3d_color_set_a, gensym("a"),  A_FLOAT, A_NULL);  


}

#ifdef __cplusplus
}
#endif

--- NEW FILE: pdp_3d_drawmesh.c ---
/*
 *   Pure Data Packet module.
 *   Copyright (c) by Tom Schouten <pdp at zzz.kotnet.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

/* a very naive approach to triangular meshes */


// $$TODO: some serious memory corruption in this file our the list implementation


#include "GL/gl.h"
#include <math.h>
//#include <GL/glut.h>

#include "pdp_opengl.h"
#include "pdp_3dp_base.h"
#include "pdp_mesh.h"


/* PD OBJECT */

typedef struct _pdp_3d_drawmesh
{
    t_pdp_3dp_base x_base;
    t_pdp_dpd_commandfactory x_clist;

    t_mesh *x_mesh; 
    int x_wireframe;
    int x_flatshading;

} t_pdp_3d_drawmesh;


/* MESHCOMMAND OBJECT */

typedef struct _meshcommand
{
    t_pdp_dpd_command x_head;
    int x_context_packet;
    int x_texture_packet;
    t_pdp_3d_drawmesh *x_mother;
    t_pdp_method x_method;

    int x_wireframe;
    int x_flatshading;
    float x_step;
    float x_d0;
    float x_r0;
    int x_normal_type;
    
} t_meshcommand;


/* MESHCOMMAND METHODS */

/* draw the mesh */
static void meshcommand_draw(t_meshcommand *x)
{
    int i = 0;
    t_pdp_atom *it;
    t_pdp_list *tl = x->x_mother->x_mesh->triangles;
    t_triangle *t;
    GLenum mode = (x->x_wireframe) ? GL_LINE_LOOP : GL_TRIANGLES;

    //glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);

    glLineWidth(5);

    glBegin(mode);

    if (x->x_flatshading){
	PDP_POINTER_IN(tl, it, t){
	    glNormal3fv(t->n);
	    for (i=0; i<3; i++){
		glVertex3fv(t->v[i]->c);
	    }
	}
    }
    else{
	PDP_POINTER_IN(tl, it, t){
	    for (i=0; i<3; i++){
		glNormal3fv(t->v[i]->n);
		glVertex3fv(t->v[i]->c);
	    }
	}
    }
    glEnd();
}

static void meshcommand_relax(t_meshcommand *x)
{
    mesh_relax(x->x_mother->x_mesh, x->x_step, x->x_d0, x->x_r0);
}


/* the main subcommand dispatcher */
static void meshcommand_execute(t_meshcommand *x)
{
    int p = x->x_context_packet;
 
    /* check if it's a valid buffer we can draw in */
    if (pdp_packet_3Dcontext_isvalid(p)){ 
	

	/* setup rendering context */
	pdp_packet_3Dcontext_set_rendering_context(p);

	/* call the command method */
	if (x->x_method) (x->x_method)(x);

    }

    /* you know the drill: command done, sword in belly. */
    pdp_dpd_command_suicide(x);
}

static void meshcommand_split_all_four(t_meshcommand *x)
{
    mesh_split_all_four(x->x_mother->x_mesh);
}
static void meshcommand_split_all_three(t_meshcommand *x){
    mesh_split_all_three(x->x_mother->x_mesh);
}
static void meshcommand_split_random_three(t_meshcommand *x){
    mesh_split_random_three(x->x_mother->x_mesh);
}


static void meshcommand_reset(t_meshcommand *x)
{
    mesh_free(x->x_mother->x_mesh);
    x->x_mother->x_mesh = mesh_new_tetra();
}

static void meshcommand_debug(t_meshcommand *x)
{
    mesh_debug(x->x_mother->x_mesh);
}

static void meshcommand_calculate_normals(t_meshcommand *x)
{
    x->x_mother->x_mesh->normal_type = x->x_normal_type;
    mesh_calculate_normals(x->x_mother->x_mesh);
}




/* PD OBJECT METHODS */


/* return a new command object */
void *pdp_3d_drawmesh_get_command_object(t_pdp_3d_drawmesh *x)
{
    t_meshcommand *c = (t_meshcommand *)pdp_dpd_commandfactory_get_new_command(&x->x_clist);
    c->x_context_packet = pdp_3dp_base_get_context_packet(x);
    c->x_mother = x;
    c->x_method = (t_pdp_method)meshcommand_draw; //default command is draw
    c->x_wireframe = x->x_wireframe;
    c->x_flatshading = x->x_flatshading;

    return c;
}

/* schedule a command */
static void pdp_3d_drawmesh_queue_command(t_pdp_3d_drawmesh *x, t_meshcommand *c)
{
    pdp_3dp_base_queue_command(x, c, (t_pdp_method)meshcommand_execute, 0, 0);
}

static void pdp_3d_drawmesh_queue_simple_command(t_pdp_3d_drawmesh *x, t_pdp_method method)
{
    t_meshcommand *c = (t_meshcommand *)pdp_3d_drawmesh_get_command_object(x);
    c->x_method = method;
    pdp_3dp_base_queue_command(x, c, (t_pdp_method)meshcommand_execute, 0, 0);
}

//NOTE: only the meshcommands are entitled to use the mesh (thread issues)
//therefore all mesh manipulations must be queued as a command


static void pdp_3d_drawmesh_debug(t_pdp_3d_drawmesh *x)
{
    pdp_3d_drawmesh_queue_simple_command(x, (t_pdp_method)meshcommand_debug);
}

static void pdp_3d_drawmesh_relax(t_pdp_3d_drawmesh *x, t_floatarg step, 
				  t_floatarg d0, t_floatarg r0)
{
    t_meshcommand *c = (t_meshcommand *)pdp_3d_drawmesh_get_command_object(x);
    c->x_step = step;
    c->x_d0 = d0;
    c->x_r0 = r0;
    c->x_method = (t_pdp_method)meshcommand_relax;
    pdp_3d_drawmesh_queue_command(x, c);

}

void pdp_3d_drawmesh_normal(t_pdp_3d_drawmesh *x, t_symbol *s)
{
    t_meshcommand *c = (t_meshcommand *)pdp_3d_drawmesh_get_command_object(x);
    if (gensym("sphere") == s)       c->x_normal_type = MESH_NORMAL_SPHERE;
    else if (gensym("prism") == s)   c->x_normal_type = MESH_NORMAL_PRISM;
    else if (gensym("random") == s)  c->x_normal_type = MESH_NORMAL_RANDOM;
    else if (gensym("average") == s) c->x_normal_type = MESH_NORMAL_AVERAGE;
    c->x_method = (t_pdp_method)meshcommand_calculate_normals;
    pdp_3d_drawmesh_queue_command(x, c);

}

/* this is used by the standard drawing routine, so doesn't need to be scheduled */
void pdp_3d_drawmesh_wireframe(t_pdp_3d_drawmesh *x, t_float f)
{
    x->x_wireframe = (f != 0.0f);
}

void pdp_3d_drawmesh_flatshading(t_pdp_3d_drawmesh *x, t_float f)
{
    x->x_flatshading = (f != 0.0f);
}


static void pdp_3d_drawmesh_split_all_four(t_pdp_3d_drawmesh *x)
{
    pdp_3d_drawmesh_queue_simple_command(x, (t_pdp_method)meshcommand_split_all_four);
}

static void pdp_3d_drawmesh_split_all_three(t_pdp_3d_drawmesh *x)
{
    pdp_3d_drawmesh_queue_simple_command(x, (t_pdp_method)meshcommand_split_all_three);
}

static void pdp_3d_drawmesh_split_random_three(t_pdp_3d_drawmesh *x)
{
    pdp_3d_drawmesh_queue_simple_command(x, (t_pdp_method)meshcommand_split_random_three);
}


static void pdp_3d_drawmesh_reset(t_pdp_3d_drawmesh *x)
{
    pdp_3d_drawmesh_queue_simple_command(x, (t_pdp_method)meshcommand_reset);

}










t_class *pdp_3d_drawmesh_class;


void pdp_3d_drawmesh_free(t_pdp_3d_drawmesh *x)
{
    /* queue needs to finish before mesh is deleted */
    pdp_3dp_base_queue_wait(x);
    mesh_free(x->x_mesh);

    pdp_3dp_base_free(x);
    pdp_dpd_commandfactory_free(&x->x_clist);
}

void *pdp_3d_drawmesh_new(t_symbol *s, t_floatarg p0, t_floatarg p1, t_floatarg p2, t_floatarg p3)
{
    t_pdp_3d_drawmesh *x = (t_pdp_3d_drawmesh *)pd_new(pdp_3d_drawmesh_class);

    /* super init */
    pdp_3dp_base_init(x);

    /* create dpd outlet */
    pdp_3dp_base_add_outlet(x, (t_pdp_method)meshcommand_execute, 0);

    /* init command list */
    pdp_dpd_commandfactory_init(&x->x_clist, sizeof(t_meshcommand));

    /* register command factory method */
    pdp_dpd_base_register_command_factory_method(x, (t_pdp_newmethod)pdp_3d_drawmesh_get_command_object);
       

    /* initialize triangular mesh with a simply connected manifold */
    x->x_mesh = mesh_new_tetra();

    x->x_wireframe = 0;
    x->x_flatshading = 0;

    return (void *)x;
}


#ifdef __cplusplus
extern "C"
{
#endif


void pdp_3d_drawmesh_setup(void)
{

    pdp_3d_drawmesh_class = class_new(gensym("3dp_drawmesh"), (t_newmethod)pdp_3d_drawmesh_new,
    	(t_method)pdp_3d_drawmesh_free, sizeof(t_pdp_3d_drawmesh), 0, A_DEFSYMBOL, 
				  A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
    pdp_3dp_base_setup(pdp_3d_drawmesh_class);


    class_addmethod(pdp_3d_drawmesh_class, (t_method)pdp_3d_drawmesh_split_random_three, gensym("split3random"), A_NULL);
    class_addmethod(pdp_3d_drawmesh_class, (t_method)pdp_3d_drawmesh_split_all_three, gensym("split3"), A_NULL);
    class_addmethod(pdp_3d_drawmesh_class, (t_method)pdp_3d_drawmesh_split_all_four, gensym("split4"), A_NULL);
    class_addmethod(pdp_3d_drawmesh_class, (t_method)pdp_3d_drawmesh_reset, gensym("reset"), A_NULL);
    class_addmethod(pdp_3d_drawmesh_class, (t_method)pdp_3d_drawmesh_normal, gensym("normal"), A_SYMBOL, A_NULL);
    class_addmethod(pdp_3d_drawmesh_class, (t_method)pdp_3d_drawmesh_relax, gensym("springrelax"),
		    A_FLOAT, A_FLOAT, A_FLOAT, A_NULL);
    class_addmethod(pdp_3d_drawmesh_class, (t_method)pdp_3d_drawmesh_debug, gensym("info"), A_NULL);
    class_addmethod(pdp_3d_drawmesh_class, (t_method)pdp_3d_drawmesh_wireframe, gensym("wireframe"), A_FLOAT, A_NULL);
    class_addmethod(pdp_3d_drawmesh_class, (t_method)pdp_3d_drawmesh_flatshading, gensym("flatshading"), A_FLOAT, A_NULL);

}

#ifdef __cplusplus
}
#endif

--- NEW FILE: pdp_3d_state.c ---
/*
 *   Pure Data Packet module.
 *   Copyright (c) by Tom Schouten <pdp at zzz.kotnet.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */


/* change binary opengl state variables. all defaults (flag = 0) should be set
   in the render context init.

   right outlet has the thing enabled (or disabled, depending on toggle)
   left outlet has the thing disabled (better: it should push it)

   simple version: does not permit reentry (yet) */


#include <GL/gl.h>
#include "pdp_opengl.h"
#include "pdp_3dp_base.h"

typedef struct pdp_3d_state_struct
{
    t_pdp_3dp_base x_base;
    GLboolean x_flag;
    GLboolean x_prev_flag;
    GLenum x_thing;
    void (*x_setup)(void);

} t_pdp_3d_state;


static void _setflag(GLenum thing, GLboolean flag)
{
    if (flag) glEnable(thing);
    else glDisable(thing);
}

static void pdp_3d_state_process_right(t_pdp_3d_state *x)
{
    int p;
    if (-1 != (p = pdp_3dp_base_get_context_packet(x))){
	/* store previous flag */
	pdp_packet_3Dcontext_set_rendering_context(p);
	glGetBooleanv(x->x_thing, &x->x_prev_flag);
	_setflag(x->x_thing, x->x_flag);
	if (x->x_setup) x->x_setup();
    }
}

static void pdp_3d_state_process_left(t_pdp_3d_state *x)
{
    int p;
    /* allways run left method (reset) */
    if (-1 != (p = pdp_3dp_base_get_context_packet(x))){
	pdp_packet_3Dcontext_set_rendering_context(p);
	_setflag(x->x_thing, x->x_prev_flag);
    }
}

static void pdp_3d_state_flag(t_pdp_3d_state *x, t_floatarg f)
{
    x->x_flag = (f == 0.0f) ? GL_FALSE : GL_TRUE;
}

static void _blend(void)     {glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);}
static void _blend_add(void) {glBlendFunc(GL_SRC_ALPHA, GL_ONE);}

t_class *pdp_3d_state_class;
void pdp_3d_state_free(t_pdp_3d_state *x){pdp_3dp_base_free(x);}
void *pdp_3d_state_new(t_symbol *s, t_floatarg f)
{
    t_pdp_3d_state *x = (t_pdp_3d_state *)pd_new(pdp_3d_state_class);

    /* super init */
    pdp_3dp_base_init(x);
    pdp_3d_state_flag(x,f);

    if      (s == gensym("blend_mix"))  {x->x_setup = _blend;     x->x_thing = GL_BLEND;}
    else if (s == gensym("blend_add"))  {x->x_setup = _blend_add; x->x_thing = GL_BLEND;}
    else if (s == gensym("depth_test")) {x->x_setup = 0;          x->x_thing = GL_DEPTH_TEST;}

    /* unkown command: do nothing */
    else {
	post ("3dp_state: unknown flag %s", s->s_name);
	pd_free((void *)x);
	return 0;
    }

    /* create additional inlet */
    pdp_base_add_gen_inlet(x, gensym("float"), gensym("flag"));

    /* create dpd outlets */
    pdp_3dp_base_add_outlet(x, (t_pdp_method)pdp_3d_state_process_left, 0);
    pdp_3dp_base_add_outlet(x, (t_pdp_method)pdp_3d_state_process_right, 0);


    return (void *)x;
}


#ifdef __cplusplus
extern "C"
{
#endif


void pdp_3d_state_setup(void)
{


    pdp_3d_state_class = class_new(gensym("3dp_toggle"), (t_newmethod)pdp_3d_state_new,
    	(t_method)pdp_3d_state_free, sizeof(t_pdp_3d_state), 0, A_SYMBOL, A_DEFFLOAT, A_NULL);

    pdp_3dp_base_setup(pdp_3d_state_class);
    class_addmethod(pdp_3d_state_class, (t_method)pdp_3d_state_flag, gensym("flag"), A_FLOAT, A_NULL);

}

#ifdef __cplusplus
}
#endif

--- NEW FILE: Makefile ---
include ../Makefile.config

all:	pdp_3d_windowcontext.o pdp_3d_draw.o pdp_3d_view.o \
	pdp_3d_push.o pdp_3d_light.o pdp_3d_dlist.o pdp_3d_color.o \
	pdp_3d_snap.o pdp_3d_drawmesh.o pdp_3d_for.o pdp_3d_state.o \
	pdp_3d_subcontext.o

clean:
	rm -rf *~ *.o


--- NEW FILE: README ---

This directory contains opengl modules for the pdp_opengl library.


--- NEW FILE: pdp_3d_dlist.c ---
/*
 *   Pure Data Packet module.
 *   Copyright (c) by Tom Schouten <pdp at zzz.kotnet.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */


#include <GL/gl.h>

#include "pdp_opengl.h"
#include "pdp_3dp_base.h"

/* gl display list compilation & execution */

typedef struct pdp_3d_dlist_struct
{
    t_pdp_3dp_base x_base;

    GLuint x_dlist;
    int x_compile;

} t_pdp_3d_dlist;



static void pdp_3d_dlist_complete_notify(t_pdp_3d_dlist *x)
{
    /* disable the second outlet */
    pdp_3dp_base_enable_outlet(x, 0, 0);
}

static void pdp_3d_dlist_compile(t_pdp_3d_dlist *x)
{
    //x->x_compile = 1;
    /* enable the second outlet */
    pdp_3dp_base_enable_outlet(x, 0, 1);
}

static void pdp_3d_dlist_process_start(t_pdp_3d_dlist *x)
{
    int p = pdp_3dp_base_get_context_packet(x);
    if (-1 != p){

	/* check if pbuf */
	if (pdp_packet_3Dcontext_isvalid(p)){

	    /* set context */
	    //pdp_pbuf_set_rendering_context(p);

	    /* display list needs to be created in the correct context
	       if we don't have one yet, create it */
	    if (!x->x_dlist) x->x_dlist = glGenLists(1);

	    

	    /* start the list */ /* $$$TODO: error checking for recursion */
	    x->x_compile = 1;
	    glNewList(x->x_dlist, GL_COMPILE_AND_EXECUTE);
	    //glNewList(x->x_dlist, GL_COMPILE);

	    //post("compiling");

	    
	}
    }
}

static void pdp_3d_dlist_process_cleanup(t_pdp_3d_dlist *x)
{
    int p = pdp_3dp_base_get_context_packet(x);
    if (-1 != p){

	/* check if pbuf */
	if (pdp_packet_3Dcontext_isvalid(p)){

	    /* end list if we're compiling */
	    if (x->x_compile){
		
		/* end the list */
		glEndList();
		
		/* use the list next time */
		x->x_compile = 0;

		//post("ending compile");

	    }

	    /* or execute the old one */
	    else {
		if (x->x_dlist) {
		    //post("calling dlist %d", x->x_dlist);
		    glCallList(x->x_dlist);
		}
		
	    }


	}
    }
}




t_class *pdp_3d_dlist_class;



void pdp_3d_dlist_free(t_pdp_3d_dlist *x)
{
    pdp_3dp_base_free(x);
    if (x->x_dlist) glDeleteLists(x->x_dlist, 1);
}

void *pdp_3d_dlist_new(t_symbol *s)
{
    t_pdp_3d_dlist *x = (t_pdp_3d_dlist *)pd_new(pdp_3d_dlist_class);

    /* super init */
    pdp_3dp_base_init(x);


    /* io & callbacks */
    pdp_3dp_base_add_outlet(x, (t_pdp_method)pdp_3d_dlist_process_start, 0);
    pdp_3dp_base_add_cleanup(x, (t_pdp_method)pdp_3d_dlist_process_cleanup, 0);
    pdp_3dp_base_register_complete_notify(x, (t_pdp_method)pdp_3d_dlist_complete_notify);

    /* disable the second outlet */
    pdp_3dp_base_enable_outlet(x, 1, 0);


    /* create dlist */
    x->x_dlist = 0;
    x->x_compile = 0;

    /* compile the first packet */
    pdp_3d_dlist_compile(x);

    return (void *)x;
}


#ifdef __cplusplus
extern "C"
{
#endif


void pdp_3d_dlist_setup(void)
{


    pdp_3d_dlist_class = class_new(gensym("pdp_3d_dlist"), (t_newmethod)pdp_3d_dlist_new,
    	(t_method)pdp_3d_dlist_free, sizeof(t_pdp_3d_dlist), 0, A_DEFSYMBOL, A_NULL);

    class_addcreator((t_newmethod)pdp_3d_dlist_new, gensym("3dp_dlist"), A_DEFSYMBOL, A_NULL);

    pdp_3dp_base_setup(pdp_3d_dlist_class);

    class_addmethod(pdp_3d_dlist_class, (t_method)pdp_3d_dlist_compile, gensym("compile"), A_NULL);



}

#ifdef __cplusplus
}
#endif

--- NEW FILE: pdp_3d_snap.c ---
/*
 *   Pure Data Packet module.
 *   Copyright (c) by Tom Schouten <pdp at zzz.kotnet.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */


#include <GL/gl.h>
#include "pdp.h"
#include "pdp_3dp_base.h"
#include "pdp_opengl.h"

typedef struct _pdp_3d_snap
{
    t_pdp_3dp_base x_base;
    t_pdp_dpd_commandfactory x_cfact;
    t_outlet *x_result_outlet;
    t_pdp_symbol *x_dest_template;
    int x_is_texture;
    u32 x_width;
    u32 x_height;
    int x_auto_snap;
    int x_pending_snap;

} t_pdp_3d_snap;


typedef struct _snap_command
{
    t_pdp_dpd_command x_base;
    t_pdp_3d_snap *x_mother;
    int x_context_packet;
    int x_result_packet;
    int x_active;
} t_snap_command;




/* COMAND METHODS */

static void snap_texture_process(t_snap_command *x)
{
    int pt = -1;
    int p = x->x_context_packet;
    int i;
    u32 w,h;

    if (x->x_active && pdp_packet_3Dcontext_isvalid(p)){
	
	/* get dest texture sub dims */
	w = (x->x_mother->x_width)  ? x->x_mother->x_width : pdp_packet_3Dcontext_subwidth(p);
	h = (x->x_mother->x_height) ? x->x_mother->x_height : pdp_packet_3Dcontext_subheight(p);

	/* texture is a special case */
	if (x->x_mother->x_is_texture){

	    /* create a new texture packet */
	    pt = pdp_packet_new_texture(w,h,GL_RGB);
	    if (-1 != pt) {
		
		/* set rendering context */
		pdp_packet_3Dcontext_set_rendering_context(p);
		
		/* copy pbuf to new texture */
		pdp_packet_texture_make_current(pt);
		//glReadBuffer(GL_FRONT); //this is for weird feedback stuff..
		glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, w, h);
		
		x->x_result_packet = pt;
	    }
	}

	/* other type: snap to bitmap first, then convert */
	else{

	    //nvidia driver 4191 bug workaround (w -> multiple of 4)
	    w &= -4;

	    pt = pdp_packet_3Dcontext_snap_to_bitmap(p, w, h);
	    //pt = pdp_packet_new_bitmap_rgb(w, h);
	    //pdp_packet_print_debug(pt);
	    x->x_result_packet = pdp_packet_convert_ro(pt, x->x_mother->x_dest_template);
	    pdp_packet_mark_unused(pt);
	}
    }
}

static void snap_callback(t_snap_command *x)
{
    /* send packet to outlet */
    pdp_packet_pass_if_valid(x->x_mother->x_result_outlet, &x->x_result_packet);
    pdp_dpd_command_suicide(x);
}


/* PD OBJECT METHODS */


static void pdp_3d_snap_snap(t_pdp_3d_snap *x)
{
    x->x_pending_snap = 1;
}

static void pdp_3d_snap_autosnap(t_pdp_3d_snap *x, t_floatarg f)
{
    if (f){
	x->x_auto_snap = 1;
	x->x_pending_snap = 1;
    }
    else{
	x->x_auto_snap = 0;
	x->x_pending_snap = 0;
    }
}

static void *pdp_3d_snap_get_new_command(t_pdp_3d_snap *x)
{
    t_snap_command *c = (t_snap_command *)pdp_dpd_commandfactory_get_new_command(&x->x_cfact);
    c->x_mother = x;
    c->x_context_packet = pdp_3dp_base_get_context_packet(x);
    c->x_result_packet = -1;
    c->x_active = x->x_pending_snap;
    if (!x->x_auto_snap) x->x_pending_snap = 0;
    return (void *)c;
}


t_class *pdp_3d_snap_class;



void pdp_3d_snap_free(t_pdp_3d_snap *x)
{
    //pdp_dpd_base_queue_wait(x);
    pdp_3dp_base_free(x);
}

void *pdp_3d_snap_new(t_symbol *s, t_floatarg w, t_floatarg h)
{
    t_pdp_3d_snap *x = (t_pdp_3d_snap *)pd_new(pdp_3d_snap_class);

    /* super init */
    pdp_3dp_base_init(x);

    /* get destination template */
    x->x_dest_template = (s == gensym("")) ?  pdp_gensym("texture/*/*") : pdp_gensym(s->s_name);
    x->x_is_texture = pdp_type_description_match(x->x_dest_template, pdp_gensym("texture/*/*"));
    w = (w < 0) ? 0 : w;
    h = (h < 0) ? 0 : h;
    x->x_width = w;
    x->x_height = h;

    x->x_auto_snap = 1;
    x->x_pending_snap = 1;

    /* issue warning */
    if (!x->x_is_texture && !(x->x_width && x->x_height)){
	//post("WARNING: 3dp_snap: target is not a texture and dimensions are not set.");
	//post("WARNING: using default image size 320x240.");
	//x->x_width = 320;
	//x->x_height = 240;
    }

    /* create outlets */
    pdp_3dp_base_add_outlet(x, (t_pdp_method)snap_texture_process, (t_pdp_method)snap_callback);
    x->x_result_outlet = outlet_new((t_object *)x, &s_anything);

    /* init command list */
    pdp_dpd_commandfactory_init(&x->x_cfact, sizeof(t_snap_command));

    /* register command factory method */
    pdp_dpd_base_register_command_factory_method(x, (t_pdp_newmethod)pdp_3d_snap_get_new_command);
       

    return (void *)x;
}


#ifdef __cplusplus
extern "C"
{
#endif


void pdp_3d_snap_setup(void)
{


    pdp_3d_snap_class = class_new(gensym("3dp_snap"), (t_newmethod)pdp_3d_snap_new,
    	(t_method)pdp_3d_snap_free, sizeof(t_pdp_3d_snap), 0, A_DEFSYMBOL, A_DEFFLOAT, A_DEFFLOAT, A_NULL);

    pdp_3dp_base_setup(pdp_3d_snap_class);

    class_addmethod(pdp_3d_snap_class, (t_method)pdp_3d_snap_snap, gensym("bang"), A_NULL);
    class_addmethod(pdp_3d_snap_class, (t_method)pdp_3d_snap_autosnap, gensym("autosnap"), A_FLOAT, A_NULL);

}

#ifdef __cplusplus
}
#endif

--- NEW FILE: pdp_3d_context.c ---
/*
 *   Pure Data Packet module.
 *   Copyright (c) by Tom Schouten <pdp at zzz.kotnet.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */



#include "pdp.h"
#include "pdp_base.h"
#include "pdp_opengl.h"


typedef struct pdp_3d_context_struct
{
    t_pdp_base x_base;

    t_outlet *x_outlet0;

    int x_packet0;

    t_symbol *x_type;

    unsigned int x_width;
    unsigned int x_height;

    void *x_constant;
 
} t_pdp_3d_context;





static void pdp_3d_context_preproc(t_pdp_3d_context *x)
{
    int p;
    int i;

    /* create new packet */
    p = pdp_packet_new_pbuf(x->x_width, x->x_height, 0);
    x->x_packet0 = p;

    if (-1 == p) return;
    
    pdp_pbuf_set_rendering_context(p);
    pdp_pbuf_setup_3d_context(p);

    /* clear buffer */
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_AUTO_NORMAL);
    glEnable(GL_NORMALIZE);
    glShadeModel(GL_SMOOTH);


    /* disable everything that is enabled in other modules */
    glDisable(GL_LIGHTING);
    for (i=0; i<8; i++) glDisable(GL_LIGHT0 + i);
    glDisable(GL_COLOR_MATERIAL);


}

static void pdp_3d_context_process(t_pdp_3d_context *x)
{
}

static void pdp_3d_context_postproc(t_pdp_3d_context *x)
{
    pdp_pass_if_valid(x->x_outlet0, &x->x_packet0);
}

static void pdp_3d_context_bang(t_pdp_3d_context *x)
{
    pdp_base_bang(x);
}

static void pdp_3d_context_dim(t_pdp_3d_context *x, t_floatarg w, t_floatarg h)
{
    x->x_width  = pdp_imageproc_legalwidth((int)w);
    x->x_height = pdp_imageproc_legalheight((int)h);
    //post("dims %d %d",  x->x_width, x->x_height);
}


static void pdp_3d_context_free(t_pdp_3d_context *x)
{
    pdp_base_free(x);
    pdp_packet_mark_unused(x->x_packet0);

}

t_class *pdp_3d_context_class;



void *pdp_3d_context_new(void)
{
    int i;
    t_pdp_3d_context *x = (t_pdp_3d_context *)pd_new(pdp_3d_context_class);

    /* super init */
    pdp_base_init(x);

    /* in/out*/
    x->x_outlet0 = pdp_base_add_pdp_outlet(x);

    /* base callbacks */
    pdp_base_disable_active_inlet(x);
    pdp_base_set_process_method(x, (t_pdp_method)pdp_3d_context_process);
    pdp_base_set_preproc_method(x, (t_pdp_method)pdp_3d_context_preproc);
    pdp_base_set_postproc_method(x, (t_pdp_method)pdp_3d_context_postproc);

    /* data init */
    x->x_packet0 = -1;
    pdp_3d_context_dim(x, 320, 240);


    return (void *)x;
}



#ifdef __cplusplus
extern "C"
{
#endif



void pdp_3d_context_setup(void)
{


    pdp_3d_context_class = class_new(gensym("pdp_3d_context"), (t_newmethod)pdp_3d_context_new,
    	(t_method)pdp_3d_context_free, sizeof(t_pdp_3d_context), 0, A_NULL);
    class_addcreator((t_newmethod)pdp_3d_context_new, gensym("3dp_context"), A_NULL);

    pdp_base_setup(pdp_3d_context_class);

    class_addmethod(pdp_3d_context_class, (t_method)pdp_3d_context_dim, gensym("dim"), A_FLOAT, A_FLOAT, A_NULL);
    class_addmethod(pdp_3d_context_class, (t_method)pdp_3d_context_bang, gensym("bang"), A_NULL);

}

#ifdef __cplusplus
}
#endif

--- NEW FILE: pdp_3d_subcontext.c ---
/*
 *   Pure Data Packet module.
 *   Copyright (c) by Tom Schouten <pdp at zzz.kotnet.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */



#include <GL/gl.h>
#include "pdp_opengl.h"
#include "pdp_3dp_base.h"

typedef struct pdp_3d_subcontext_struct
{
    t_pdp_3dp_base x_base;
    int x_width;
    int x_height;

} t_pdp_3d_subcontext;



static void pdp_3d_subcontext_process_right(t_pdp_3d_subcontext *x)
{
    int p = pdp_3dp_base_get_context_packet(x);
    if (-1 != p){

	/* set subdims */
	pdp_packet_3Dcontext_set_subwidth(p, x->x_width);
	pdp_packet_3Dcontext_set_subheight(p, x->x_height);

	/* reinit everything */
	pdp_packet_3Dcontext_set_rendering_context(p);
	pdp_packet_3Dcontext_setup_3d_context(p);

    }
}
static void pdp_3d_subcontext_process_left(t_pdp_3d_subcontext *x)
{
    int p = pdp_3dp_base_get_context_packet(x);
    if (-1 != p){
      
	/* restore subdims */
	pdp_packet_3Dcontext_set_subwidth(p, pdp_packet_3Dcontext_width(p));
	pdp_packet_3Dcontext_set_subheight(p, pdp_packet_3Dcontext_height(p));

	/* re-init everything */
	pdp_packet_3Dcontext_set_rendering_context(p);
	pdp_packet_3Dcontext_setup_3d_context(p);

    }

}

t_class *pdp_3d_subcontext_class;



void pdp_3d_subcontext_free(t_pdp_3d_subcontext *x)
{
    pdp_3dp_base_free(x);
}

void *pdp_3d_subcontext_new(t_floatarg w, t_floatarg h)
{
    t_pdp_3d_subcontext *x = (t_pdp_3d_subcontext *)pd_new(pdp_3d_subcontext_class);

    /* super init */
    pdp_3dp_base_init(x);


    /* create dpd outlets */
    pdp_3dp_base_add_outlet(x, (t_pdp_method)pdp_3d_subcontext_process_left, 0);
    pdp_3dp_base_add_outlet(x, (t_pdp_method)pdp_3d_subcontext_process_right, 0);

    x->x_width = (w < 0) ? 64 : w;
    x->x_height = (h < 0) ? 64 : h;

    return (void *)x;
}


#ifdef __cplusplus
extern "C"
{
#endif


void pdp_3d_subcontext_setup(void)
{


    pdp_3d_subcontext_class = class_new(gensym("3dp_subcontext"), (t_newmethod)pdp_3d_subcontext_new,
    	(t_method)pdp_3d_subcontext_free, sizeof(t_pdp_3d_subcontext), 0, A_FLOAT, A_FLOAT, A_NULL);

    pdp_3dp_base_setup(pdp_3d_subcontext_class);

}

#ifdef __cplusplus
}
#endif

--- NEW FILE: pdp_3d_windowcontext.c ---
/*
 *   Pure Data Packet module.
 *   Copyright (c) by Tom Schouten <pdp at zzz.kotnet.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */


#include <GL/gl.h>
#include "pdp_opengl.h"
#include "pdp_3dp_base.h"

typedef struct pdp_3d_windowcontext_struct
{
    t_pdp_3dp_base x_base;
    int x_width;
    int x_height;
    t_outlet *x_eventout;
    int x_finish_queue_id[2];
    int x_finish_queue_id_current;

} t_pdp_3d_windowcontext;


static void pdp_3d_windowcontext_sendfinish(t_pdp_3d_windowcontext *x)
{
    PDP_ASSERT(x);
    PDP_ASSERT(x->x_eventout);
    outlet_symbol(x->x_eventout, gensym("done"));
}

/* outlet methods */

/* called before the context is propagated */
static void pdp_3d_windowcontext_clearbuffer(t_pdp_3d_windowcontext *x)
{
    int p = pdp_3dp_base_get_context_packet(x);
    //post("setting up render buffer");

    // for multipass rendering
    //pdp_packet_3Dcontext_set_subwidth(p, 320);
    //pdp_packet_3Dcontext_set_subheight(p, 240);

    pdp_packet_3Dcontext_set_rendering_context(p);
    pdp_packet_3Dcontext_setup_3d_context(p);

    /* clear buffer */
    //glScissor(0,0,
    //	      pdp_packet_3Dcontext_subwidth(p),
    //	      pdp_packet_3Dcontext_subheight(p));
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);



}

/* called after context is propagated */
static void pdp_3d_windowcontext_swapbuffer(t_pdp_3d_windowcontext *x)
{
    int p = pdp_3dp_base_get_context_packet(x);
    //post("displaying render buffer");
    //pdp_packet_3Dcontext_set_rendering_context(p);
    pdp_packet_3Dcontext_win_swapbuffers(p);
    //pdp_packet_3Dcontext_unset_rendering_context(p);
}

void pdp_3d_windowcontext_resize(t_pdp_3d_windowcontext *x, t_floatarg width, t_floatarg height)
{
    int w = (int)width;
    int h = (int)height;
    int p = pdp_3dp_base_get_context_packet(x);
    if ((w>0) && (h>0)){
	pdp_packet_3Dcontext_win_resize(p, w, h);
	x->x_width = w;
	x->x_height = h;
    }
}

void pdp_3d_windowcontext_open(t_pdp_3d_windowcontext *x)
{
    int p = pdp_3dp_base_get_context_packet(x);
    if (-1 == p){
	p  = pdp_packet_new_3Dcontext_win();
	pdp_3d_windowcontext_resize(x, x->x_width, x->x_height);
	pdp_3dp_base_set_context_packet(x, p);
    }
    
}
void pdp_3d_windowcontext_close(t_pdp_3d_windowcontext *x)
{
    t_pdp_procqueue *q = pdp_3dp_base_get_queue(x);

    /* flush all pending tasks in the queue */
    //post("preflush");
    pdp_procqueue_flush(q);
    //post("postflush");

    /* now it is safe to delete the context packet */
    pdp_packet_delete(pdp_3dp_base_move_context_packet(x));

    //post("deleted");
}

void pdp_3d_windowcontext_cursor(t_pdp_3d_windowcontext *x, t_floatarg f)
{
    int p = pdp_3dp_base_get_context_packet(x);
    bool toggle = (f != 0.0f);
    pdp_packet_3Dcontext_win_cursor(p, toggle);
}



static void pdp_3d_windowcontext_bang(t_pdp_3d_windowcontext *x)
{
    int p;
    int cur = x->x_finish_queue_id_current;
    t_pdp_list *eventlist;

    /* check if at least recent processing chain is done (two chains busy = max pipeline depth) */
    if (-1 != x->x_finish_queue_id[cur]){
	//post("pdp_3d_windowcontext_bang: bang ignored (previous rendering not finished)");
	return;
    }

    /* create a window context if needed */
    pdp_3d_windowcontext_open(x);

    /* get events and send to outlet */
    p = pdp_3dp_base_get_context_packet(x);
    eventlist = pdp_packet_3Dcontext_win_get_eventlist(p);
    if (eventlist){
	t_pdp_atom *a;
	for (a=eventlist->first; a; a=a->next){
	    outlet_pdp_list(x->x_eventout, a->w.w_list);
	}
	pdp_tree_free(eventlist);
    }

    /* bang base */
    pdp_3dp_base_bang(x);

    /* add a dummy process to the queue for synchro */
    pdp_procqueue_add(pdp_3dp_base_get_queue(x), x, 0, 0, &x->x_finish_queue_id[cur]);
    x->x_finish_queue_id_current = !cur;


    
}


static void pdp_3d_windowcontext_free(t_pdp_3d_windowcontext *x)
{
    pdp_3d_windowcontext_close(x);
    pdp_3dp_base_free(x);

}

t_class *pdp_3d_windowcontext_class;


void *pdp_3d_windowcontext_new(void)
{
    /* allocate */
    t_pdp_3d_windowcontext *x = (t_pdp_3d_windowcontext *)pd_new(pdp_3d_windowcontext_class);

    x->x_width = 320;
    x->x_height = 240;
    x->x_finish_queue_id[0] = -1;
    x->x_finish_queue_id[1] = -1;
    x->x_finish_queue_id_current =0;

    /* init super: this is mandatory */
    pdp_3dp_base_init(x);
    pdp_3dp_base_disable_active_inlet(x);

    /* set the dpd processing methods & outlets */
    pdp_3dp_base_add_outlet(x, (t_pdp_method)pdp_3d_windowcontext_clearbuffer, 0);
    pdp_3dp_base_add_cleanup(x, (t_pdp_method)pdp_3d_windowcontext_swapbuffer, (t_pdp_method)pdp_3d_windowcontext_sendfinish);

    /* add event outlet */
    x->x_eventout = outlet_new((t_object *)x, &s_anything);

    
    return (void *)x;
}



#ifdef __cplusplus
extern "C"
{
#endif


void pdp_3d_windowcontext_setup(void)
{
    /* create a standard pd class */
    pdp_3d_windowcontext_class = class_new(gensym("3dp_windowcontext"), (t_newmethod)pdp_3d_windowcontext_new,
   	(t_method)pdp_3d_windowcontext_free, sizeof(t_pdp_3d_windowcontext), 0, A_NULL);

    /* inherit pdp base class methods */
    pdp_3dp_base_setup(pdp_3d_windowcontext_class);

    /* register methods */
    class_addbang(pdp_3d_windowcontext_class, pdp_3d_windowcontext_bang);

    class_addmethod(pdp_3d_windowcontext_class, (t_method)pdp_3d_windowcontext_open, gensym("open"), A_NULL);
    class_addmethod(pdp_3d_windowcontext_class, (t_method)pdp_3d_windowcontext_close, gensym("close"), A_NULL);
    class_addmethod(pdp_3d_windowcontext_class, (t_method)pdp_3d_windowcontext_resize, gensym("dim"), A_FLOAT, A_FLOAT, A_NULL);
    class_addmethod(pdp_3d_windowcontext_class, (t_method)pdp_3d_windowcontext_resize, gensym("size"), A_FLOAT, A_FLOAT, A_NULL);
    class_addmethod(pdp_3d_windowcontext_class, (t_method)pdp_3d_windowcontext_cursor, gensym("cursor"), A_FLOAT, A_NULL);

}



#ifdef __cplusplus
}
#endif

--- NEW FILE: pdp_3d_draw.c ---
/*
 *   Pure Data Packet module.
 *   Copyright (c) by Tom Schouten <pdp at zzz.kotnet.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */


//#include "GL/gl.h"
#include <GL/glut.h>
#include <math.h>

#include "pdp_opengl.h"
#include "pdp_3dp_base.h"

typedef struct _drawcommand
{
    t_pdp_dpd_command x_head;
    int x_context_packet;
    int x_texture_packet;
    float x_p0;
    float x_p1;
    float x_p2;
    float x_p3;
    t_pdp_method x_method;
    GLUquadric* x_quadric; 
    int x_have_texture; /* is there a valid texture ? */
    
} t_drawcommand;


typedef struct _pdp_3d_draw
{
    t_pdp_3dp_base x_base;
    t_pdp_dpd_commandfactory x_clist;

    int x_inlets;
    float x_p0;
    float x_p1;
    float x_p2;
    float x_p3;

    t_pdp_method x_method;

    int x_tex_in;       /* the number of texture inlets */
    GLUquadric* x_quadric; 
} t_pdp_3d_draw;


void pdp_3d_draw_delete_texture(t_pdp_3d_draw *x)
{
    pdp_base_move_packet(x, 1);
}

/* return a new command object */
void *pdp_3d_draw_get_command_object(t_pdp_3d_draw *x)
{
    t_drawcommand *c = (t_drawcommand *)pdp_dpd_commandfactory_get_new_command(&x->x_clist);
    c->x_p0 = x->x_p0;
    c->x_p1 = x->x_p1;
    c->x_p2 = x->x_p2;
    c->x_p3 = x->x_p3;
    c->x_context_packet = pdp_3dp_base_get_context_packet(x);
    c->x_texture_packet = pdp_packet_copy_ro(pdp_base_get_packet(x, 1));

    c->x_quadric = x->x_quadric; /* $$$TODO: this assumes quadric doesn't change */

    c->x_method = x->x_method;
    //post("o: %x, vc %x, n %d, u %d", x, c, x->x_clist.nb_commands, c->x_head.used);
    return c;
}

/* object drawing methods */

static void draw_clear(t_drawcommand *x)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

}

static void draw_square(t_drawcommand *x)
{
    float f = x->x_p0 * 0.5f;
    float z = x->x_p1 * 0.5f;
    /* draw a square */
    glBegin(GL_QUADS);
        glNormal3f(0.0f, 0.0f, 1.0f);
        glTexCoord2f(1, 0);
        glVertex3f(f,-f, z);
	glTexCoord2f(1, 1);
	glVertex3f(f, f, z);
	glTexCoord2f(0, 1);
	glVertex3f(-f, f, z);
	glTexCoord2f(0, 0);
	glVertex3f(-f,-f, z);
    glEnd();
}

static void draw_wsquare(t_drawcommand *x)
{
    float f = x->x_p0;
    float z = x->x_p1;
    /* draw a square */
    glBegin(GL_LINE_LOOP);
        glVertex3f(f,-f, z);
	glVertex3f(f, f, z);
	glVertex3f(-f, f, z);
	glVertex3f(-f,-f, z);
    glEnd();
}

static void draw_triangle(t_drawcommand *x)
{
    float f = x->x_p0 * 0.5f;
    float f2 = f * 0.5f;
    float f3 = f * (sqrt(3.0f) / 2.0f);
    float z = x->x_p1 * 0.5f;
    /* draw a triangle */
    glBegin(GL_TRIANGLES);
        glNormal3f(0.0f, 0.0f, 1.0f);

        glTexCoord2f(0.5f, 1.0f);
        glVertex3f(0, f, z);

	glTexCoord2f(0.5f * (1.0f - sqrt(3.0f)/2.0f), 0.25f);
	glVertex3f(-f3, -f2, z);

	glTexCoord2f(0.5f * (1.0f + sqrt(3.0f)/2.0f), 0.25f);
	glVertex3f(f3, -f2, z);
    glEnd();
}

static void draw_wtriangle(t_drawcommand *x)
{
    float f = x->x_p0 * 0.5f;
    float f2 = f * 0.5f;
    float f3 = f * (sqrt(3.0f) / 2.0f);
    float z = x->x_p1 * 0.5f;

    /* draw a wire triangle */
    glBegin(GL_LINE_LOOP);
        glNormal3f(0.0f, 0.0f, 1.0f);
        glVertex3f(0, f, z);
	glVertex3f(-f3, -f2, z);
	glVertex3f(f3, -f2, z);
    glEnd();
}


static void draw_wcube(t_drawcommand *x) 
{
    glutWireCube(x->x_p0);
}

static void draw_cube(t_drawcommand *x) 
{
    x->x_p1 = x->x_p0; // set square z coord;

    //glutSolidCube(x->x_p0);

    //glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
        draw_square(x);
	glRotatef(90, 0,1,0);
	draw_square(x);
	glRotatef(90, 0,1,0);
	draw_square(x);
	glRotatef(90, 0,1,0);
	draw_square(x);
    glPopMatrix();

    glPushMatrix();
        glRotatef(90, 1, 0, 0);
	draw_square(x);
	glRotatef(180, 1, 0, 0);
	draw_square(x);
    glPopMatrix();

}

static void draw_wtorus(t_drawcommand *x)
{
    float ri = x->x_p0;
    float ro = x->x_p1;
    int n = (int)x->x_p2;
    int m = (int)x->x_p3;

    if (n < 1) n = 20;
    if (m < 1) m = n;

    glutWireTorus(ri, ro, n, m);

}

static void draw_torus(t_drawcommand *x)
{
    float ri = x->x_p0;
    float ro = x->x_p1;
    int n = (int)x->x_p2;
    int m = (int)x->x_p3;

    if (n < 1) n = 20;
    if (m < 1) m = n;

    glutSolidTorus(ri, ro, n, m);

}

static void draw_cone(t_drawcommand *x)
{
    float base = x->x_p0;
    float height = x->x_p1;
    int n = (int)x->x_p2;
    int m = (int)x->x_p3;

    if (n < 1) n = 20;
    if (m < 1) m = n;

    glutSolidCone(base, height, n, m);

}

static void draw_wcone(t_drawcommand *x)
{
    float base = x->x_p0;
    float height = x->x_p1;
    int n = (int)x->x_p2;
    int m = (int)x->x_p3;

    if (n < 1) n = 20;
    if (m < 1) m = n;

    glutWireCone(base, height, n, m);

}

static void draw_wteapot(t_drawcommand *x)
{
    float f = x->x_p0;
    glutWireTeapot(f);

}

static void draw_teapot(t_drawcommand *x)
{
    float f = x->x_p0;
    glutSolidTeapot(f);

}

static void draw_wsphere(t_drawcommand *x)
{
    float f = x->x_p0;
    int n = (int)x->x_p1;
    int m = (int)x->x_p2;

    if (n < 1) n = 20;
    if (m < 1) m = n;

    glutWireSphere(f, n, m);

}

static void draw_sphere(t_drawcommand *x)
{
    float f = x->x_p0;
    int n = (int)x->x_p1;
    int m = (int)x->x_p2;

    if (n < 1) n = 20;
    if (m < 1) m = n;

    gluSphere(x->x_quadric, f, n, m);

    //glutSolidSphere(f, n, m);

}

static void draw_dodeca(t_drawcommand *x){glutSolidDodecahedron();}
static void draw_octa(t_drawcommand *x)  {glutSolidOctahedron();}
static void draw_tetra(t_drawcommand *x) {glutSolidTetrahedron();}
static void draw_icosa(t_drawcommand *x) {glutSolidIcosahedron();}

static void draw_wdodeca(t_drawcommand *x){glutWireDodecahedron();}
static void draw_wocta(t_drawcommand *x)  {glutWireOctahedron();}
static void draw_wtetra(t_drawcommand *x) {glutWireTetrahedron();}
static void draw_wicosa(t_drawcommand *x) {glutWireIcosahedron();}






/* the actual (registered) draw method */
/* when this is finished, the drawcommand object should commit suicide */

static void draw_process(t_drawcommand *x)
{
    int p = x->x_context_packet;
    int pt = x->x_texture_packet;
    float fx=1;
    float fy=1;
    x->x_have_texture = pdp_packet_texture_isvalid(pt);

    //post("pdp_3d_draw: context = %d, texture = %d", p, pt);
 
    /* check if it's a valid buffer we can draw in */
    if (pdp_packet_3Dcontext_isvalid(p)){ 
	

	/* setup rendering context */
	pdp_packet_3Dcontext_set_rendering_context(p);

	/* enable texture */
	if (x->x_have_texture){
	    fx = pdp_packet_texture_fracx(pt);
	    fy = pdp_packet_texture_fracy(pt);
	    glEnable(GL_TEXTURE_2D);
	    pdp_packet_texture_make_current(pt);
	    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);	   

	    /* scale texture matrix to reflect subtexture's coords */
	    glMatrixMode(GL_TEXTURE);
	    //glLoadIdentity();
	    glPushMatrix();
	    glScalef(fx, fy, 1);
	    glMatrixMode(GL_MODELVIEW);

	    gluQuadricTexture(x->x_quadric, 1);
	}

	/* call the generating method */
	if (x->x_method) (*x->x_method)(x);

	/* disable texture */
	if (x->x_have_texture){
	    glMatrixMode(GL_TEXTURE);
	    glPopMatrix();
	    glMatrixMode(GL_MODELVIEW);
	    glDisable(GL_TEXTURE_2D);
	    gluQuadricTexture(x->x_quadric, 0);
	}

    }

    /* you know the drill: command done, sword in belly. */
    pdp_packet_mark_unused(x->x_texture_packet);
    pdp_dpd_command_suicide(x);

}

static void pdp_3d_draw_p0(t_pdp_3d_draw *x, t_floatarg f){x->x_p0 = f;}
static void pdp_3d_draw_p1(t_pdp_3d_draw *x, t_floatarg f){x->x_p1 = f;}
static void pdp_3d_draw_p2(t_pdp_3d_draw *x, t_floatarg f){x->x_p2 = f;}
static void pdp_3d_draw_p3(t_pdp_3d_draw *x, t_floatarg f){x->x_p3 = f;}


t_class *pdp_3d_draw_class;



void pdp_3d_draw_free(t_pdp_3d_draw *x)
{
    pdp_3dp_base_free(x);
    gluDeleteQuadric(x->x_quadric);
    pdp_dpd_commandfactory_free(&x->x_clist);
}

void pdp_3d_draw_object(t_pdp_3d_draw *x, t_symbol *s)
{
    /* find out if it is a buffer operation */
    if      (s == gensym("clear"))   {x->x_method = (t_pdp_method)draw_clear;   x->x_inlets = 0;}

    /* if not, find out which object we need to draw */
    else if (s == gensym("triangle"))  {x->x_method = (t_pdp_method)draw_triangle;  x->x_inlets = 1;}
    else if (s == gensym("wtriangle")) {x->x_method = (t_pdp_method)draw_wtriangle; x->x_inlets = 1;}
    else if (s == gensym("square"))    {x->x_method = (t_pdp_method)draw_square;  x->x_inlets = 1;}
    else if (s == gensym("wsquare"))   {x->x_method = (t_pdp_method)draw_wsquare; x->x_inlets = 1;}
    else if (s == gensym("cube"))      {x->x_method = (t_pdp_method)draw_cube;    x->x_inlets = 1;}
    else if (s == gensym("wcube"))     {x->x_method = (t_pdp_method)draw_wcube;   x->x_inlets = 1;}
    else if (s == gensym("sphere"))    {x->x_method = (t_pdp_method)draw_sphere;  x->x_inlets = 3;}
    else if (s == gensym("wsphere"))   {x->x_method = (t_pdp_method)draw_wsphere; x->x_inlets = 3;}
    else if (s == gensym("torus"))     {x->x_method = (t_pdp_method)draw_torus;   x->x_inlets = 4;}
    else if (s == gensym("wtorus"))    {x->x_method = (t_pdp_method)draw_wtorus;  x->x_inlets = 4;}
    else if (s == gensym("cone"))      {x->x_method = (t_pdp_method)draw_cone;    x->x_inlets = 4;}
    else if (s == gensym("wcone"))     {x->x_method = (t_pdp_method)draw_wcone;   x->x_inlets = 4;}
    else if (s == gensym("teapot"))    {x->x_method = (t_pdp_method)draw_teapot;  x->x_inlets = 1;}
    else if (s == gensym("wteapot"))   {x->x_method = (t_pdp_method)draw_wteapot; x->x_inlets = 1;}

    else if (s == gensym("dodeca"))  {x->x_method = (t_pdp_method)draw_dodeca;  x->x_inlets = 0;}
    else if (s == gensym("icosa"))   {x->x_method = (t_pdp_method)draw_icosa;   x->x_inlets = 0;}
    else if (s == gensym("octa"))    {x->x_method = (t_pdp_method)draw_octa;    x->x_inlets = 0;}
    else if (s == gensym("tetra"))   {x->x_method = (t_pdp_method)draw_tetra;   x->x_inlets = 0;}
    else if (s == gensym("wdodeca")) {x->x_method = (t_pdp_method)draw_wdodeca;  x->x_inlets = 0;}
    else if (s == gensym("wicosa"))  {x->x_method = (t_pdp_method)draw_wicosa;   x->x_inlets = 0;}
    else if (s == gensym("wocta"))   {x->x_method = (t_pdp_method)draw_wocta;    x->x_inlets = 0;}
    else if (s == gensym("wtetra"))  {x->x_method = (t_pdp_method)draw_wtetra;   x->x_inlets = 0;}

    else {
	post("pdp_3d_draw: object %s not found", s->s_name);
	x->x_method = 0;
	x->x_inlets = 0;
    }

    // the number of texture inlets
    x->x_tex_in = 1;
}


void *pdp_3d_draw_new(t_symbol *s, t_floatarg p0, t_floatarg p1, t_floatarg p2, t_floatarg p3)
{
    t_pdp_3d_draw *x = (t_pdp_3d_draw *)pd_new(pdp_3d_draw_class);
    char param[] = "p0";
    int i;

    /* super init */
    pdp_3dp_base_init(x);

    x->x_p0 = p0;
    x->x_p1 = p1;
    x->x_p2 = p2;
    x->x_p3 = p3;

    /* set the object & number of inlets */
    pdp_3d_draw_object(x, s);

    /* create texture inlets */
    for(i=0; i<x->x_tex_in; i++){
	pdp_base_add_pdp_inlet(x);
    }

    /* create additional inlets */
    for(i=0; i<x->x_inlets; i++){
	pdp_base_add_gen_inlet(x, gensym("float"), gensym(param));
	param[1]++;
    }

    /* create dpd outlet */
    pdp_3dp_base_add_outlet(x, (t_pdp_method)draw_process, 0);

    /* setup quadric */
    x->x_quadric = gluNewQuadric();

    /* init command list */
    pdp_dpd_commandfactory_init(&x->x_clist, sizeof(t_drawcommand));

    /* register command factory method */
    pdp_dpd_base_register_command_factory_method(x, (t_pdp_newmethod)pdp_3d_draw_get_command_object);
       



    return (void *)x;
}


#ifdef __cplusplus
extern "C"
{
#endif


void pdp_3d_draw_setup(void)
{


    pdp_3d_draw_class = class_new(gensym("3dp_draw"), (t_newmethod)pdp_3d_draw_new,
    	(t_method)pdp_3d_draw_free, sizeof(t_pdp_3d_draw), 0, A_SYMBOL, 
				  A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
    pdp_3dp_base_setup(pdp_3d_draw_class);

    class_addmethod(pdp_3d_draw_class, (t_method)pdp_3d_draw_p0, gensym("p0"),  A_DEFFLOAT, A_NULL);  
    class_addmethod(pdp_3d_draw_class, (t_method)pdp_3d_draw_p1, gensym("p1"),  A_DEFFLOAT, A_NULL);  
    class_addmethod(pdp_3d_draw_class, (t_method)pdp_3d_draw_p2, gensym("p2"),  A_DEFFLOAT, A_NULL);  
    class_addmethod(pdp_3d_draw_class, (t_method)pdp_3d_draw_p3, gensym("p3"),  A_DEFFLOAT, A_NULL);  

    class_addmethod(pdp_3d_draw_class, (t_method)pdp_3d_draw_delete_texture, gensym("delete_texture"),  A_DEFFLOAT, A_NULL);  

}

#ifdef __cplusplus
}
#endif

--- NEW FILE: pdp_3d_light.c ---
/*
 *   Pure Data Packet module.
 *   Copyright (c) by Tom Schouten <pdp at zzz.kotnet.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */


#include <GL/gl.h>
#include "pdp_opengl.h"
#include "pdp_3dp_base.h"

typedef struct pdp_3d_light_struct
{
    t_pdp_3dp_base x_base;

    //float x_centerx;
    //float x_centery;
    //float x_centerz;
    int x_index;

} t_pdp_3d_light;



static void pdp_3d_light_process(t_pdp_3d_light *x)
{
    int p = pdp_3dp_base_get_context_packet(x);
    int i;
    GLfloat ambient[] = {.7,.7,.7,1};
    GLfloat diffuse[] = {.6,.6,.6,1};
    GLfloat specular[] = {1, 1, 1, 1};
    GLfloat shininess[] = {50};
    GLfloat position[] = {0,0,1,1};
    GLfloat intensity[] = {1,1,1,0};

    int light = GL_LIGHT0 + x->x_index;

    /* check if it's a valid buffer we can draw in */
    if (pdp_packet_3Dcontext_isvalid(p)){

	position[0] = 0; //x->x_centerx;
	position[1] = 0; //x->x_centery;
	position[2] = 0; //x->x_centerz;
	
	/* set rendering context */
	//pdp_packet_3Dcontext_set_rendering_context(p);

	/* setup lighting */
	
	glEnable(GL_LIGHTING);
	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
	glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
	glEnable(GL_COLOR_MATERIAL);
	//glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
	glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
	glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
	glMaterialfv(GL_FRONT, GL_SHININESS, shininess);
	glLightfv(light, GL_POSITION, position);
	//glLightfv(light, GL_DIFFUSE, intensity);
	glEnable(light);


	/* ALPHA HACK */
	//glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
	//glEnable(GL_BLEND);
	//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	//glBlendFunc(GL_SRC_ALPHA, GL_ONE);
	//glEnable(GL_ALPHA_TEST);
	//glAlphaFunc(GL_GREATER, 0.f);

    }

}



//static void pdp_3d_light_centerx(t_pdp_3d_light *x, t_floatarg f){x->x_centerx = f;}
//static void pdp_3d_light_centery(t_pdp_3d_light *x, t_floatarg f){x->x_centery = f;}
//static void pdp_3d_light_centerz(t_pdp_3d_light *x, t_floatarg f){x->x_centerz = f;}


t_class *pdp_3d_light_class;



void pdp_3d_light_free(t_pdp_3d_light *x)
{
    pdp_3dp_base_free(x);
}

void *pdp_3d_light_new(t_floatarg fi, t_floatarg cx, t_floatarg cy, t_floatarg cz)
{
    t_pdp_3d_light *x = (t_pdp_3d_light *)pd_new(pdp_3d_light_class);

    /* super init */
    pdp_3dp_base_init(x);

    if (fi < 0) fi = 0;

    x->x_index = (int)fi;
    //x->x_centerx = cx;
    //x->x_centery = cy;
    //x->x_centerz = cz;

    /* io */
    //pdp_base_add_gen_inlet(x, gensym("float"), gensym("centerx"));
    //pdp_base_add_gen_inlet(x, gensym("float"), gensym("centery"));
    //pdp_base_add_gen_inlet(x, gensym("float"), gensym("centerz"));

    /* add dpd outlet */
    pdp_3dp_base_add_outlet(x,  (t_pdp_method)pdp_3d_light_process, 0);

    return (void *)x;
}


#ifdef __cplusplus
extern "C"
{
#endif


void pdp_3d_light_setup(void)
{


    pdp_3d_light_class = class_new(gensym("3dp_light"), (t_newmethod)pdp_3d_light_new,
    	(t_method)pdp_3d_light_free, sizeof(t_pdp_3d_light), 0, 
				   A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_NULL);

    pdp_3dp_base_setup(pdp_3d_light_class);

    //class_addmethod(pdp_3d_light_class, (t_method)pdp_3d_light_centerx, gensym("centerx"),  A_DEFFLOAT, A_NULL);   
    //class_addmethod(pdp_3d_light_class, (t_method)pdp_3d_light_centery, gensym("centery"),  A_DEFFLOAT, A_NULL);   
    //class_addmethod(pdp_3d_light_class, (t_method)pdp_3d_light_centerz, gensym("centerz"),  A_DEFFLOAT, A_NULL);   

}

#ifdef __cplusplus
}
#endif

--- NEW FILE: pdp_3d_push.c ---
/*
 *   Pure Data Packet module.
 *   Copyright (c) by Tom Schouten <pdp at zzz.kotnet.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */



#include <GL/gl.h>
#include "pdp_opengl.h"
#include "pdp_3dp_base.h"

typedef struct pdp_3d_push_struct
{
    t_pdp_3dp_base x_base;
    GLenum x_matrix;
    int x_change_mode;

} t_pdp_3d_push;



static void pdp_3d_push_process_right(t_pdp_3d_push *x)
{
    int p = pdp_3dp_base_get_context_packet(x);
    if (-1 != p){

	/* push one of the matrices */
	glMatrixMode(x->x_matrix);
	glPushMatrix();

	/* set default matrix to modelview */
	if (!x->x_change_mode) glMatrixMode(GL_MODELVIEW);

    }
}
static void pdp_3d_push_process_left(t_pdp_3d_push *x)
{
    int p = pdp_3dp_base_get_context_packet(x);
    if (-1 != p){

	/* restore the saved matrix */
	glMatrixMode(x->x_matrix);
	glPopMatrix();

	/* set default matrix back to modelview */
	glMatrixMode(GL_MODELVIEW);

    }

}


static void pdp_3d_mode_process_right(t_pdp_3d_push *x)
{
    int p = pdp_3dp_base_get_context_packet(x);
    if (-1 != p){

	/* change matrix mode */
	glMatrixMode(x->x_matrix);

    }
}

static void pdp_3d_mode_process_left(t_pdp_3d_push *x)
{
    int p = pdp_3dp_base_get_context_packet(x);
    if (-1 != p){

	/* restore default matrix to modelview */
	glMatrixMode(GL_MODELVIEW);

    }
}


static void pdp_3d_push_setmatrix(t_pdp_3d_push *x, t_symbol *s)
{
    GLenum m;

    /* find out which matrix to push */
    if (s == gensym("projection")) m = GL_PROJECTION;
    else if (s == gensym("modelview")) m = GL_MODELVIEW;
    else if (s == gensym("texture")) m = GL_TEXTURE;
    else if (s == gensym("color")) m = GL_COLOR;

    /* default is modelview */
    else m = GL_MODELVIEW;

    x->x_matrix = m;
}


t_class *pdp_3d_push_class;



void pdp_3d_push_free(t_pdp_3d_push *x)
{
    pdp_3dp_base_free(x);
}

void *pdp_3d_push_mode_new(t_symbol *s)
{
    t_pdp_3d_push *x = (t_pdp_3d_push *)pd_new(pdp_3d_push_class);

    /* super init */
    pdp_3dp_base_init(x);

    /* setup which matrix we are talking about */
    pdp_3d_push_setmatrix(x, s);

    x->x_change_mode = 0;

    return (void *)x;
}

void *pdp_3d_push_new(t_symbol *s, t_floatarg f)
{
    t_pdp_3d_push *x = (t_pdp_3d_push *)pdp_3d_push_mode_new(s);

    /* create dpd outlets */
    pdp_3dp_base_add_outlet(x, (t_pdp_method)pdp_3d_push_process_left, 0);
    pdp_3dp_base_add_outlet(x, (t_pdp_method)pdp_3d_push_process_right, 0);

    x->x_change_mode = (f != 0.0f);
    
    return (void *)x;
}


void *pdp_3d_mode_new(t_symbol *s)
{
    t_pdp_3d_push *x = (t_pdp_3d_push *)pdp_3d_push_mode_new(s);

    /* create dpd outlets */
    pdp_3dp_base_add_outlet(x, (t_pdp_method)pdp_3d_mode_process_left, 0);
    pdp_3dp_base_add_outlet(x, (t_pdp_method)pdp_3d_mode_process_right, 0);


    return (void *)x;
}



#ifdef __cplusplus
extern "C"
{
#endif


void pdp_3d_push_setup(void)
{


    pdp_3d_push_class = class_new(gensym("3dp_push"), (t_newmethod)pdp_3d_push_new,
    	(t_method)pdp_3d_push_free, sizeof(t_pdp_3d_push), 0, A_DEFSYMBOL, A_NULL);

    class_addcreator((t_newmethod)pdp_3d_mode_new, gensym("3dp_mode"), A_DEFSYMBOL, A_NULL);

    pdp_3dp_base_setup(pdp_3d_push_class);

}

#ifdef __cplusplus
}
#endif

--- NEW FILE: pdp_3d_view.c ---
/*
 *   Pure Data Packet module.
 *   Copyright (c) by Tom Schouten <pdp at zzz.kotnet.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */



#include <GL/gl.h>
#include "pdp_opengl.h"
#include "pdp_3dp_base.h"



/* PD OBJECT */
typedef struct _pdp_3d_view
{
    t_pdp_3dp_base x_base;
    t_pdp_dpd_commandfactory x_clist;

    float x_p0;
    float x_p1;
    float x_p2;
    float x_p3;
    t_pdp_method x_method;


    int x_inlets;
} t_pdp_3d_view;


/* COMMAND OBJECT */
typedef struct _viewcommand
{
    t_pdp_dpd_command x_head; // viewcommand base
    t_pdp_3d_view *x_x;       // command owner
    int x_context_packet;
    float x_p0;
    float x_p1;
    float x_p2;
    float x_p3;
    
} t_viewcommand;




/* COMMAND OBJECT METHODS */

/* rotate about the negative z axis */
static void view_rot2d(t_viewcommand *x) {glRotatef(x->x_p0, 0, 0, -1);}

/* rotate about the positive x,y,z axis */
static void view_rotx(t_viewcommand *x) {glRotatef(x->x_p0, 1, 0, 0);}
static void view_roty(t_viewcommand *x) {glRotatef(x->x_p0, 0, 1, 0);}
static void view_rotz(t_viewcommand *x) {glRotatef(x->x_p0, 0, 0, 1);}
static void view_rota(t_viewcommand *x) {glRotatef(x->x_p3, x->x_p0, x->x_p1, x->x_p2);}

/* translate along an axis */
static void view_transx(t_viewcommand *x) {glTranslatef(x->x_p0, 0, 0);}
static void view_transy(t_viewcommand *x) {glTranslatef(0, x->x_p0, 0);}
static void view_transz(t_viewcommand *x) {glTranslatef(0, 0, x->x_p0);}
static void view_transxyz(t_viewcommand *x) {glTranslatef(x->x_p0, x->x_p1, x->x_p2);}

/* rotate about the positive x,y,z axis */
static void view_scalex(t_viewcommand *x) {glScalef(x->x_p0, 1, 1);}
static void view_scaley(t_viewcommand *x) {glScalef(1, x->x_p0, 1);}
static void view_scalez(t_viewcommand *x) {glScalef(1, 1, x->x_p0);}
static void view_scale(t_viewcommand *x) {glScalef(x->x_p0, x->x_p0, x->x_p0);}

/* specials */
static void view_reset_3d(t_viewcommand *x) {pdp_packet_3Dcontext_setup_3d_context(x->x_context_packet);}
static void view_scale_aspect(t_viewcommand *x) {glScalef(pdp_packet_3Dcontext_subaspect(x->x_context_packet),1,1);}


/* process command */
static void view_process(t_viewcommand *x)
{
    int p = x->x_context_packet;
 
    /* check if it's a valid context buffer we can draw in */
    if (pdp_packet_3Dcontext_isvalid(p)){ 

	/* setup rendering context */
	pdp_packet_3Dcontext_set_rendering_context(p);

	/* call the generating method */
	if (x->x_x->x_method) (*x->x_x->x_method)(x);
    }

    /* suicide */
    pdp_dpd_command_suicide(x);
}



/* command object factory method */
void *pdp_3d_view_get_command_object(t_pdp_3d_view *x)
{
    t_viewcommand *c = (t_viewcommand *)pdp_dpd_commandfactory_get_new_command(&x->x_clist);
    c->x_p0 = x->x_p0;
    c->x_p1 = x->x_p1;
    c->x_p2 = x->x_p2;
    c->x_p3 = x->x_p3;
    c->x_context_packet = pdp_3dp_base_get_context_packet(x);
    c->x_x = x;

    return c;
}



/* PD OBJECT METHODS */

static void pdp_3d_view_p0(t_pdp_3d_view *x, t_floatarg f){x->x_p0 = f;}
static void pdp_3d_view_p1(t_pdp_3d_view *x, t_floatarg f){x->x_p1 = f;}
static void pdp_3d_view_p2(t_pdp_3d_view *x, t_floatarg f){x->x_p2 = f;}
static void pdp_3d_view_p3(t_pdp_3d_view *x, t_floatarg f){x->x_p3 = f;}


t_class *pdp_3d_view_class;



void pdp_3d_view_free(t_pdp_3d_view *x)
{
    pdp_dpd_commandfactory_free(&x->x_clist);
    pdp_3dp_base_free(x);
}

void *pdp_3d_view_new(t_symbol *s, t_floatarg p0, t_floatarg p1, t_floatarg p2, t_floatarg p3)
{
    t_pdp_3d_view *x = (t_pdp_3d_view *)pd_new(pdp_3d_view_class);
    char param[] = "p0";
    int i;

    /* super init */
    pdp_3dp_base_init(x);

    x->x_p0 = p0;
    x->x_p1 = p1;
    x->x_p2 = p2;
    x->x_p3 = p3;

    /* find out which transform we need to apply */
    if      (s == gensym("rot2d")) {x->x_method = (t_pdp_method)view_rot2d; x->x_inlets = 1;}

    else if (s == gensym("rotx"))  {x->x_method = (t_pdp_method)view_rotx;  x->x_inlets = 1;}
    else if (s == gensym("roty"))  {x->x_method = (t_pdp_method)view_roty;  x->x_inlets = 1;}
    else if (s == gensym("rotz"))  {x->x_method = (t_pdp_method)view_rotz;  x->x_inlets = 1;}
    else if (s == gensym("rota"))  {x->x_method = (t_pdp_method)view_rota;  x->x_inlets = 4;}

    else if (s == gensym("transx"))    {x->x_method = (t_pdp_method)view_transx;  x->x_inlets = 1;}
    else if (s == gensym("transy"))    {x->x_method = (t_pdp_method)view_transy;  x->x_inlets = 1;}
    else if (s == gensym("transz"))    {x->x_method = (t_pdp_method)view_transz;  x->x_inlets = 1;}
    else if (s == gensym("transxyz"))  {x->x_method = (t_pdp_method)view_transxyz;  x->x_inlets = 3;}

    else if (s == gensym("scalex"))  {x->x_method = (t_pdp_method)view_scalex;  x->x_inlets = 1;}
    else if (s == gensym("scaley"))  {x->x_method = (t_pdp_method)view_scaley;  x->x_inlets = 1;}
    else if (s == gensym("scalez"))  {x->x_method = (t_pdp_method)view_scalez;  x->x_inlets = 1;}
    else if (s == gensym("scale"))   {x->x_method = (t_pdp_method)view_scale;  x->x_inlets = 1;}

    else if (s == gensym("scale_aspect"))   {x->x_method = (t_pdp_method)view_scale_aspect;  x->x_inlets = 0;}
    else if (s == gensym("reset"))   {x->x_method = (t_pdp_method)view_reset_3d;  x->x_inlets = 0;}

    else {
	post("pdp_view: view transformation %s not found", s->s_name);
	x->x_method = 0;
	x->x_inlets = 0;
    }

    /* create additional inlets */
    for(i=0; i<x->x_inlets; i++){
	pdp_base_add_gen_inlet(x, gensym("float"), gensym(param));
	param[1]++;
    }

    /* create dpd outlet */
    pdp_3dp_base_add_outlet(x, (t_pdp_method)view_process, 0);

    /* init command factory */
    pdp_dpd_commandfactory_init(&x->x_clist, sizeof(t_viewcommand));

    /* register command factory method */
    pdp_dpd_base_register_command_factory_method(x, (t_pdp_newmethod)pdp_3d_view_get_command_object);
       

    return (void *)x;
}


#ifdef __cplusplus
extern "C"
{
#endif


void pdp_3d_view_setup(void)
{


    pdp_3d_view_class = class_new(gensym("3dp_view"), (t_newmethod)pdp_3d_view_new,
    	(t_method)pdp_3d_view_free, sizeof(t_pdp_3d_view), 0, A_SYMBOL, 
				   A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT,A_DEFFLOAT, A_NULL);

    pdp_3dp_base_setup(pdp_3d_view_class);

    class_addmethod(pdp_3d_view_class, (t_method)pdp_3d_view_p0, gensym("p0"),  A_DEFFLOAT, A_NULL);  
    class_addmethod(pdp_3d_view_class, (t_method)pdp_3d_view_p1, gensym("p1"),  A_DEFFLOAT, A_NULL);  
    class_addmethod(pdp_3d_view_class, (t_method)pdp_3d_view_p2, gensym("p2"),  A_DEFFLOAT, A_NULL);  
    class_addmethod(pdp_3d_view_class, (t_method)pdp_3d_view_p3, gensym("p3"),  A_DEFFLOAT, A_NULL);  

}

#ifdef __cplusplus
}
#endif

--- NEW FILE: pdp_3d_for.c ---
/*
 *   Pure Data Packet module.
 *   Copyright (c) by Tom Schouten <pdp at zzz.kotnet.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

/* a for loop for 3dp packets
   this can later be adapted to a for loop for dpd packets. */

#include "pdp_opengl.h"
#include "pdp_internals.h"


typedef struct pdp_3d_for_struct
{
    t_object x_obj;

    t_int x_count;

    t_outlet *x_outlet_dpd;
    t_outlet *x_outlet_float;

} t_pdp_3d_for;



static void pdp_3d_for_input_0(t_pdp_3d_for *x, t_symbol *s, t_floatarg f)
{
    int i;

    /* trigger on "accumulate" */

    if (s == gensym("accumulate")){
	for (i=0; i<x->x_count; i++){
	    outlet_float(x->x_outlet_float, (float)i);
	    outlet_dpd(x->x_outlet_dpd, (int)f);
	}
    }
}

static void pdp_3d_for_count(t_pdp_3d_for *x, t_floatarg f)
{
    int count = (int)f;
    if (count >= 0) x->x_count = count;
}


static void pdp_3d_for_free(t_pdp_3d_for *x)
{
}

t_class *pdp_3d_for_class;



void *pdp_3d_for_new(t_floatarg f)
{
    int count = (int)f;

    t_pdp_3d_for *x = (t_pdp_3d_for *)pd_new(pdp_3d_for_class);

    inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("count"));

    x->x_outlet_dpd = outlet_new(&x->x_obj, &s_anything); 
    x->x_outlet_float = outlet_new(&x->x_obj, &s_float); 
    x->x_count = (count > 0) ? count : 1;

    return (void *)x;
}


#ifdef __cplusplus
extern "C"
{
#endif


void pdp_3d_for_setup(void)
{


    pdp_3d_for_class = class_new(gensym("3dp_for"), (t_newmethod)pdp_3d_for_new,
    	(t_method)pdp_3d_for_free, sizeof(t_pdp_3d_for), 0, A_DEFFLOAT, A_NULL);

    class_addmethod(pdp_3d_for_class, (t_method)pdp_3d_for_input_0, gensym("dpd"),  A_SYMBOL, A_DEFFLOAT, A_NULL);
    class_addmethod(pdp_3d_for_class, (t_method)pdp_3d_for_count, gensym("count"), A_FLOAT, A_NULL);

}

#ifdef __cplusplus
}
#endif





More information about the Pd-cvs mailing list