Max 5 API Reference
00001 /* 00002 * Copyright 2001-2005 - Cycling '74 00003 * Randall Jones - rej@2uptech.com 00004 * 00005 * OpenGL OB3D interface for maintaining OpenGL state. 00006 */ 00007 00008 00009 /** 00010 * @defgroup ob3dmod OB3D Module 00011 @ingroup jitter 00012 */ 00013 00014 00015 /****************************************************************************/ 00016 00017 #include "jit.gl.h" 00018 #include "jit.gl.ob3d.h" 00019 #include "jit.gl.ob3d.internal.h" 00020 #include "jit.gl.readback.h" 00021 #include "trackball.h" 00022 #include "ext_obex.h" 00023 00024 00025 void * g_jit_gl_current_context; //obsolete 00026 void * g_jit_gl_current_ob3d; 00027 00028 long _jit_glerrorcheck = 1; 00029 long _jit_glattribpush = 0; 00030 long _jit_glmatrixdebug = 0; 00031 00032 static t_symbol *ps_texture=NULL; 00033 static t_symbol *ps_ob3d_get_offset=NULL; 00034 00035 static long jit_ob3d_get_offset(void *x); 00036 00037 00038 /****************************************************************************/ 00039 00040 void * jit_gl_current_ob3d_set(void * p) 00041 { 00042 void *last=g_jit_gl_current_ob3d; 00043 g_jit_gl_current_ob3d = p; 00044 return last; 00045 } 00046 00047 void * jit_gl_current_ob3d_get() 00048 { 00049 return g_jit_gl_current_ob3d; 00050 } 00051 00052 /****************************************************************************/ 00053 00054 /** 00055 * Adds default methods and attributes to the OB3D class. 00056 * 00057 * @ingroup ob3dmod 00058 * 00059 * @param jit_class Jitter class pointer 00060 * @param oboffset object struct byte offset for t_jit_ob3d pointer 00061 * @param flags flags to override default OB3D behavior 00062 * 00063 * @return t_jit_class3d pointer (opaque) 00064 * 00065 */ 00066 void *jit_ob3d_setup(void * jit_class, long oboffset, long flags) 00067 { 00068 t_jit_class3d *x; 00069 long attrflags = 0; 00070 t_jit_object *attr; 00071 00072 if (!ps_texture) { 00073 ps_texture = gensym("texture"); 00074 ps_ob3d_get_offset = gensym("ob3d_get_offset"); 00075 } 00076 00077 if (x=(t_jit_class3d *)jit_getbytes(sizeof(t_jit_class3d))) 00078 { 00079 x->oboffset = oboffset; 00080 x->flags = flags; 00081 00082 // add storage for pointer to ob3d struct in message list. 00083 jit_class_addmethod(jit_class, (method)x, JIT_CLASS3D_FINDER, A_CANT, 0); 00084 jit_class_addmethod(jit_class, (method)jit_ob3d_get_offset, "ob3d_get_offset", A_CANT, 0); 00085 00086 // add draw method called from bang. this wraps the jit object's "ob3d_draw" method. 00087 jit_class_addmethod(jit_class, (method)jit_ob3d_draw, "draw", A_DEFER_LOW, 0); 00088 jit_class_addmethod(jit_class, (method)jit_ob3d_drawraw, "drawraw", A_DEFER_LOW, 0); 00089 jit_class_addmethod(jit_class, (method)jit_ob3d_drawimmediate, "drawimmediate", A_DEFER_LOW, 0); 00090 00091 if ((!GET_FLAG(flags, JIT_OB3D_IS_SLAB))&&(!GET_FLAG(flags, JIT_OB3D_NO_TEXTURE))) 00092 jit_class_addmethod(jit_class, (method)jit_ob3d_jit_gl_texture, "jit_gl_texture", A_DEFER_LOW, 0); 00093 00094 // add ui method called from jit.gl.render. 00095 jit_class_addmethod(jit_class, (method)jit_ob3d_ui, "do_ob3d_ui", A_CANT, 0); 00096 00097 // set and get renderer. 00098 jit_class_addmethod(jit_class, (method)jit_ob3d_renderer_set, "render_ptr", A_CANT, 0); 00099 jit_class_addmethod(jit_class, (method)jit_ob3d_renderer_get, "get_render_ptr", A_CANT, 0); 00100 00101 // get draw chunk. 00102 jit_class_addmethod(jit_class, (method)jit_ob3d_get_chunk, "get_chunk", A_CANT, 0); 00103 00104 // screen/world coordinate conversion. 00105 jit_class_addmethod(jit_class, (method)jit_ob3d_world_to_screen, "world_to_screen", A_CANT, 0); 00106 jit_class_addmethod(jit_class, (method)jit_ob3d_screen_to_world, "screen_to_world", A_CANT, 0); 00107 00108 // add standard 3d attributes. 00109 attrflags = JIT_ATTR_GET_DEFER_LOW | JIT_ATTR_SET_USURP_LOW; 00110 00111 if (!GET_FLAG(flags, JIT_OB3D_IS_RENDERER)) // default on 00112 { 00113 // draw target 00114 attr = jit_object_new(_jit_sym_jit_attr_offset, "drawto", _jit_sym_symbol, 00115 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_dest_name_set, // custom 00116 calcoffset(t_jit_ob3d, dest_name)); 00117 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00118 jit_class_addattr(jit_class, attr); 00119 00120 attr = jit_object_new(_jit_sym_jit_attr_offset, "layer", _jit_sym_long, 00121 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_layer_set, // custom 00122 calcoffset(t_jit_ob3d, layer)); 00123 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00124 jit_class_addattr(jit_class, attr); 00125 00126 } 00127 00128 if (GET_FLAG(flags, JIT_OB3D_HAS_CAMERA)) // default off 00129 { 00130 // camera: x y z 00131 attr = jit_object_new(_jit_sym_jit_attr_offset_array,"camera",_jit_sym_float32, 3, attrflags, 00132 (method)jit_ob3d_attr_offset_array_get,(method)jit_ob3d_attr_offset_array_set,0L,calcoffset(t_jit_ob3d,camera)); 00133 // object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00134 jit_class_addattr(jit_class,attr); 00135 // lookat: x y z 00136 attr = jit_object_new(_jit_sym_jit_attr_offset_array,"lookat",_jit_sym_float32, 3, attrflags, 00137 (method)jit_ob3d_attr_offset_array_get,(method)jit_ob3d_attr_offset_array_set,0L,calcoffset(t_jit_ob3d,lookat)); 00138 // object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00139 jit_class_addattr(jit_class,attr); 00140 // up: x y z 00141 attr = jit_object_new(_jit_sym_jit_attr_offset_array,"up",_jit_sym_float32, 3, attrflags, 00142 (method)jit_ob3d_attr_offset_array_get,(method)jit_ob3d_attr_offset_array_set,0L,calcoffset(t_jit_ob3d,up)); 00143 // object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00144 jit_class_addattr(jit_class,attr); 00145 // lens angle 00146 attr = jit_object_new(_jit_sym_jit_attr_offset,"lens_angle",_jit_sym_float32,attrflags, 00147 (method)jit_ob3d_attr_offset_get,(method)jit_ob3d_lens_angle_set,calcoffset(t_jit_ob3d,lens_angle)); 00148 // object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00149 jit_class_addattr(jit_class,attr); 00150 // near clip 00151 attr = jit_object_new(_jit_sym_jit_attr_offset,"near_clip",_jit_sym_float32,attrflags, 00152 (method)jit_ob3d_attr_offset_get,(method)jit_ob3d_attr_offset_set,calcoffset(t_jit_ob3d,near_clip)); 00153 // object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00154 jit_class_addattr(jit_class,attr); 00155 // far clip 00156 attr = jit_object_new(_jit_sym_jit_attr_offset,"far_clip",_jit_sym_float32,attrflags, 00157 (method)jit_ob3d_attr_offset_get,(method)jit_ob3d_attr_offset_set,calcoffset(t_jit_ob3d,far_clip)); 00158 // object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00159 jit_class_addattr(jit_class,attr); 00160 // ortho 00161 attr = jit_object_new(_jit_sym_jit_attr_offset, "ortho", _jit_sym_long, 00162 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00163 calcoffset(t_jit_ob3d, ortho)); 00164 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00165 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"enumindex"); 00166 object_addattr_parse(attr,"enumvals",_jit_sym_atom,0,"\"Off (Perspective)\" \"Orthographic (Lens Angle)\" \"Orthographic (No Lens Angle)\""); 00167 jit_class_addattr(jit_class, attr); 00168 } 00169 00170 // enable 00171 attr = jit_object_new(_jit_sym_jit_attr_offset, "enable", _jit_sym_long, 00172 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00173 calcoffset(t_jit_ob3d, enable)); 00174 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00175 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00176 jit_class_addattr(jit_class, attr); 00177 00178 // dest_dim -- sent by gl.render if a render destination exists. otherwise, humans can set it. 00179 attr = jit_object_new(_jit_sym_jit_attr_offset_array, "dest_dim", _jit_sym_long, 2, 00180 attrflags, (method)jit_ob3d_attr_offset_array_get, (method)jit_ob3d_attr_offset_array_set, 00181 0L, calcoffset(t_jit_ob3d, dest_dim)); 00182 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00183 jit_class_addattr(jit_class, attr); 00184 00185 // position 00186 attr = jit_object_new(_jit_sym_jit_attr_offset_array, "position", _jit_sym_float32, 3, 00187 attrflags, (method)jit_ob3d_attr_offset_array_get, (method)jit_ob3d_attr_offset_array_set, 00188 0L, calcoffset(t_jit_ob3d, position)); 00189 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00190 jit_class_addattr(jit_class, attr); 00191 00192 if (!GET_FLAG(flags, JIT_OB3D_NO_ROTATION_SCALE)) // default on 00193 { 00194 // rotation 00195 attr = jit_object_new(_jit_sym_jit_attr_offset_array, "rotate", _jit_sym_float32, 4, 00196 attrflags, (method)jit_ob3d_attr_offset_array_get, (method)jit_ob3d_attr_offset_array_set, 00197 0L, calcoffset(t_jit_ob3d, rotation)); 00198 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00199 jit_class_addattr(jit_class, attr); 00200 00201 // rotatexyz 00202 attr = jit_object_new(_jit_sym_jit_attr_offset_array, "rotatexyz", _jit_sym_float32, 4, 00203 attrflags, (method)jit_ob3d_attr_rotatexyz_get, (method)jit_ob3d_attr_rotatexyz_set, 00204 0L, 0L); 00205 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00206 jit_class_addattr(jit_class, attr); 00207 00208 // scale 00209 attr = jit_object_new(_jit_sym_jit_attr_offset_array, "scale", _jit_sym_float32, 3, 00210 attrflags, (method)jit_ob3d_attr_offset_array_get, (method)jit_ob3d_scale_set, 00211 0L, calcoffset(t_jit_ob3d, scale)); 00212 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00213 jit_class_addattr(jit_class, attr); 00214 00215 // viewalign 00216 attr = jit_object_new(_jit_sym_jit_attr_offset, "viewalign", _jit_sym_long, 00217 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00218 calcoffset(t_jit_ob3d, viewalign)); 00219 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00220 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00221 jit_class_addattr(jit_class, attr); 00222 00223 // transform_reset 00224 attr = jit_object_new(_jit_sym_jit_attr_offset, "transform_reset", _jit_sym_long, 00225 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00226 calcoffset(t_jit_ob3d, transform_reset)); 00227 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00228 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"enumindex"); 00229 object_addattr_parse(attr,"enumvals",_jit_sym_atom,0,"Off \"Orthographic (Aspect Preserve)\" \"Orthographic (Normalize Both Axes)\" \"Perspective (Aspect Preserve)\" \"Orthographic (Normalize Both Axes)\""); 00230 jit_class_addattr(jit_class, attr); 00231 00232 } 00233 00234 if (!GET_FLAG(flags, JIT_OB3D_NO_COLOR)) { // default on 00235 // color 00236 attr = jit_object_new(_jit_sym_jit_attr_offset_array, "color", _jit_sym_float32, 4, 00237 attrflags, (method)jit_ob3d_attr_offset_array_get, (method)jit_ob3d_attr_offset_array_set, 00238 0L, calcoffset(t_jit_ob3d, color)); 00239 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00240 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"rgba"); 00241 jit_class_addattr(jit_class, attr); 00242 00243 // aux_color 00244 attr = jit_object_new(_jit_sym_jit_attr_offset_array, "aux_color", _jit_sym_float32, 4, 00245 attrflags, (method)jit_ob3d_attr_offset_array_get, (method)jit_ob3d_attr_offset_array_set, 00246 0L, calcoffset(t_jit_ob3d, aux_color)); 00247 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00248 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"rgba"); 00249 jit_class_addattr(jit_class, attr); 00250 00251 // smooth_shading 00252 attr = jit_object_new(_jit_sym_jit_attr_offset, "smooth_shading", _jit_sym_long, 00253 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00254 calcoffset(t_jit_ob3d, smooth_shading)); 00255 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00256 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00257 jit_class_addattr(jit_class, attr); 00258 } 00259 00260 if (!GET_FLAG(flags, JIT_OB3D_NO_POLY_VARS)) // default on 00261 { 00262 // poly mode 00263 attr = jit_object_new(_jit_sym_jit_attr_offset_array, "poly_mode", _jit_sym_long, 2, 00264 attrflags, (method)jit_ob3d_attr_offset_array_get, (method)jit_ob3d_attr_offset_array_set, 00265 0L, calcoffset(t_jit_ob3d, poly_mode)); 00266 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00267 jit_class_addattr(jit_class, attr); 00268 00269 // cull_face 00270 attr = jit_object_new(_jit_sym_jit_attr_offset, "cull_face", _jit_sym_long, 00271 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00272 calcoffset(t_jit_ob3d, cull_face)); 00273 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00274 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"enumindex"); 00275 object_addattr_parse(attr,"enumvals",_jit_sym_atom,0,"Off Back Front"); 00276 jit_class_addattr(jit_class, attr); 00277 00278 // point_size 00279 attr = jit_object_new(_jit_sym_jit_attr_offset, "point_size", _jit_sym_float32, 00280 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00281 calcoffset(t_jit_ob3d, point_size)); 00282 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00283 jit_class_addattr(jit_class, attr); 00284 00285 // line_width 00286 attr = jit_object_new(_jit_sym_jit_attr_offset, "line_width", _jit_sym_float32, 00287 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00288 calcoffset(t_jit_ob3d, line_width)); 00289 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00290 jit_class_addattr(jit_class, attr); 00291 } 00292 00293 if (!GET_FLAG(flags, JIT_OB3D_NO_DEPTH)) // default on 00294 { 00295 // depth_enable 00296 attr = jit_object_new(_jit_sym_jit_attr_offset, "depth_enable", _jit_sym_long, 00297 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00298 calcoffset(t_jit_ob3d, depth_enable)); 00299 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00300 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00301 jit_class_addattr(jit_class, attr); 00302 00303 // depth_clear 00304 attr = jit_object_new(_jit_sym_jit_attr_offset, "depth_clear", _jit_sym_long, 00305 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00306 calcoffset(t_jit_ob3d, depth_clear)); 00307 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00308 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00309 jit_class_addattr(jit_class, attr); 00310 00311 } 00312 00313 if (!GET_FLAG(flags, JIT_OB3D_NO_BLEND)) // default on 00314 { 00315 // blend mode 00316 attr = jit_object_new(_jit_sym_jit_attr_offset_array, "blend_mode", _jit_sym_long, 2, 00317 attrflags, (method)jit_ob3d_attr_offset_array_get, (method)jit_ob3d_attr_offset_array_set, 00318 0L, calcoffset(t_jit_ob3d, blend_mode)); 00319 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00320 jit_class_addattr(jit_class, attr); 00321 00322 // blend_enable 00323 attr = jit_object_new(_jit_sym_jit_attr_offset, "blend_enable", _jit_sym_long, 00324 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00325 calcoffset(t_jit_ob3d, blend_enable)); 00326 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00327 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00328 jit_class_addattr(jit_class, attr); 00329 } 00330 00331 if (!GET_FLAG(flags, JIT_OB3D_NO_ANTIALIAS)) 00332 { 00333 attr = jit_object_new(_jit_sym_jit_attr_offset, "antialias", _jit_sym_long, 00334 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00335 calcoffset(t_jit_ob3d, antialias)); 00336 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00337 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00338 jit_class_addattr(jit_class, attr); 00339 } 00340 00341 if (!GET_FLAG(flags, JIT_OB3D_NO_FOG)) 00342 { 00343 attr = jit_object_new(_jit_sym_jit_attr_offset, "fog", _jit_sym_float32, 00344 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00345 calcoffset(t_jit_ob3d, fog)); 00346 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00347 jit_class_addattr(jit_class, attr); 00348 attr = jit_object_new(_jit_sym_jit_attr_offset_array,"fog_params",_jit_sym_float32, 7, attrflags, 00349 (method)jit_ob3d_attr_offset_array_get,(method)jit_ob3d_attr_offset_array_set,0L,calcoffset(t_jit_ob3d,fog_params)); 00350 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00351 jit_class_addattr(jit_class,attr); 00352 00353 } 00354 00355 if (GET_FLAG(flags, JIT_OB3D_HAS_LIGHTS)) // default off-- true for renderers and maybe other things in future. 00356 { 00357 // light_global_ambient 00358 attr = jit_object_new(_jit_sym_jit_attr_offset_array,"light_global_ambient",_jit_sym_float32, 4, attrflags, 00359 (method)jit_ob3d_attr_offset_array_get,(method)jit_ob3d_attr_offset_array_set,0L,calcoffset(t_jit_ob3d,light_global_ambient)); 00360 // object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00361 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"rgba"); 00362 jit_class_addattr(jit_class,attr); 00363 // light_ambient 00364 attr = jit_object_new(_jit_sym_jit_attr_offset_array,"light_ambient",_jit_sym_float32, 4, attrflags, 00365 (method)jit_ob3d_attr_offset_array_get,(method)jit_ob3d_attr_offset_array_set,0L,calcoffset(t_jit_ob3d,light_ambient)); 00366 // object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00367 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"rgba"); 00368 jit_class_addattr(jit_class,attr); 00369 // light_diffuse 00370 attr = jit_object_new(_jit_sym_jit_attr_offset_array,"light_diffuse",_jit_sym_float32, 4, attrflags, 00371 (method)jit_ob3d_attr_offset_array_get,(method)jit_ob3d_attr_offset_array_set,0L,calcoffset(t_jit_ob3d,light_diffuse)); 00372 // object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00373 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"rgba"); 00374 jit_class_addattr(jit_class,attr); 00375 // light_specular 00376 attr = jit_object_new(_jit_sym_jit_attr_offset_array,"light_specular",_jit_sym_float32, 4, attrflags, 00377 (method)jit_ob3d_attr_offset_array_get,(method)jit_ob3d_attr_offset_array_set,0L,calcoffset(t_jit_ob3d,light_specular)); 00378 // object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00379 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"rgba"); 00380 jit_class_addattr(jit_class,attr); 00381 // light_position 00382 attr = jit_object_new(_jit_sym_jit_attr_offset_array,"light_position",_jit_sym_float32, 4, attrflags, 00383 (method)jit_ob3d_attr_offset_array_get,(method)jit_ob3d_attr_offset_array_set,0L,calcoffset(t_jit_ob3d,light_position)); 00384 // object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00385 jit_class_addattr(jit_class,attr); 00386 00387 } 00388 00389 if (!GET_FLAG(flags, JIT_OB3D_NO_LIGHTING_MATERIAL)) // default on 00390 { 00391 // two sided lighting 00392 attr = jit_object_new(_jit_sym_jit_attr_offset, "two_sided", _jit_sym_long, 00393 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00394 calcoffset(t_jit_ob3d, two_sided)); 00395 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00396 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00397 jit_class_addattr(jit_class, attr); 00398 00399 // lighting_enable 00400 attr = jit_object_new(_jit_sym_jit_attr_offset, "lighting_enable", _jit_sym_long, 00401 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00402 calcoffset(t_jit_ob3d, lighting_enable)); 00403 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00404 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00405 jit_class_addattr(jit_class, attr); 00406 00407 // auto_material 00408 attr = jit_object_new(_jit_sym_jit_attr_offset, "auto_material", _jit_sym_long, 00409 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00410 calcoffset(t_jit_ob3d, auto_material)); 00411 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00412 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00413 jit_class_addattr(jit_class, attr); 00414 00415 // material properties 00416 attr = jit_object_new(_jit_sym_jit_attr_offset,"shininess",_jit_sym_float32,attrflags, 00417 (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set,calcoffset(t_jit_ob3d,shininess)); 00418 jit_attr_addfilterset_clip(attr, 0, 255, 1, 1); 00419 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00420 jit_class_addattr(jit_class,attr); 00421 attr = jit_object_new(_jit_sym_jit_attr_offset_array,"mat_ambient",_jit_sym_float32, 4, attrflags, 00422 (method)jit_ob3d_attr_offset_array_get, (method)jit_ob3d_attr_offset_array_set,0L/*fix*/,calcoffset(t_jit_ob3d,mat_ambient)); 00423 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00424 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"rgba"); 00425 jit_class_addattr(jit_class,attr); 00426 attr = jit_object_new(_jit_sym_jit_attr_offset_array,"mat_diffuse",_jit_sym_float32, 4, attrflags, 00427 (method)jit_ob3d_attr_offset_array_get, (method)jit_ob3d_attr_offset_array_set,0L/*fix*/,calcoffset(t_jit_ob3d,mat_diffuse)); 00428 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00429 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"rgba"); 00430 jit_class_addattr(jit_class,attr); 00431 attr = jit_object_new(_jit_sym_jit_attr_offset_array,"mat_specular",_jit_sym_float32, 4, attrflags, 00432 (method)jit_ob3d_attr_offset_array_get, (method)jit_ob3d_attr_offset_array_set,0L/*fix*/,calcoffset(t_jit_ob3d,mat_specular)); 00433 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00434 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"rgba"); 00435 jit_class_addattr(jit_class,attr); 00436 attr = jit_object_new(_jit_sym_jit_attr_offset_array,"mat_emission",_jit_sym_float32, 4, attrflags, 00437 (method)jit_ob3d_attr_offset_array_get, (method)jit_ob3d_attr_offset_array_set,0L/*fix*/,calcoffset(t_jit_ob3d,mat_emission)); 00438 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00439 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"rgba"); 00440 jit_class_addattr(jit_class,attr); 00441 } 00442 00443 if (!GET_FLAG(flags, JIT_OB3D_NO_TEXTURE)) // default on 00444 { 00445 // multitexture support 00446 attr = jit_object_new(_jit_sym_jit_attr_offset_array, "texture", _jit_sym_symbol, JIT_GL_MAX_TEXTUREUNITS, attrflags, 00447 (method)jit_ob3d_attr_offset_array_get,(method)jit_ob3d_texture_set,calcoffset(t_jit_ob3d,texturecount),calcoffset(t_jit_ob3d,texture)); 00448 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00449 jit_class_addattr(jit_class, attr); 00450 00451 // render to texture support 00452 attr = jit_object_new(_jit_sym_jit_attr_offset_array, "capture", _jit_sym_symbol, JIT_GL_MAX_TEXTUREUNITS, attrflags, 00453 (method)jit_ob3d_attr_offset_array_get,(method)jit_ob3d_texture_set,calcoffset(t_jit_ob3d,capturecount),calcoffset(t_jit_ob3d,capture)); 00454 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00455 jit_class_addattr(jit_class, attr); 00456 00457 // tex_map 00458 attr = jit_object_new(_jit_sym_jit_attr_offset, "tex_map", _jit_sym_long, 00459 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00460 calcoffset(t_jit_ob3d, tex_map)); 00461 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00462 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"enumindex"); 00463 object_addattr_parse(attr,"enumvals",_jit_sym_atom,0,"Off \"Object Plane\" \"Sphere Map\" \"Eye Plane\""); 00464 jit_class_addattr(jit_class, attr); 00465 attr = jit_object_new(_jit_sym_jit_attr_offset_array,"tex_plane_s",_jit_sym_float32, 4, attrflags, 00466 (method)jit_ob3d_attr_offset_array_get, (method)jit_ob3d_attr_offset_array_set,0L/*fix*/,calcoffset(t_jit_ob3d,tex_plane_s)); 00467 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00468 jit_class_addattr(jit_class,attr); 00469 attr = jit_object_new(_jit_sym_jit_attr_offset_array,"tex_plane_t",_jit_sym_float32, 4, attrflags, 00470 (method)jit_ob3d_attr_offset_array_get, (method)jit_ob3d_attr_offset_array_set,0L/*fix*/,calcoffset(t_jit_ob3d,tex_plane_t)); 00471 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00472 jit_class_addattr(jit_class,attr); 00473 00474 } 00475 00476 // axes 00477 attr = jit_object_new(_jit_sym_jit_attr_offset, "axes", _jit_sym_long, 00478 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00479 calcoffset(t_jit_ob3d, axes)); 00480 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00481 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00482 jit_class_addattr(jit_class, attr); 00483 00484 // if (!GET_FLAG(flags, JIT_OB3D_NO_SHADER)) { // default on 00485 // shader 00486 attr = jit_object_new(_jit_sym_jit_attr_offset, "shader", _jit_sym_symbol, 00487 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00488 calcoffset(t_jit_ob3d, shader)); 00489 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00490 jit_class_addattr(jit_class, attr); 00491 // } 00492 00493 00494 // inheritance groups 00495 attr = jit_object_new(_jit_sym_jit_attr_offset, "inherit_poly", _jit_sym_long, 00496 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00497 calcoffset(t_jit_ob3d, inherit_poly)); 00498 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00499 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00500 jit_class_addattr(jit_class, attr); 00501 attr = jit_object_new(_jit_sym_jit_attr_offset, "inherit_depth", _jit_sym_long, 00502 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00503 calcoffset(t_jit_ob3d, inherit_depth)); 00504 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00505 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00506 jit_class_addattr(jit_class, attr); 00507 attr = jit_object_new(_jit_sym_jit_attr_offset, "inherit_fog", _jit_sym_long, 00508 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00509 calcoffset(t_jit_ob3d, inherit_fog)); 00510 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00511 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00512 jit_class_addattr(jit_class, attr); 00513 attr = jit_object_new(_jit_sym_jit_attr_offset, "inherit_color", _jit_sym_long, 00514 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00515 calcoffset(t_jit_ob3d, inherit_color)); 00516 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00517 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00518 jit_class_addattr(jit_class, attr); 00519 attr = jit_object_new(_jit_sym_jit_attr_offset, "inherit_texture", _jit_sym_long, 00520 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00521 calcoffset(t_jit_ob3d, inherit_texture)); 00522 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00523 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00524 jit_class_addattr(jit_class, attr); 00525 attr = jit_object_new(_jit_sym_jit_attr_offset, "inherit_material", _jit_sym_long, 00526 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00527 calcoffset(t_jit_ob3d, inherit_material)); 00528 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00529 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00530 jit_class_addattr(jit_class, attr); 00531 attr = jit_object_new(_jit_sym_jit_attr_offset, "inherit_transform", _jit_sym_long, 00532 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00533 calcoffset(t_jit_ob3d, inherit_transform)); 00534 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00535 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00536 jit_class_addattr(jit_class, attr); 00537 attr = jit_object_new(_jit_sym_jit_attr_offset, "inherit_all", _jit_sym_long, 00538 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00539 calcoffset(t_jit_ob3d, inherit_all)); 00540 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00541 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00542 jit_class_addattr(jit_class, attr); 00543 00544 if (!GET_FLAG(flags, JIT_OB3D_NO_MATRIXOUTPUT)) 00545 { 00546 // matrixoutput: draw via messages through patcher. 00547 // otherwise, draw direct to gl.render destination. 00548 attr = jit_object_new(_jit_sym_jit_attr_offset, "matrixoutput", _jit_sym_long, 00549 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00550 calcoffset(t_jit_ob3d, matrixoutput)); 00551 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00552 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00553 jit_class_addattr(jit_class, attr); 00554 } 00555 00556 if (!GET_FLAG(flags, JIT_OB3D_AUTO_ONLY)) 00557 { 00558 // auto: draw automatically when renderer swaps buffers. 00559 // otherwise, bang makes us draw. 00560 attr = jit_object_new(_jit_sym_jit_attr_offset, "automatic", _jit_sym_long, 00561 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_attr_offset_set, 00562 calcoffset(t_jit_ob3d, automatic)); 00563 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00564 object_addattr_parse(attr,"style",_jit_sym_symbol,0,"onoff"); 00565 jit_class_addattr(jit_class, attr); 00566 } 00567 00568 // name attribute 00569 attr = jit_object_new(_jit_sym_jit_attr_offset, "name", _jit_sym_symbol, 00570 attrflags, (method)jit_ob3d_attr_offset_get, (method)jit_ob3d_name_set, 00571 calcoffset(t_jit_ob3d, name)); 00572 object_addattr_parse(attr,"category",_jit_sym_symbol,0,"OB3D"); 00573 jit_class_addattr(jit_class, attr); 00574 } 00575 return x; 00576 } 00577 00578 t_jit_err jit_ob3d_set(void *x, void *v) 00579 { 00580 t_jit_ob3d *ob3d = v; 00581 long offset; 00582 static method mf=NULL; 00583 00584 if (x) 00585 { 00586 if (!mf) 00587 mf = jit_object_getmethod(NULL,NULL); 00588 00589 00590 //jit_cpost("ob3d_set entered"); 00591 ob3d->class3d = ((t_jit_class3d *)jit_object_getmethod(x, ps_JIT_CLASS3D_FINDER)); 00592 00593 //jit_cpost("ob3d->class3d: %x",ob3d->class3d); 00594 00595 if ((method)ob3d->class3d==mf) { 00596 ob3d->class3d = NULL; 00597 } else { 00598 //jit_cpost("ob3doffset: %d",ob3d->class3d->oboffset); 00599 offset = ob3d->class3d->oboffset; 00600 if (offset) 00601 { 00602 *(t_jit_ob3d **)(((char *)x) + offset) = ob3d; 00603 ob3d->jitob = x; 00604 } 00605 } 00606 } 00607 return JIT_ERR_GENERIC; 00608 } 00609 00610 void *jit_ob3d_get(void *x) 00611 { 00612 long offset; 00613 static method mf=NULL; 00614 00615 if (x) 00616 { 00617 offset = (long) jit_object_method(x,ps_ob3d_get_offset); 00618 if (offset) 00619 return *(t_jit_ob3d **)(((char *)x) + offset); 00620 } 00621 return NULL; 00622 } 00623 00624 long jit_ob3d_get_offset(void *x) 00625 { 00626 t_jit_class3d *c; 00627 static method mf=NULL; 00628 00629 if (x) 00630 { 00631 if (!mf) 00632 mf = jit_object_getmethod(NULL,NULL); 00633 c = (t_jit_class3d *)jit_object_getmethod(x, ps_JIT_CLASS3D_FINDER); 00634 if ((method)c!=mf) 00635 { 00636 return c->oboffset; 00637 } 00638 } 00639 return 0; 00640 } 00641 00642 /** 00643 * Allocates and initializes OB3D resources. 00644 * 00645 * @ingroup ob3dmod 00646 * 00647 * @param x Jitter object pointer 00648 * @param dest_name drawing destination name 00649 * 00650 * @return t_jit_ob3d pointer (opaque) 00651 * 00652 */ 00653 void *jit_ob3d_new(void *x, t_symbol * dest_name) 00654 { 00655 long i; 00656 t_jit_ob3d *ob3d; 00657 static method mf=NULL; 00658 00659 if (ob3d = jit_getbytes(sizeof(t_jit_ob3d))) 00660 { 00661 // attach to jit obj 00662 jit_ob3d_set(x, ob3d); 00663 00664 // set instance data defaults 00665 ob3d->next = 0; 00666 ob3d->max_obj = 0; 00667 ob3d->name = _jit_sym_nothing; 00668 ob3d->dest_name = _jit_sym_nothing; 00669 ob3d->dest_render_sym = _jit_sym_nothing; 00670 // ob3d->texture = _jit_sym_nothing; 00671 ob3d->enable = 1; 00672 jit_gl_set_floats(ob3d->position, 3, 0., 0., 0.); 00673 jit_gl_set_floats(ob3d->rotation, 4, 0., 0., 0., 1.); 00674 jit_gl_set_floats(ob3d->scale, 3, 1., 1., 1.); 00675 00676 jit_gl_set_floats(ob3d->color, 4, .5, .5, .5, 1.); 00677 jit_gl_set_floats(ob3d->aux_color, 4, 1., 1., 1., 1.); 00678 ob3d->blend_mode[0] = 6; 00679 ob3d->blend_mode[1] = 7; 00680 ob3d->poly_mode[0] = ob3d->poly_mode[1] = 0; 00681 ob3d->cull_face = 0; 00682 ob3d->depth_enable = 1; 00683 ob3d->point_size = 1; 00684 ob3d->line_width = 1; 00685 ob3d->antialias = 0; 00686 ob3d->blend_enable = 0; 00687 ob3d->smooth_shading = 0; 00688 ob3d->lighting_enable = 0; 00689 ob3d->two_sided = 1; 00690 ob3d->tex_map = 0; 00691 jit_gl_set_floats(ob3d->tex_plane_s, 4, 1., 0., 0., 0.); 00692 jit_gl_set_floats(ob3d->tex_plane_t, 4, 0., 1., 0., 0.); 00693 ob3d->auto_material = 1; 00694 ob3d->dest_dim[0] = ob3d->dest_dim[1] = 1; 00695 00696 ob3d->ortho = 0; 00697 ob3d->axes = 0; 00698 ob3d->automatic = 1; 00699 ob3d->matrixoutput = 0; 00700 ob3d->viewalign = 0; 00701 ob3d->depth_clear = 0; 00702 ob3d->transform_reset = 0; 00703 00704 00705 ob3d->last = 0; 00706 ob3d->next = 0; 00707 ob3d->drawout = 0; 00708 ob3d->renderer = 0; 00709 ob3d->p_chunk = 0; 00710 00711 // fog 00712 ob3d->fog = 0; 00713 jit_gl_set_floats(ob3d->fog_params, 7, 0.5, 0.5, 0.5, 0., 1., 1., 100.); // RGBA, density, start, end. 00714 00715 // camera stuff 00716 jit_gl_set_floats(ob3d->camera, 3, 0., 0., 2.); 00717 jit_gl_set_floats(ob3d->lookat, 3, 0., 0., 0.); 00718 jit_gl_set_floats(ob3d->up, 3, 0., 1., 0.); 00719 ob3d->lens_angle = 45.0; 00720 ob3d->near_clip = 0.1; 00721 ob3d->far_clip = 100.0; 00722 00723 // lighting / mat'ls 00724 jit_gl_set_floats(ob3d->light_global_ambient, 4, 0.2, 0.2, 0.2, 1.); 00725 jit_gl_set_floats(ob3d->light_ambient, 4, 0., 0., 0., 1.); 00726 jit_gl_set_floats(ob3d->light_diffuse, 4, 1., 1., 1., 1.); 00727 jit_gl_set_floats(ob3d->light_specular, 4, 1., 1., 1., 1.); 00728 jit_gl_set_floats(ob3d->light_position, 4, 1., 1., 1., 0.); 00729 ob3d->shininess = 10; 00730 jit_gl_set_floats(ob3d->mat_ambient, 4, .5, .5, .5, 1.); 00731 jit_gl_set_floats(ob3d->mat_diffuse, 4, .5, .5, .5, 1.); 00732 jit_gl_set_floats(ob3d->mat_specular, 4, .5, .5, .5, 1.); 00733 jit_gl_set_floats(ob3d->mat_emission, 4, 0., 0., 0., 1.); 00734 00735 // inheritance 00736 ob3d->inherit_poly = 0; 00737 ob3d->inherit_depth = 0; 00738 ob3d->inherit_fog = 0; 00739 ob3d->inherit_color = 0; 00740 ob3d->inherit_texture = 0; 00741 ob3d->inherit_material = 0; 00742 ob3d->inherit_transform = 0; 00743 ob3d->inherit_all = 0; 00744 00745 ob3d->dirty = 0; 00746 00747 if (dest_name != _jit_sym_nothing) 00748 { 00749 int ac=1; 00750 Atom av; 00751 // post ("debug ob3d: initial dest: %s", dest_name->s_name); 00752 jit_atom_setsym(&av, dest_name); 00753 jit_object_method(ob3d->jitob, ps_drawto, ac, &av); 00754 } 00755 00756 if (!mf) 00757 mf = jit_object_getmethod(NULL,NULL); 00758 // is a ui object? 00759 ob3d->ui = jit_object_getmethod(x,ps_ob3d_ui)!=mf; 00760 ob3d->shader = _jit_sym_nothing; 00761 00762 ob3d->maxtextureunits = -1; 00763 for(i = 0; i < JIT_GL_MAX_TEXTUREUNITS; i++) 00764 { 00765 ob3d->texture[i] = _jit_sym_nothing; 00766 ob3d->capture[i] = _jit_sym_nothing; 00767 } 00768 ob3d->texturecount = 0; 00769 ob3d->capturecount = 0; 00770 00771 ob3d->layer = 0; 00772 } 00773 return x; 00774 } 00775 00776 /** 00777 * Disposes OB3D resources. 00778 * 00779 * @ingroup ob3dmod 00780 * 00781 * @param jit_ob Jitter object pointer 00782 * 00783 */ 00784 void jit_ob3d_free(void *jit_ob) 00785 { 00786 t_jit_ob3d *ob3d; 00787 if (jit_ob) 00788 { 00789 if (ob3d = jit_ob3d_get(jit_ob)) 00790 { 00791 if (ob3d->dest_render_sym != _jit_sym_nothing) 00792 { 00793 ob3d_leave_client_list(ob3d, (t_jit_ob3d_client_list **) &(ob3d->dest_render_sym->s_thing)); 00794 } 00795 00796 jit_freebytes(ob3d, sizeof(t_jit_ob3d)); 00797 } 00798 } 00799 } 00800 00801 /** 00802 * Sets the current Open GL context to the context referenced by the OB3D drawto attribute. 00803 * 00804 * @warning Not recommended for use within the draw method, as it can have adverse effects 00805 * when rendering to alternate contexts as is the case when capturing to a texture. 00806 * 00807 * @ingroup ob3dmod 00808 * 00809 * @param jit_ob Jitter object pointer 00810 * 00811 * @return t_jit_err error code 00812 * 00813 */ 00814 t_jit_err jit_ob3d_set_context(void *jit_ob) 00815 { 00816 t_jit_object *render; 00817 00818 if (render=jit_object_method(jit_ob,ps_get_render_ptr)) { 00819 return (t_jit_err) jit_object_method(render,ps_setup); 00820 } else { 00821 return JIT_ERR_GENERIC; 00822 } 00823 } 00824 00825 #pragma mark - 00826 00827 /****************************************************************************/ 00828 // public ob3d routines 00829 00830 /** 00831 * Retrieves parent Jitter object from opaque t_jit_ob3d struct. 00832 * 00833 * @ingroup ob3dmod 00834 * 00835 * @param v t_jit_ob3d pointer 00836 * 00837 * @return parent Jitter object pointer 00838 * 00839 */ 00840 void * ob3d_jitob_get(void *v) 00841 { 00842 t_jit_ob3d *ob3d = (t_jit_ob3d *)v; 00843 if (ob3d) 00844 return ob3d->jitob; 00845 else 00846 return 0; 00847 } 00848 00849 void * ob3d_next_get(void *v) 00850 { 00851 t_jit_ob3d *ob3d = (t_jit_ob3d *)v; 00852 if (ob3d) 00853 return ob3d->next; 00854 else 00855 return 0; 00856 } 00857 00858 /** 00859 * Retrieves automatic flag from opaque t_jit_ob3d struct. 00860 * 00861 * @ingroup ob3dmod 00862 * 00863 * @param v t_jit_ob3d pointer 00864 * 00865 * @return automatic flag 00866 * 00867 */ 00868 long ob3d_auto_get(void *v) 00869 { 00870 t_jit_ob3d *ob3d = (t_jit_ob3d *)v; 00871 if (ob3d) 00872 return ob3d->automatic; 00873 else 00874 return 0; 00875 } 00876 00877 /** 00878 * Retrieves enable flag from opaque t_jit_ob3d struct. 00879 * 00880 * @ingroup ob3dmod 00881 * 00882 * @param v t_jit_ob3d pointer 00883 * 00884 * @return enable flag 00885 * 00886 */ 00887 long ob3d_enable_get(void *v) 00888 { 00889 t_jit_ob3d *ob3d = (t_jit_ob3d *)v; 00890 if (ob3d) 00891 return ob3d->enable; 00892 else 00893 return 0; 00894 } 00895 00896 /** 00897 * Retrieves UI flag from opaque t_jit_ob3d struct. 00898 * 00899 * @ingroup ob3dmod 00900 * 00901 * @param v t_jit_ob3d pointer 00902 * 00903 * @return UI flag 00904 * 00905 */ 00906 long ob3d_ui_get(void *v) 00907 { 00908 t_jit_ob3d *ob3d = (t_jit_ob3d *)v; 00909 if (ob3d) 00910 return ob3d->ui; 00911 else 00912 return 0; 00913 } 00914 00915 /** 00916 * Retrieves matrix outlet from opaque t_jit_ob3d struct. 00917 * 00918 * @ingroup ob3dmod 00919 * 00920 * @param v t_jit_ob3d pointer 00921 * 00922 * @return matrix outlet 00923 * 00924 */ 00925 void * ob3d_outlet_get(void *v) 00926 { 00927 t_jit_ob3d *ob3d = (t_jit_ob3d *)v; 00928 if (ob3d) 00929 return ob3d->drawout; 00930 else 00931 return 0; 00932 } 00933 00934 /** 00935 * Retrieves dirty flag from opaque t_jit_ob3d struct. 00936 * 00937 * @ingroup ob3dmod 00938 * 00939 * @param v t_jit_ob3d pointer 00940 * 00941 * @return dirty flag 00942 * 00943 */ 00944 long ob3d_dirty_get(void *v) 00945 { 00946 t_jit_ob3d *ob3d = (t_jit_ob3d *)v; 00947 if (ob3d) 00948 return ob3d->dirty; 00949 else 00950 return 0; 00951 } 00952 00953 /** 00954 * Sets dirty flag from opaque t_jit_ob3d struct. 00955 * 00956 * @ingroup ob3dmod 00957 * 00958 * @param v t_jit_ob3d pointer 00959 * @param c dirty flag state 00960 * 00961 */ 00962 void ob3d_dirty_set(void *v, long c) 00963 { 00964 t_jit_ob3d *ob3d = (t_jit_ob3d *)v; 00965 if (ob3d) 00966 ob3d->dirty = c; 00967 } 00968 00969 /** 00970 * Sets destination dimensions in opaque t_jit_ob3d struct. 00971 * 00972 * @ingroup ob3dmod 00973 * 00974 * @param v t_jit_ob3d pointer 00975 * @param width destination dimensions width 00976 * @param height destination dimensions height 00977 * 00978 */ 00979 void ob3d_dest_dim_set(void *v, long width, long height) 00980 { 00981 t_jit_ob3d *ob3d = (t_jit_ob3d *)v; 00982 if (ob3d) { 00983 ob3d->dest_dim[0] = width; 00984 ob3d->dest_dim[1] = height; 00985 } 00986 } 00987 00988 /** 00989 * Gets destination dimensions from opaque t_jit_ob3d struct. 00990 * 00991 * @ingroup ob3dmod 00992 * 00993 * @param v t_jit_ob3d pointer 00994 * @param width destination dimensions width pointer 00995 * @param height destination dimensions height pointer 00996 * 00997 */ 00998 void ob3d_dest_dim_get(void *v, long *width, long *height) 00999 { 01000 t_jit_ob3d *ob3d = (t_jit_ob3d *)v; 01001 if (ob3d) { 01002 if (width) 01003 *width = ob3d->dest_dim[0]; 01004 if (height) 01005 (*height) = ob3d->dest_dim[1]; 01006 } 01007 } 01008 01009 01010 /** 01011 * Sets renderer pointer in opaque t_jit_ob3d struct. 01012 * 01013 * @ingroup ob3dmod 01014 * 01015 * @param v t_jit_ob3d pointer 01016 * @param render_ptr renderer pointer 01017 * 01018 */ 01019 void ob3d_render_ptr_set(void *v, void *render_ptr) 01020 { 01021 t_jit_ob3d *ob3d = (t_jit_ob3d *)v; 01022 if (ob3d) 01023 ob3d->renderer = render_ptr; 01024 } 01025 01026 /** 01027 * Gets renderer pointer from opaque t_jit_ob3d struct. 01028 * 01029 * @ingroup ob3dmod 01030 * 01031 * @param v t_jit_ob3d pointer 01032 * 01033 * @return renderer pointer 01034 * 01035 */ 01036 void *ob3d_render_ptr_get(void *v) 01037 { 01038 t_jit_ob3d *ob3d = (t_jit_ob3d *)v; 01039 return (ob3d) ? ob3d->renderer : NULL; 01040 } 01041 01042 01043 #pragma mark - 01044 01045 /****************************************************************************/ 01046 // max_ob3d routines 01047 01048 /** 01049 * Adds default methods and OB3D Max wrapper class. 01050 * 01051 * @ingroup ob3dmod 01052 * 01053 */ 01054 void max_ob3d_setup(void) 01055 { 01056 addmess((method)max_ob3d_notify, "notify", A_CANT, 0); 01057 addbang((method)max_ob3d_bang); 01058 } 01059 01060 /** 01061 * Allocates and initializes OB3D Max wrapper related resources. 01062 * 01063 * @ingroup ob3dmod 01064 * 01065 * @param x Max wrapper object pointer 01066 * @param jit_ob Jitter object pointer 01067 * @param outlet matrix outlet pointer 01068 * 01069 */ 01070 void max_jit_ob3d_attach(void *x, t_jit_object *jit_ob, void *outlet) 01071 { 01072 t_symbol *name; 01073 t_jit_ob3d *ob3d; 01074 01075 if (ob3d = jit_ob3d_get(jit_ob)) 01076 { 01077 // if jit object has a "name" attribute, the value of which is nonzero, 01078 // use that for jit obj name. otherwise, invent one. 01079 name = jit_attr_getsym(jit_ob, _jit_sym_name); 01080 if ((name == 0) || (name == _jit_sym_nothing)) { 01081 name = jit_symbol_unique(); 01082 jit_ob = jit_object_method(jit_ob, _jit_sym_register, name); 01083 } 01084 01085 if (jit_ob) 01086 { 01087 ob3d->name=name; 01088 jit_object_attach(name,x); 01089 } 01090 01091 // cache outlet and max obj in ob3d 01092 ob3d->drawout = outlet; 01093 ob3d->max_obj = x; 01094 } 01095 } 01096 01097 /** 01098 * Disposes OB3D Max wrapper related resources. 01099 * 01100 * @ingroup ob3dmod 01101 * 01102 * @param x Max wrapper object pointer 01103 * 01104 */ 01105 void max_jit_ob3d_detach(void *x) 01106 { 01107 t_jit_object *jit_ob; 01108 t_symbol *name; 01109 01110 if (jit_ob=max_jit_obex_jitob_get(x)) { 01111 name = jit_attr_getsym(jit_ob, _jit_sym_name); 01112 jit_object_detach(name, x); 01113 } 01114 } 01115 01116 /** 01117 * Default OB3D Max wrapper assistance method. 01118 * 01119 * @ingroup ob3dmod 01120 * 01121 * @param x Max object pointer 01122 * @param b ignored 01123 * @param m inlet or outlet type 01124 * @param a index 01125 * @param s output string 01126 * 01127 * @return t_jit_err error code 01128 * 01129 */ 01130 t_jit_err max_jit_ob3d_assist(void *x, void *b, long m, long a, char *s) 01131 { 01132 if (m == 1) //input 01133 { 01134 switch(a) 01135 { 01136 case 0: 01137 sprintf(s,"messages to this 3d object"); 01138 break; 01139 default: 01140 return JIT_ERR_GENERIC; 01141 } 01142 } 01143 else //output 01144 { 01145 switch(a) 01146 { 01147 case 0: 01148 sprintf(s,"matrix output if enabled"); 01149 break; 01150 case 1: 01151 sprintf(s,"dumpout"); 01152 break; 01153 default: 01154 return JIT_ERR_GENERIC; 01155 } 01156 } 01157 01158 return JIT_ERR_NONE; 01159 } 01160 01161 01162 t_jit_err jit_ob3d_name_set(t_jit_object *jit_ob, void *attr, long argc, t_atom *argv) 01163 { 01164 t_jit_err result = JIT_ERR_NONE; 01165 t_jit_ob3d *ob3d; 01166 t_symbol *old_name, *new_name; 01167 t_jit_object *o; 01168 01169 if (jit_ob && (ob3d = jit_ob3d_get(jit_ob)) && argc && argv) 01170 { 01171 old_name = ob3d->name; 01172 new_name = jit_atom_getsym(argv); 01173 01174 if (new_name==old_name) 01175 return result; 01176 01177 01178 if (o=jit_object_findregistered(new_name)) 01179 { 01180 error("name %s already in use. ob3d does not allow multiple bindings", new_name->s_name); 01181 result = JIT_ERR_GENERIC; 01182 } 01183 else 01184 { 01185 if (ob3d->max_obj) 01186 jit_object_detach(old_name, ob3d->max_obj); 01187 jit_object_unregister(jit_ob); 01188 jit_ob = jit_object_method(jit_ob, _jit_sym_register, new_name); 01189 01190 // if registered ok under new name, attach max obj to new name. 01191 if (jit_ob) 01192 { 01193 ob3d->name = new_name; 01194 if (ob3d->max_obj) 01195 { 01196 jit_object_attach(new_name, ob3d->max_obj); 01197 max_jit_obex_jitob_set(ob3d->max_obj, jit_ob); 01198 } 01199 } 01200 else 01201 result = JIT_ERR_GENERIC; 01202 } 01203 } 01204 return result; 01205 } 01206 01207 01208 /** 01209 * Default OB3D Max wrapper bang method. 01210 * 01211 * @ingroup ob3dmod 01212 * 01213 * @param x Max object pointer 01214 * 01215 */ 01216 void max_ob3d_bang(t_max_object *x) 01217 { 01218 typedmess(x, ps_draw, 0, 0); 01219 } 01220 01221 01222 // recursively send chunk geometry to outlet. 01223 // uses Atom * sent by caller for message-building. Make sure this is big enough 01224 // for all the possible atoms we might add in one message, below. 01225 // side effect: will add matrix names to chunk if it has none. 01226 void send_chunk_to_outlet(t_jit_glchunk * p_chunk, void * outlet, Atom * av); 01227 void send_chunk_to_outlet(t_jit_glchunk * p_chunk, void * outlet, Atom * av) 01228 { 01229 int i; 01230 long OK = true; 01231 if (!outlet) return; 01232 01233 // make matrix names if needed 01234 if (p_chunk->m_vertex && (p_chunk->m_vertex_name == _jit_sym_nothing)) 01235 { 01236 p_chunk->m_vertex_name = jit_symbol_unique(); 01237 if (!(p_chunk->m_vertex = jit_object_method(p_chunk->m_vertex, _jit_sym_register, p_chunk->m_vertex_name))) OK = false; 01238 } 01239 01240 if (p_chunk->m_index && (p_chunk->m_index_name == _jit_sym_nothing)) 01241 { 01242 p_chunk->m_index_name = jit_symbol_unique(); 01243 if (!(p_chunk->m_index = jit_object_method(p_chunk->m_index, _jit_sym_register, p_chunk->m_index_name))) OK = false; 01244 } 01245 01246 // format message 01247 if (OK) 01248 { 01249 i=0; 01250 jit_atom_setsym(av+i, p_chunk->m_vertex_name); i++; 01251 01252 if (p_chunk->m_index) 01253 { 01254 jit_atom_setsym(av+i, p_chunk->m_index_name); i++; 01255 } 01256 01257 jit_atom_setsym(av+i, p_chunk->prim); i++; 01258 01259 if (GET_FLAG(p_chunk->m_flags, JIT_GL_CHUNK_IGNORE_TEXTURES)) 01260 { 01261 jit_atom_setsym(av+i, ps_ignore_textures); i++; 01262 } 01263 01264 if (GET_FLAG(p_chunk->m_flags, JIT_GL_CHUNK_IGNORE_NORMALS)) 01265 { 01266 jit_atom_setsym(av+i, ps_ignore_normals); i++; 01267 } 01268 01269 if (GET_FLAG(p_chunk->m_flags, JIT_GL_CHUNK_IGNORE_COLORS)) 01270 { 01271 jit_atom_setsym(av+i, ps_ignore_colors); i++; 01272 } 01273 01274 if (GET_FLAG(p_chunk->m_flags, JIT_GL_CHUNK_IGNORE_EDGES)) 01275 { 01276 jit_atom_setsym(av+i, ps_ignore_edges); i++; 01277 } 01278 01279 // send it out 01280 outlet_anything(outlet, _jit_sym_jit_matrix, i, av); 01281 } 01282 01283 if (p_chunk->next_chunk) 01284 send_chunk_to_outlet(p_chunk->next_chunk, outlet, av); 01285 } 01286 01287 01288 /** 01289 * Default OB3D Max wrapper notification method. 01290 * 01291 * @ingroup ob3dmod 01292 * 01293 * @param x Max object pointer 01294 * @param sender_name sender's object name 01295 * @param msg notification message 01296 * @param p_sender sender's object pointer 01297 * 01298 */ 01299 void max_ob3d_notify(t_max_object *x, t_symbol *sender_name, t_symbol *msg, void *p_sender) 01300 { 01301 Atom av[8]; 01302 01303 // handle draw_chunk message -- sent by our jit_ob3d object. 01304 // post ("2. got notify"); 01305 if (msg==ps_draw_chunk) 01306 { 01307 t_jit_ob3d *ob3d; 01308 t_jit_glchunk * p_chunk=NULL; 01309 long i=0; 01310 01311 if (!p_sender) return; 01312 if (ob3d = jit_ob3d_get(p_sender)) 01313 { 01314 // get info from jit obj 01315 jit_object_method(p_sender, ps_get_chunk, &p_chunk); 01316 01317 // send it 01318 if (p_chunk) 01319 send_chunk_to_outlet(p_chunk, ob3d->drawout, av); 01320 } 01321 } 01322 } 01323 01324 01325 #pragma mark - 01326 01327 /****************************************************************************/ 01328 // ob3d routines 01329 01330 t_jit_ob3d_client_list * ob3d_client_list_new() 01331 { 01332 t_jit_ob3d_client_list *ob3dlist; 01333 01334 ob3dlist = (t_jit_ob3d_client_list *)jit_getbytes(sizeof(t_jit_ob3d_client_list)); 01335 if (ob3dlist) { 01336 ob3dlist->list = jit_linklist_new(); 01337 systhread_mutex_new(&ob3dlist->mutex,SYSTHREAD_MUTEX_RECURSIVE); //can investigate more efficient in future 01338 ob3dlist->dirty = 0; 01339 } 01340 return ob3dlist; 01341 } 01342 01343 void ob3d_client_list_free(t_jit_ob3d_client_list *ob3dlist) 01344 { 01345 if (ob3dlist) { 01346 jit_linklist_chuck(ob3dlist->list); 01347 systhread_mutex_free(ob3dlist->mutex); 01348 jit_freebytes(ob3dlist,sizeof(t_jit_ob3d_client_list)); 01349 } 01350 } 01351 01352 void ob3d_enter_client_list(t_jit_ob3d *x, t_jit_ob3d_client_list **ob3dlist) 01353 { 01354 t_jit_ob3d *p; 01355 t_object *o; 01356 long i; 01357 01358 if(*ob3dlist == 0) 01359 { 01360 *ob3dlist = ob3d_client_list_new(); 01361 } 01362 01363 systhread_mutex_lock((*ob3dlist)->mutex); 01364 01365 o = ob3d_jitob_get(x); 01366 if (jit_linklist_objptr2index((*ob3dlist)->list,o)==-1) { 01367 i = jit_linklist_append((*ob3dlist)->list,o); 01368 (*ob3dlist)->dirty = 1; 01369 //post("entering client list: i=%d, classname:%s, object:%x",i,object_classname(o)->s_name,o); 01370 } 01371 systhread_mutex_unlock((*ob3dlist)->mutex); 01372 } 01373 01374 void ob3d_leave_client_list(t_jit_ob3d *x, t_jit_ob3d_client_list **ob3dlist) 01375 { 01376 t_jit_ob3d *p; 01377 long i; 01378 t_object *o; 01379 01380 if(*ob3dlist == 0) 01381 { 01382 error("jit_ob3d_leave_client_list: client remove from empty list!"); 01383 return; 01384 } 01385 01386 o = ob3d_jitob_get(x); 01387 01388 systhread_mutex_lock((*ob3dlist)->mutex); 01389 if ((i=jit_linklist_objptr2index((*ob3dlist)->list,o))>-1) { 01390 jit_linklist_chuckindex((*ob3dlist)->list,i); 01391 //post("leaving client list: i=%d, classname:%s, object:%x",i,object_classname(o)->s_name,o); 01392 } 01393 (*ob3dlist)->dirty = 1; 01394 systhread_mutex_unlock((*ob3dlist)->mutex); 01395 01396 if (jit_linklist_getsize((*ob3dlist)->list) == 0) 01397 { 01398 t_jit_ob3d_client_list *killme=*ob3dlist; 01399 01400 *ob3dlist = 0; 01401 ob3d_client_list_free(killme); 01402 } 01403 } 01404 01405 extern t_symbol *_jit_glreadback; 01406 01407 t_jit_err ob3d_draw_begin(void *v, long setup) 01408 { 01409 long i, flags, do_setup=0; 01410 t_jit_ob3d * ob3d = (t_jit_ob3d *)v; 01411 t_symbol *s[1]; 01412 01413 // get class ob3d flags. 01414 flags = ob3d->class3d->flags; 01415 01416 //the setup part of this method performed by jit.gl.render must go before 01417 //a readback mechanism is bound 01418 if (!ob3d->renderer) { 01419 //post("warning attempting to draw with invalid renderer pointer"); 01420 return JIT_ERR_GENERIC; 01421 } 01422 01423 //need to override the setup argument if capturing 01424 //because pbuffers need the render setup 01425 //ideally this would not happen with FBOs 01426 if(ob3d->capture[0]) { 01427 void *tex; 01428 01429 tex = jit_object_findregistered(ob3d->capture[0]); 01430 01431 if(tex) { 01432 if(jit_object_classname(tex) == ps_jit_gl_texture) { 01433 if(_jit_glreadback != ps_jit_gl_readback_fbo) 01434 setup = 1; 01435 } 01436 } 01437 } 01438 01439 do_setup = setup && jit_attr_getsym_array(ob3d->renderer, ps_capture, 1, s) <= 0; 01440 if(do_setup) 01441 if (JIT_ERR_NONE != jit_object_method(ob3d->renderer, ps_setup)) return JIT_ERR_GENERIC; 01442 01443 for(i = 0; i < ob3d->capturecount; i++) 01444 { 01445 jit_gl_dobegincapture(ob3d,ob3d->capture[i],i); 01446 jit_gl_report_error("ob3d_draw_begin capture"); 01447 } 01448 01449 // jit.gl.render's preabmle must go after the readback mechanism is bound 01450 // because pbuffer's have their own context and we need to transfer state 01451 // for FBO's, it doesn't matter 01452 01453 // if ob3d's renderer is not set, make it current if not capturing 01454 // as the viewport gets reset. 01455 { 01456 void *rend_ob3d; 01457 01458 if (do_setup) { 01459 jit_gl_report_error("ob3d_draw_begin setup"); 01460 rend_ob3d = jit_object_method(ob3d->renderer, ps_get_ob3d); 01461 if (rend_ob3d) 01462 ob3d_draw_preamble(rend_ob3d); 01463 } 01464 } 01465 01466 if (!jit_gl_get_context()) 01467 { 01468 error("ob3d_draw_begin: no context"); 01469 return JIT_ERR_GENERIC; 01470 } 01471 01472 glNormal3f(0., 1., 0.); // just prevent old normals from "leaking through" 01473 01474 if (_jit_glattribpush) { 01475 glPushAttrib(GL_ALL_ATTRIB_BITS); 01476 jit_gl_report_error("ob3d_draw_begin push attr"); 01477 } 01478 01479 if (!ob3d->inherit_transform) 01480 { 01481 glMatrixMode(GL_MODELVIEW); 01482 glPushMatrix(); 01483 glMatrixMode(GL_PROJECTION); 01484 glPushMatrix(); 01485 jit_gl_report_error("ob3d_draw_begin pushmatrix"); 01486 } 01487 01488 /* 01489 This was initially added during the final hours of v1.5 development 01490 to get around artifacts of binding a texture which had been created 01491 in a different context than it was being bound/used. 01492 01493 This no longer seems to be needed. Remove if no artifacts showup. 01494 01495 if (ob3d->capturecount) 01496 { 01497 // multi texturing support via gl.texture 01498 for(i = 0; i < ob3d->texturecount; i++) 01499 { 01500 jit_gl_dobindtexture(ob3d,ob3d->texture[i],i); 01501 jit_gl_dounbindtexture(ob3d,ob3d->texture[i],i); 01502 jit_gl_report_error("ob3d_draw_preamble render multitexture"); 01503 } 01504 } 01505 */ 01506 01507 01508 /*{ 01509 t_jit_ob3d *rend_ob3d; 01510 rend_ob3d = jit_object_method(ob3d->renderer, ps_get_ob3d); 01511 glLightfv(GL_LIGHT0, GL_POSITION, rend_ob3d->light_position); 01512 }*/ 01513 01514 // render to texture support via gl.texture 01515 01516 ob3d_draw_preamble(ob3d); 01517 jit_gl_report_error("ob3d_draw_begin preamble"); 01518 01519 return JIT_ERR_NONE; 01520 } 01521 01522 long ob3d_draw_end(void *v, long setup) 01523 { 01524 long flags; 01525 int i; 01526 t_jit_ob3d * ob3d = (t_jit_ob3d *)v; 01527 t_jit_gl_context ctx=NULL; 01528 01529 // get class ob3d flags. 01530 flags = ob3d->class3d->flags; 01531 01532 if (!(ctx=jit_gl_get_context())) { 01533 error("ob3d_draw_end: no context"); 01534 return JIT_ERR_GENERIC; 01535 } 01536 01537 // multi texturing support via gl.texture 01538 for(i = 0; i < ob3d->texturecount; i++) 01539 { 01540 jit_gl_dounbindtexture(ob3d, ob3d->texture[i], i); 01541 jit_gl_report_error("ob3d_draw_end texture"); 01542 } 01543 // force texture 0 as active 01544 if (ctx->support->multitexture) 01545 glActiveTextureARB(GL_TEXTURE0_ARB); 01546 01547 if (ob3d->shader!=_jit_sym_nothing) 01548 { 01549 t_atom a; 01550 t_jit_object *o = NULL; 01551 01552 // find registered gl.shader object with given name 01553 o = jit_object_findregistered(ob3d->shader); 01554 if (o && jit_object_classname(o) == ps_jit_gl_shader) 01555 { 01556 // pass ob3d to shader 01557 jit_atom_setobj(&a, ob3d->jitob); 01558 jit_object_method(o, ps_unbind, ps_unbind, 1, &a); 01559 } 01560 } 01561 01562 if (ob3d->tex_map) 01563 { 01564 glDisable(GL_TEXTURE_GEN_S); 01565 glDisable(GL_TEXTURE_GEN_T); 01566 } 01567 01568 01569 if (ob3d->axes) 01570 { 01571 // RGB axes utility 01572 glDisable(GL_LIGHTING); 01573 glDisable(GL_TEXTURE_2D); 01574 // x 01575 glBegin(GL_LINES); 01576 glColor3f(4., 0., 0.); 01577 glVertex3f(0., 0., 0.); 01578 glVertex3f(4., 0., 0.); 01579 glEnd(); 01580 for (i=1;i<5;i++) 01581 { 01582 glBegin(GL_LINE_LOOP); 01583 glVertex3f(i*1., 0.01, 0.01); 01584 glVertex3f(i*1., 0.01, -0.01); 01585 glVertex3f(i*1., -0.01, -0.01); 01586 glVertex3f(i*1., -0.01, 0.01); 01587 glEnd(); 01588 } 01589 // y 01590 glBegin(GL_LINES); 01591 glColor3f(0., 4., 0.); 01592 glVertex3f(0., 0., 0.); 01593 glVertex3f(0., 4., 0.); 01594 glEnd(); 01595 for (i=1;i<5;i++) 01596 { 01597 glBegin(GL_LINE_LOOP); 01598 glVertex3f(0.01, i*1., 0.01); 01599 glVertex3f(0.01, i*1., -0.01); 01600 glVertex3f(-0.01, i*1., -0.01); 01601 glVertex3f(-0.01, i*1., 0.01); 01602 glEnd(); 01603 } 01604 // z 01605 glBegin(GL_LINES); 01606 glColor3f(0., 0., 4.); 01607 glVertex3f(0., 0., 0.); 01608 glVertex3f(0., 0., 4.); 01609 glEnd(); 01610 for (i=1;i<5;i++) 01611 { 01612 glBegin(GL_LINE_LOOP); 01613 glVertex3f(0.01, 0.01, i*1.); 01614 glVertex3f(0.01, -0.01, i*1.); 01615 glVertex3f(-0.01, -0.01, i*1.); 01616 glVertex3f(-0.01, 0.01, i*1.); 01617 glEnd(); 01618 } 01619 jit_gl_report_error("ob3d_draw_end axes"); 01620 } 01621 01622 if (!ob3d->inherit_transform) 01623 { 01624 glMatrixMode(GL_PROJECTION); 01625 glPopMatrix(); 01626 glMatrixMode(GL_MODELVIEW); 01627 glPopMatrix(); 01628 jit_gl_report_error("ob3d_draw_end popmatrix"); 01629 } 01630 01631 // render to texture support via gl.texture 01632 for(i = 0; i < ob3d->capturecount; i++) 01633 { 01634 jit_gl_doendcapture(ob3d,ob3d->capture[i],i); 01635 jit_gl_report_error("ob3d_draw_end capture"); 01636 } 01637 01638 if (_jit_glattribpush) { 01639 glPopAttrib(); 01640 jit_gl_report_error("ob3d_draw_end popattrib"); 01641 } 01642 01643 return JIT_ERR_NONE; 01644 } 01645 01646 // set up OpenGL machine with ob3d instance info 01647 long ob3d_draw_preamble(void *v) 01648 { 01649 long i; 01650 long flags; 01651 void * r; 01652 GLdouble aspect; 01653 float mat[16]; 01654 t_jit_ob3d * ob3d = (t_jit_ob3d *)v; 01655 float angle; 01656 01657 if (!ob3d) return JIT_ERR_GENERIC; 01658 01659 // get class ob3d flags. 01660 flags = ob3d->class3d->flags; 01661 01662 if (ob3d->inherit_all) return JIT_ERR_NONE; 01663 01664 jit_gl_report_error("ob3d_draw_preamble initial"); 01665 01666 if (!ob3d->inherit_poly) 01667 { 01668 if (!GET_FLAG(flags, JIT_OB3D_NO_POLY_VARS)) 01669 { 01670 // poly mode 01671 switch (ob3d->poly_mode[0]) { 01672 case 2: glPolygonMode(GL_FRONT, GL_POINT); break; 01673 case 1: glPolygonMode(GL_FRONT, GL_LINE); break; 01674 default: glPolygonMode(GL_FRONT, GL_FILL); break; 01675 } 01676 switch (ob3d->poly_mode[1]) { 01677 case 2: glPolygonMode(GL_BACK, GL_POINT); break; 01678 case 1: glPolygonMode(GL_BACK, GL_LINE); break; 01679 default: glPolygonMode(GL_BACK, GL_FILL); break; 01680 } 01681 jit_gl_report_error("ob3d_draw_preamble poly_mode"); 01682 01683 // cull faces 01684 if (ob3d->cull_face) 01685 { 01686 glEnable(GL_CULL_FACE); 01687 glCullFace((ob3d->cull_face == 1) ? GL_BACK : GL_FRONT); 01688 } 01689 else 01690 { 01691 glDisable(GL_CULL_FACE); 01692 } 01693 jit_gl_report_error("ob3d_draw_preamble cull_face"); 01694 01695 // points and lines 01696 glPointSize(ob3d->point_size); 01697 glLineWidth(ob3d->line_width); 01698 jit_gl_report_error("ob3d_draw_preamble point+line"); 01699 } 01700 01701 01702 if (!GET_FLAG(flags, JIT_OB3D_NO_ANTIALIAS)) 01703 { 01704 // antialiasing 01705 if (ob3d->antialias) 01706 { 01707 glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); 01708 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); 01709 glEnable(GL_POINT_SMOOTH); 01710 glEnable(GL_LINE_SMOOTH); 01711 } 01712 else 01713 { 01714 glDisable(GL_POINT_SMOOTH); 01715 glDisable(GL_LINE_SMOOTH); 01716 } 01717 jit_gl_report_error("ob3d_draw_preamble antialias"); 01718 } 01719 } 01720 01721 if (!ob3d->inherit_depth) 01722 { 01723 if (!GET_FLAG(flags, JIT_OB3D_NO_DEPTH)) 01724 { 01725 // depth 01726 if (ob3d->depth_enable) 01727 { 01728 glEnable(GL_DEPTH_TEST); 01729 } 01730 else 01731 { 01732 glDisable(GL_DEPTH_TEST); 01733 } 01734 jit_gl_report_error("ob3d_draw_preamble depth"); 01735 if (ob3d->depth_clear) 01736 { 01737 glClear(GL_DEPTH_BUFFER_BIT); 01738 jit_gl_report_error("ob3d_draw_preamble depth_clear"); 01739 } 01740 } 01741 } 01742 01743 if (!ob3d->inherit_fog) 01744 { 01745 if (!GET_FLAG(flags, JIT_OB3D_NO_FOG)) 01746 { 01747 // fog 01748 if (ob3d->fog) 01749 { 01750 glEnable(GL_FOG); 01751 glHint(GL_FOG_HINT, GL_NICEST); // without GL_NICEST, distance settings have no effect on Rage128 01752 glFogi(GL_FOG_MODE, GL_LINEAR); 01753 glFogfv(GL_FOG_COLOR, ob3d->fog_params); 01754 glFogf(GL_FOG_DENSITY, ob3d->fog_params[4]); // but density has no effect in GL_NICEST 01755 glFogf(GL_FOG_START, ob3d->fog_params[5]); 01756 glFogf(GL_FOG_END, ob3d->fog_params[6]); 01757 } 01758 else 01759 { 01760 glDisable(GL_FOG); 01761 } 01762 jit_gl_report_error("ob3d_draw_preamble fog"); 01763 } 01764 } 01765 01766 if (!ob3d->inherit_color) 01767 { 01768 if (!GET_FLAG(flags, JIT_OB3D_NO_COLOR)) 01769 { 01770 // default draw color, alpha controls texture blending. 01771 glColor4fv(ob3d->color); 01772 01773 // shade model 01774 if (ob3d->smooth_shading) 01775 { 01776 glShadeModel(GL_SMOOTH); 01777 } 01778 else 01779 { 01780 glShadeModel(GL_FLAT); 01781 } 01782 jit_gl_report_error("ob3d_draw_preamble smooth shading"); 01783 } 01784 01785 if (!GET_FLAG(flags, JIT_OB3D_NO_BLEND)) 01786 { 01787 // blend 01788 if (ob3d->blend_enable) 01789 { 01790 int b0, b1; 01791 b0 = jit_gl_get_blend_mode(ob3d->blend_mode[0]); 01792 b1 = jit_gl_get_blend_mode(MIN(ob3d->blend_mode[1],9)); //do not support 10=src_alpha_saturate 01793 glEnable(GL_BLEND); 01794 glBlendFunc(b0, b1); 01795 } 01796 else 01797 { 01798 glDisable(GL_BLEND); 01799 } 01800 jit_gl_report_error("ob3d_draw_preamble blend"); 01801 } 01802 } 01803 01804 if (!ob3d->inherit_texture) 01805 { 01806 if (!GET_FLAG(flags, JIT_OB3D_NO_TEXTURE)) 01807 { 01808 // multi texturing support via gl.texture 01809 for(i = 0; i < ob3d->texturecount; i++) 01810 { 01811 jit_gl_dobindtexture(ob3d,ob3d->texture[i],i); 01812 jit_gl_report_error("ob3d_draw_preamble render multitexture"); 01813 } 01814 01815 // texture mapping modes 01816 switch (ob3d->tex_map) 01817 { 01818 case 1: 01819 glEnable(GL_TEXTURE_GEN_S); 01820 glEnable(GL_TEXTURE_GEN_T); 01821 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); 01822 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); 01823 glTexGenfv(GL_S, GL_OBJECT_PLANE, ob3d->tex_plane_s); 01824 glTexGenfv(GL_T, GL_OBJECT_PLANE, ob3d->tex_plane_t); 01825 break; 01826 case 2: 01827 glEnable(GL_TEXTURE_GEN_S); 01828 glEnable(GL_TEXTURE_GEN_T); 01829 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); 01830 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); 01831 break; 01832 case 3: 01833 glEnable(GL_TEXTURE_GEN_S); 01834 glEnable(GL_TEXTURE_GEN_T); 01835 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); 01836 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); 01837 glTexGenfv(GL_S, GL_EYE_PLANE, ob3d->tex_plane_s); 01838 glTexGenfv(GL_T, GL_EYE_PLANE, ob3d->tex_plane_t); 01839 break; 01840 default: 01841 //glDisable(GL_TEXTURE_GEN_S); 01842 //glDisable(GL_TEXTURE_GEN_T); 01843 break; 01844 } 01845 01846 jit_gl_report_error("ob3d_draw_preamble texture mode"); 01847 01848 } 01849 } 01850 01851 if (!ob3d->inherit_material) 01852 { 01853 if (!GET_FLAG(flags, JIT_OB3D_NO_LIGHTING_MATERIAL)) 01854 { 01855 if (GET_FLAG(flags, JIT_OB3D_HAS_LIGHTS)) // TODO: add list of lights to renderer 01856 { 01857 glLightfv(GL_LIGHT0, GL_AMBIENT, ob3d->light_ambient); 01858 glLightfv(GL_LIGHT0, GL_DIFFUSE, ob3d->light_diffuse); 01859 glLightfv(GL_LIGHT0, GL_SPECULAR, ob3d->light_specular); 01860 glLightfv(GL_LIGHT0, GL_POSITION, ob3d->light_position); 01861 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ob3d->light_global_ambient); 01862 } 01863 01864 if (ob3d->lighting_enable) 01865 { 01866 if (ob3d->two_sided) // default auto mode: set diffuse color 01867 { 01868 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); // convenient but slow 01869 } 01870 else 01871 { 01872 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); 01873 } 01874 glEnable(GL_LIGHTING); 01875 glEnable(GL_LIGHT0); 01876 glEnable(GL_NORMALIZE); // also convenient but slow 01877 if (ob3d->auto_material) // default auto mode: set diffuse color 01878 { 01879 float mv[4] = {0.f,0.f,0.f,1.f}; 01880 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, ob3d->color); 01881 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ob3d->color); 01882 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mv); 01883 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mv); 01884 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.); 01885 } 01886 else // complete material specification 01887 { 01888 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ob3d->mat_ambient); 01889 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, ob3d->mat_diffuse); 01890 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, ob3d->mat_specular); 01891 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, ob3d->mat_emission); 01892 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, ob3d->shininess); 01893 } 01894 } 01895 else 01896 { 01897 glDisable(GL_LIGHTING); 01898 glDisable(GL_LIGHT0); 01899 glDisable(GL_NORMALIZE); 01900 } 01901 jit_gl_report_error("ob3d_draw_preamble render lights"); 01902 } else { 01903 glDisable(GL_LIGHTING); 01904 glDisable(GL_LIGHT0); 01905 glDisable(GL_NORMALIZE); 01906 } 01907 } 01908 01909 // transformation 01910 if (!ob3d->inherit_transform) 01911 { 01912 aspect = (GLdouble)ob3d->dest_dim[0] / (GLdouble)ob3d->dest_dim[1]; 01913 01914 if (GET_FLAG(flags, JIT_OB3D_HAS_CAMERA)) 01915 { 01916 glMatrixMode(GL_PROJECTION); 01917 glLoadIdentity(); 01918 switch (ob3d->ortho) 01919 { 01920 case 2: 01921 glOrtho(-aspect, aspect, -1.0, 1.0, ob3d->near_clip, ob3d->far_clip); 01922 break; 01923 case 0: 01924 gluPerspective(ob3d->lens_angle, aspect, ob3d->near_clip, ob3d->far_clip); 01925 break; 01926 default: 01927 orthoView(ob3d->lens_angle, aspect, ob3d->near_clip, ob3d->far_clip); 01928 } 01929 01930 glMatrixMode(GL_MODELVIEW); 01931 glLoadIdentity(); 01932 gluLookAt(ob3d->camera[0], ob3d->camera[1], ob3d->camera[2], 01933 ob3d->lookat[0], ob3d->lookat[1], ob3d->lookat[2], 01934 ob3d->up[0], ob3d->up[1], ob3d->up[2]); 01935 jit_gl_report_error("ob3d_draw_preamble camera"); 01936 } 01937 01938 glMatrixMode(GL_MODELVIEW); 01939 01940 if(ob3d->viewalign) 01941 { 01942 // perform screen aligned transformation 01943 glTranslatef(ob3d->position[0], ob3d->position[1], ob3d->position[2]); 01944 glGetFloatv(GL_MODELVIEW_MATRIX, mat); 01945 jit_gl_build_rotation_matrix(jit_math_atan2(mat[8], mat[10]) * JIT_MATH_F32_RADTODEG, 0, 1, 0, mat); 01946 glMultMatrixf(mat); 01947 glScalef(ob3d->scale[0], ob3d->scale[1], ob3d->scale[2]); 01948 } 01949 else 01950 { 01951 if (ob3d->transform_reset) { 01952 float near_clip=-100.; 01953 float far_clip=100.; 01954 float lens_angle=45.; 01955 // later update camera info? 01956 01957 glMatrixMode(GL_PROJECTION); 01958 glLoadIdentity(); 01959 switch (ob3d->transform_reset) 01960 { 01961 case 1: 01962 glOrtho(-aspect, aspect, -1.0, 1.0, near_clip, far_clip); 01963 break; 01964 case 2: 01965 glOrtho(-1.0, 1.0, -1.0, 1.0, near_clip, far_clip); 01966 break; 01967 case 3: 01968 gluPerspective(lens_angle, aspect, 0.001/*near_clip*/, far_clip); 01969 break; 01970 case 4: 01971 gluPerspective(lens_angle, 1.0, 0.001/*near_clip*/, far_clip); 01972 break; 01973 } 01974 glMatrixMode(GL_MODELVIEW); 01975 glLoadIdentity(); 01976 jit_gl_report_error("ob3d_draw_preamble transform_reset"); 01977 } 01978 01979 // perform standard transformation 01980 glTranslatef(ob3d->position[0], ob3d->position[1], ob3d->position[2]); 01981 glRotatef(ob3d->rotation[0], ob3d->rotation[1], ob3d->rotation[2], ob3d->rotation[3]); 01982 glScalef(ob3d->scale[0], ob3d->scale[1], ob3d->scale[2]); 01983 } 01984 01985 jit_gl_report_error("ob3d_draw_preamble transform"); 01986 } 01987 01988 if (ob3d->shader!=_jit_sym_nothing) 01989 { 01990 t_atom a; 01991 t_jit_object *o = NULL; 01992 01993 // find registered gl.shader object with given name 01994 o = jit_object_findregistered(ob3d->shader); 01995 if (o && jit_object_classname(o) == ps_jit_gl_shader) 01996 { 01997 // pass ob3d to shader 01998 jit_atom_setobj(&a, ob3d->jitob); 01999 jit_object_method(o, ps_bind, ps_bind, 1, &a); 02000 } 02001 jit_gl_report_error("ob3d_draw_preamble shader"); 02002 } 02003 02004 return JIT_ERR_NONE; 02005 } 02006 02007 void jit_gl_build_rotation_matrix(float theta, float x, float y, float z, float m[16]) 02008 { 02009 float a = theta * JIT_MATH_F32_DEGTORAD; 02010 float d = x*x + y*y + z*z; 02011 float ct = jit_math_cos(a); 02012 float st = jit_math_sin(a); 02013 02014 // normalize 02015 if (d > 0) 02016 { 02017 d = 1/d; 02018 x *= d; 02019 y *= d; 02020 z *= d; 02021 } 02022 02023 m[ 0] = 1; m[ 1] = 0; m[ 2] = 0; m[ 3] = 0; 02024 m[ 4] = 0; m[ 5] = 1; m[ 6] = 0; m[ 7] = 0; 02025 m[ 8] = 0; m[ 9] = 0; m[10] = 1; m[11] = 0; 02026 m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1; 02027 02028 /* R = uu' + cos(theta)*(I-uu') + sin(theta)*S 02029 * 02030 * S = 0 -z y u' = (x, y, z) 02031 * z 0 -x 02032 * -y x 0 02033 */ 02034 02035 m[0] = x*x + ct*(1-x*x) + st*0; 02036 m[4] = x*y + ct*(0-x*y) + st*-z; 02037 m[8] = x*z + ct*(0-x*z) + st*y; 02038 02039 m[1] = y*x + ct*(0-y*x) + st*z; 02040 m[5] = y*y + ct*(1-y*y) + st*0; 02041 m[9] = y*z + ct*(0-y*z) + st*-x; 02042 02043 m[2] = z*x + ct*(0-z*x) + st*-y; 02044 m[6] = z*y + ct*(0-z*y) + st*x; 02045 m[10]= z*z + ct*(1-z*z) + st*0; 02046 } 02047 02048 // like gluPerspective but orthographic, fovy at d=2.0 is size of viewing volume. 02049 void orthoView(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) 02050 { 02051 GLdouble xmin, xmax, ymin, ymax; 02052 02053 ymax = 2.0 * tan(fovy * PI / 360.0); 02054 ymin = -ymax; 02055 xmin = ymin * aspect; 02056 xmax = ymax * aspect; 02057 02058 glOrtho(xmin, xmax, ymin, ymax, zNear, zFar); 02059 } 02060 02061 02062 02063 #pragma mark - 02064 02065 /****************************************************************************/ 02066 // jit_ob3d attribute methods 02067 02068 t_jit_err jit_ob3d_attr_offset_get(t_jit_object *parent, void *x, long *ac, t_atom **av) 02069 { 02070 unsigned long ob3d_offset; // parent jit class offset to ob3d ptr. 02071 unsigned long attr_offset; // ob3d offset to attribute. 02072 t_symbol * attr_type; 02073 t_jit_ob3d * p_ob3d; 02074 t_jit_class3d * p_c3d; 02075 static method mf=NULL; 02076 02077 if (x&&parent) 02078 { 02079 if ((*ac)&&(*av)) { 02080 //memory passed in, use it 02081 } else { 02082 //otherwise allocate memory 02083 *ac = 0; 02084 if (!(*av = jit_getbytes(sizeof(t_atom)))) 02085 return JIT_ERR_OUT_OF_MEM; 02086 } 02087 02088 if (!mf) 02089 mf = jit_object_getmethod(NULL,NULL); 02090 p_c3d = ((t_jit_class3d *) jit_object_getmethod(parent, ps_JIT_CLASS3D_FINDER)); 02091 if (p_c3d==0||((method)p_c3d)==mf) return JIT_ERR_GENERIC; 02092 ob3d_offset = p_c3d->oboffset; 02093 if (ob3d_offset==0) return JIT_ERR_GENERIC; 02094 02095 p_ob3d = *(t_jit_ob3d **)(((char *)parent)+ob3d_offset); 02096 attr_offset = (unsigned long)jit_object_method(x, ps_getoffset); 02097 attr_type = (t_symbol *)jit_object_method(x, _jit_sym_gettype); 02098 02099 *ac = 1; 02100 if (attr_type==_jit_sym_char) 02101 jit_atom_setlong(*av, *((uchar *)(((char *)p_ob3d)+attr_offset))); 02102 else if (attr_type==_jit_sym_long) 02103 jit_atom_setlong(*av,*((ulong *)(((char *)p_ob3d)+attr_offset))); 02104 else if (attr_type==_jit_sym_float32) 02105 jit_atom_setfloat(*av,*((float *)(((char *)p_ob3d)+attr_offset))); 02106 else if (attr_type==_jit_sym_float64) 02107 jit_atom_setfloat(*av,*((double *)(((char *)p_ob3d)+attr_offset))); 02108 else if (attr_type==_jit_sym_symbol) 02109 jit_atom_setsym(*av,*((t_symbol **)(((char *)p_ob3d)+attr_offset))); 02110 else if (attr_type==_jit_sym_object) 02111 jit_atom_setobj(*av,*((void **)(((char *)p_ob3d)+attr_offset))); 02112 else if (attr_type==_jit_sym_pointer) 02113 jit_atom_setobj(*av,*((void **)(((char *)p_ob3d)+attr_offset))); 02114 else if (attr_type==_jit_sym_atom) 02115 **av = *((t_atom *)(((char *)p_ob3d)+attr_offset)); 02116 else 02117 jit_atom_setlong(*av,0); 02118 02119 return JIT_ERR_NONE; 02120 } 02121 return JIT_ERR_INVALID_PTR; 02122 } 02123 02124 t_jit_err jit_ob3d_attr_offset_set(t_jit_object *parent, void *x, long ac, t_atom *av) 02125 { 02126 unsigned long ob3d_offset; // parent jit class offset to ob3d ptr. 02127 unsigned long attr_offset; // ob3d offset to attribute. 02128 t_symbol * attr_type; 02129 t_jit_ob3d * p_ob3d; 02130 t_jit_class3d * p_c3d; 02131 static method mf=NULL; 02132 02133 if (x&&parent) 02134 { 02135 02136 if (!mf) 02137 mf = jit_object_getmethod(NULL,NULL); 02138 p_c3d = ((t_jit_class3d *) jit_object_getmethod(parent, ps_JIT_CLASS3D_FINDER)); 02139 if (p_c3d==0||((method)p_c3d)==mf) return JIT_ERR_GENERIC; 02140 ob3d_offset = p_c3d->oboffset; 02141 if (ob3d_offset==0) return JIT_ERR_GENERIC; 02142 02143 p_ob3d = *(t_jit_ob3d **)(((char *)parent)+ob3d_offset); 02144 attr_offset = (long)jit_object_method(x, ps_getoffset); 02145 attr_type = (t_symbol *)jit_object_method(x, _jit_sym_gettype); 02146 02147 if (attr_type==_jit_sym_char) 02148 *((uchar *)(((char *)p_ob3d)+attr_offset)) = jit_atom_getlong(av); 02149 else if (attr_type==_jit_sym_long) 02150 *((long *)(((char *)p_ob3d)+attr_offset)) = jit_atom_getlong(av); 02151 else if (attr_type==_jit_sym_float32) 02152 *((float *)(((char *)p_ob3d)+attr_offset)) = jit_atom_getfloat(av); 02153 else if (attr_type==_jit_sym_float64) 02154 *((double *)(((char *)p_ob3d)+attr_offset)) = jit_atom_getfloat(av); 02155 else if (attr_type==_jit_sym_symbol) 02156 *((t_symbol **)(((char *)p_ob3d)+attr_offset)) = jit_atom_getsym(av); 02157 else if (attr_type==_jit_sym_object) 02158 *((void **)(((char *)p_ob3d)+attr_offset)) = jit_atom_getobj(av); 02159 else if (attr_type==_jit_sym_pointer) 02160 *((void **)(((char *)p_ob3d)+attr_offset)) = jit_atom_getobj(av); 02161 else if (attr_type==_jit_sym_atom) 02162 *((t_atom *)(((char *)p_ob3d)+attr_offset)) = *av; 02163 02164 return JIT_ERR_NONE; 02165 } 02166 return JIT_ERR_INVALID_PTR; 02167 } 02168 02169 t_jit_ob3d *jit_ob3d_get_ob3d(t_jit_object *parent) 02170 { 02171 unsigned long ob3d_offset; // parent jit class offset to ob3d ptr. 02172 t_jit_class3d *p_c3d; 02173 static method mf=NULL; 02174 02175 if (parent) 02176 { 02177 if (!mf) 02178 mf = jit_object_getmethod(NULL,NULL); 02179 p_c3d = ((t_jit_class3d *) jit_object_getmethod(parent, ps_JIT_CLASS3D_FINDER)); 02180 if (!p_c3d||(method)p_c3d==mf) return NULL; 02181 ob3d_offset = p_c3d->oboffset; 02182 if (ob3d_offset==0) return NULL; 02183 02184 return *(t_jit_ob3d **)(((char *)parent)+ob3d_offset); 02185 } 02186 02187 return NULL; 02188 } 02189 02190 t_jit_err jit_ob3d_attr_offset_array_get(t_jit_object *parent, void *x, long *ac, t_atom **av) 02191 { 02192 long i; 02193 unsigned long attr_offset; // ob3d offset to attribute. 02194 t_symbol * type; 02195 t_jit_ob3d * p_ob3d; 02196 long offsetcount, size; 02197 02198 if (x&&parent) 02199 { 02200 p_ob3d = jit_ob3d_get_ob3d(parent); 02201 attr_offset = (long)jit_object_method(x, ps_getoffset); 02202 type = (t_symbol *)jit_object_method(x, _jit_sym_gettype); 02203 size = (long)jit_object_method(x, _jit_sym_getsize); 02204 offsetcount = (long)jit_object_method(x, ps_getoffsetcount); 02205 02206 if ((*ac)&&(*av)) 02207 { 02208 //memory passed in, use it 02209 if (offsetcount) *ac = MIN(*ac,*((long *)(((char *)p_ob3d)+offsetcount))); 02210 else *ac = MIN(*ac,size); 02211 } else 02212 { 02213 //otherwise allocate memory 02214 if (offsetcount) *ac = *((long *)(((char *)p_ob3d)+offsetcount)); 02215 else *ac = size; 02216 if (!(*av = jit_getbytes(sizeof(t_atom)*(*ac)))) { 02217 *ac = 0; 02218 return JIT_ERR_OUT_OF_MEM; 02219 } 02220 } 02221 for (i=0;i<*ac;i++) { 02222 if (type==_jit_sym_char) 02223 jit_atom_setlong((*av)+i,((uchar *)(((char *)p_ob3d)+attr_offset))[i]); 02224 else if (type==_jit_sym_long) 02225 jit_atom_setlong((*av)+i,((ulong *)(((char *)p_ob3d)+attr_offset))[i]); 02226 else if (type==_jit_sym_float32) 02227 jit_atom_setfloat((*av)+i,((float *)(((char *)p_ob3d)+attr_offset))[i]); 02228 else if (type==_jit_sym_float64) 02229 jit_atom_setfloat((*av)+i,((double *)(((char *)p_ob3d)+attr_offset))[i]); 02230 else if (type==_jit_sym_symbol) 02231 jit_atom_setsym((*av)+i,((t_symbol **)(((char *)p_ob3d)+attr_offset))[i]); 02232 else if (type==_jit_sym_object) 02233 jit_atom_setobj((*av)+i,((void **)(((char *)p_ob3d)+attr_offset))[i]); 02234 else if (type==_jit_sym_pointer) 02235 jit_atom_setobj((*av)+i,((void **)(((char *)p_ob3d)+attr_offset))[i]); 02236 else if (type==_jit_sym_atom) 02237 *((*av)+i) = ((t_atom *)(((char *)p_ob3d)+attr_offset))[i]; 02238 else 02239 jit_atom_setlong((*av)+i,0); 02240 } 02241 return JIT_ERR_NONE; 02242 } 02243 return JIT_ERR_INVALID_PTR; 02244 } 02245 02246 02247 t_jit_err jit_ob3d_attr_offset_array_set(t_jit_object *parent, void *x, long ac, t_atom *av) 02248 { 02249 long i,c; 02250 unsigned long attr_offset; // ob3d offset to attribute. 02251 t_symbol * type; 02252 t_jit_ob3d * p_ob3d; 02253 long offsetcount, size; 02254 02255 if (x&&parent) 02256 { 02257 p_ob3d = jit_ob3d_get_ob3d(parent); 02258 attr_offset = (long)jit_object_method(x, ps_getoffset); 02259 type = (t_symbol *)jit_object_method(x, _jit_sym_gettype); 02260 size = (long)jit_object_method(x, _jit_sym_getsize); 02261 offsetcount = (long)jit_object_method(x, ps_getoffsetcount); 02262 02263 c = MIN(ac, size); 02264 for (i=0;i<c;i++) 02265 { 02266 if (type==_jit_sym_char) 02267 ((uchar *)(((char *)p_ob3d)+attr_offset))[i] = jit_atom_getlong(av+i); 02268 else if (type==_jit_sym_long) 02269 ((long *)(((char *)p_ob3d)+attr_offset))[i] = jit_atom_getlong(av+i); 02270 else if (type==_jit_sym_float32) 02271 ((float *)(((char *)p_ob3d)+attr_offset))[i] = jit_atom_getfloat(av+i); 02272 else if (type==_jit_sym_float64) 02273 ((double *)(((char *)p_ob3d)+attr_offset))[i] = jit_atom_getfloat(av+i); 02274 else if (type==_jit_sym_symbol) 02275 ((t_symbol **)(((char *)p_ob3d)+attr_offset))[i] = jit_atom_getsym(av+i); 02276 else if (type==_jit_sym_object) 02277 ((void **)(((char *)p_ob3d)+attr_offset))[i] = jit_atom_getobj(av+i); 02278 else if (type==_jit_sym_pointer) 02279 ((void **)(((char *)p_ob3d)+attr_offset))[i] = jit_atom_getobj(av+i); 02280 else if (type==_jit_sym_atom) 02281 ((t_atom *)(((char *)p_ob3d)+attr_offset))[i] = *(av+i); 02282 } 02283 if (offsetcount) 02284 { 02285 *((long *)(((char *)p_ob3d)+offsetcount)) = c; 02286 } 02287 else 02288 { //fixed size array, set other elements to zero? 02289 if (c < size) { 02290 for (i = c; i < size; i++) { 02291 if (type==_jit_sym_char) 02292 ((uchar *)(((char *)p_ob3d)+attr_offset))[i] = 0; 02293 else if (type==_jit_sym_long) 02294 ((long *)(((char *)p_ob3d)+attr_offset))[i] = 0; 02295 else if (type==_jit_sym_float32) 02296 ((float *)(((char *)p_ob3d)+attr_offset))[i] = 0; 02297 else if (type==_jit_sym_float64) 02298 ((double *)(((char *)p_ob3d)+attr_offset))[i] = 0; 02299 else if (type==_jit_sym_symbol) 02300 ((t_symbol **)(((char *)p_ob3d)+attr_offset))[i] = 0; 02301 else if (type==_jit_sym_object) 02302 ((void **)(((char *)p_ob3d)+attr_offset))[i] = 0; 02303 else if (type==_jit_sym_pointer) 02304 ((void **)(((char *)p_ob3d)+attr_offset))[i] = 0; 02305 //nothing for fixed atom arrays??? 02306 } 02307 } 02308 } 02309 return JIT_ERR_NONE; 02310 } 02311 return JIT_ERR_INVALID_PTR; 02312 } 02313 02314 t_jit_err jit_ob3d_scale_set(t_jit_object *parent, void *x, long ac, t_atom *av) 02315 { 02316 t_atom a[3]; 02317 if (ac==1) { 02318 a[0] = *av; 02319 a[1] = *av; 02320 a[2] = *av; 02321 jit_ob3d_attr_offset_array_set(parent,x,3,a); 02322 } else 02323 jit_ob3d_attr_offset_array_set(parent,x,ac,av); 02324 return JIT_ERR_NONE; 02325 } 02326 02327 t_jit_err jit_ob3d_lens_angle_set(t_jit_object *parent, void *x, long ac, t_atom *av) 02328 { 02329 float f; 02330 t_atom a; 02331 02332 f = jit_atom_getfloat(av); 02333 if (ABS(f)<LENS_ANGLE_THRESH) 02334 f = (f<0) ? -LENS_ANGLE_THRESH : LENS_ANGLE_THRESH; 02335 jit_atom_setfloat(&a,f); 02336 02337 jit_ob3d_attr_offset_set(parent,x,1,&a); 02338 return JIT_ERR_NONE; 02339 } 02340 02341 t_jit_err jit_ob3d_attr_rotatexyz_get(t_jit_object *parent, void *x, long *ac, t_atom **av) 02342 { 02343 unsigned long ob3d_offset; // parent jit class offset to ob3d ptr. 02344 t_jit_ob3d * p_ob3d; 02345 t_jit_class3d * p_c3d; 02346 t_vec_3d v = {0.,0.,0.}; 02347 t_vec_3d rot = {0.,0.,0.}; 02348 float phi; 02349 static method mf=NULL; 02350 02351 if (x&&parent) 02352 { 02353 if (!mf) 02354 mf = jit_object_getmethod(NULL,NULL); 02355 p_c3d = ((t_jit_class3d *) jit_object_getmethod(parent, ps_JIT_CLASS3D_FINDER)); 02356 if (p_c3d==0||((method)p_c3d)==mf) return JIT_ERR_GENERIC; 02357 ob3d_offset = p_c3d->oboffset; 02358 if (ob3d_offset==0) return JIT_ERR_GENERIC; 02359 02360 p_ob3d = *(t_jit_ob3d **)(((char *)parent)+ob3d_offset); 02361 02362 if ((*ac)&&(*av)) 02363 { 02364 //memory passed in, use it 02365 *ac = MIN(*ac,3); 02366 } else 02367 { 02368 //otherwise allocate memory 02369 *ac = 3; 02370 if (!(*av = jit_getbytes(sizeof(t_atom)*(*ac)))) { 02371 *ac = 0; 02372 return JIT_ERR_OUT_OF_MEM; 02373 } 02374 } 02375 02376 phi = p_ob3d->rotation[0]*(PI/180.); // deg to rad; 02377 rot[0] = p_ob3d->rotation[1]; 02378 rot[1] = p_ob3d->rotation[2]; 02379 rot[2] = p_ob3d->rotation[3]; 02380 02381 axis_to_xyz(rot,phi,v); 02382 02383 vscale(v,(180./PI)); // rad to deg 02384 02385 jit_atom_setfloat((*av),v[0]); 02386 jit_atom_setfloat((*av)+1,v[1]); 02387 jit_atom_setfloat((*av)+2,v[2]); 02388 02389 return JIT_ERR_NONE; 02390 } 02391 return JIT_ERR_INVALID_PTR; 02392 } 02393 02394 t_jit_err jit_ob3d_attr_rotatexyz_set(t_jit_object *parent, void *x, long ac, t_atom *av) 02395 { 02396 t_jit_ob3d * p_ob3d; 02397 t_vec_3d v = {0.,0.,0.}; 02398 02399 if (x&&parent) 02400 { 02401 p_ob3d = jit_ob3d_get_ob3d(parent); 02402 02403 jit_atom_arg_getfloat(v,0,ac,av); 02404 jit_atom_arg_getfloat(v+1,1,ac,av); 02405 jit_atom_arg_getfloat(v+2,2,ac,av); 02406 02407 vscale(v,(PI/180.)); // deg to rad 02408 02409 xyz_to_axis(v,p_ob3d->rotation+1,p_ob3d->rotation); 02410 02411 p_ob3d->rotation[0] *= (180./PI); // rad to deg 02412 02413 // should we call the ob3d rotate settor method? 02414 02415 return JIT_ERR_NONE; 02416 } 02417 return JIT_ERR_INVALID_PTR; 02418 } 02419 02420 t_jit_err jit_ob3d_texture_set(t_jit_object *parent, void *x, long ac, t_atom *av) 02421 { 02422 t_jit_ob3d * p_ob3d; 02423 long wastexturecount; 02424 long wasnothing=TRUE; 02425 long isnothing=TRUE; 02426 02427 p_ob3d = jit_ob3d_get_ob3d(parent); 02428 wastexturecount = p_ob3d->texturecount; 02429 if (p_ob3d->texturecount&&p_ob3d->texture[0]&&p_ob3d->texture[0]!=_jit_sym_nothing&&p_ob3d->texture[0]!=ps_none) 02430 wasnothing = FALSE; 02431 02432 jit_ob3d_attr_offset_array_set(parent,x,ac,av); 02433 02434 if (p_ob3d->texturecount&&p_ob3d->texture[0]&&p_ob3d->texture[0]!=_jit_sym_nothing&&p_ob3d->texture[0]!=ps_none) 02435 isnothing = FALSE; 02436 if (wasnothing!=isnothing || wastexturecount!=p_ob3d->texturecount) { 02437 //set the context? 02438 jit_object_method(parent,ps_rebuild_geometry); 02439 } 02440 02441 return JIT_ERR_NONE; 02442 } 02443 02444 02445 02446 #pragma mark - 02447 02448 02449 /****************************************************************************/ 02450 // jit_ob3d standard methods. 02451 02452 // if we're not in automatic mode, trigger draw. 02453 t_jit_err jit_ob3d_draw(t_jit_object *x) 02454 { 02455 t_jit_ob3d *ob3d; 02456 if (x && (ob3d = jit_ob3d_get(x))) 02457 { 02458 if (ob3d->jitob&&ob3d->enable) 02459 { 02460 ob3d->last=jit_gl_current_ob3d_set((void *)ob3d); 02461 if (!ob3d->matrixoutput) 02462 { 02463 if (ob3d_draw_begin(ob3d,1)) 02464 goto cleanup; 02465 } 02466 02467 jit_object_method(ob3d->jitob, ps_ob3d_draw); 02468 02469 if (!ob3d->matrixoutput) 02470 ob3d_draw_end(ob3d,1); 02471 cleanup: 02472 jit_gl_current_ob3d_set(ob3d->last); 02473 } 02474 } 02475 return JIT_ERR_NONE; 02476 } 02477 02478 t_jit_err jit_ob3d_drawimmediate(t_jit_object *x) 02479 { 02480 t_jit_ob3d *ob3d; 02481 if (x && (ob3d = jit_ob3d_get(x))) 02482 { 02483 if (ob3d->jitob&&ob3d->enable) 02484 { 02485 ob3d->last=jit_gl_current_ob3d_set((void *)ob3d); 02486 if (!ob3d->matrixoutput) 02487 { 02488 if (ob3d_draw_begin(ob3d,0)) 02489 goto cleanup; 02490 } 02491 02492 jit_object_method(ob3d->jitob, ps_ob3d_draw); 02493 02494 if (!ob3d->matrixoutput) 02495 ob3d_draw_end(ob3d,0); 02496 cleanup: 02497 jit_gl_current_ob3d_set(ob3d->last); 02498 } 02499 } 02500 return JIT_ERR_NONE; 02501 } 02502 02503 02504 t_jit_err jit_ob3d_drawraw(t_jit_object *x) 02505 { 02506 t_jit_ob3d *ob3d; 02507 if (x && (ob3d = jit_ob3d_get(x))) 02508 { 02509 if (ob3d->jitob&&ob3d->enable) 02510 { 02511 jit_object_method(ob3d->jitob, ps_ob3d_draw); 02512 } 02513 } 02514 return JIT_ERR_NONE; 02515 } 02516 02517 // called for all ob3ds in ui client list. 02518 t_jit_err jit_ob3d_ui(t_jit_object *x, t_line_3d * p_line, t_wind_mouse_info *p_mouse) 02519 { 02520 t_jit_ob3d *ob3d; 02521 if (x && (ob3d = jit_ob3d_get(x))) 02522 { 02523 if (ob3d->jitob) 02524 { 02525 // stuff ui line and mouse info into ob3d structure. 02526 ob3d->ui_line = p_line; 02527 ob3d->ui_mouse = p_mouse; 02528 02529 // send ob3d_ui msg to jit obj. 02530 jit_object_method(ob3d->jitob, ps_ob3d_ui, p_line, p_mouse); 02531 } 02532 } 02533 return JIT_ERR_NONE; 02534 } 02535 02536 t_jit_err jit_ob3d_jit_gl_texture(t_jit_object *x, t_symbol *s, long argc, t_atom *argv) 02537 { 02538 object_attr_setvalueof(x,ps_texture,argc,argv); 02539 return JIT_ERR_NONE; 02540 } 02541 02542 t_jit_err jit_ob3d_dest_name_set(t_jit_object *x, void *attr, long argc, t_atom *argv) 02543 { 02544 char temp[255]; 02545 t_jit_err result = JIT_ERR_NONE; 02546 t_jit_ob3d *ob3d; 02547 02548 if (x && (ob3d = jit_ob3d_get(x)) && argc && argv) 02549 { 02550 t_symbol *v = jit_atom_getsym(argv); 02551 if(ob3d->dest_name != v) { 02552 02553 if (ob3d->dest_render_sym != _jit_sym_nothing) 02554 { 02555 if (!jit_ob3d_set_context(x)) 02556 jit_object_method(ob3d->jitob, ps_dest_closing); 02557 ob3d_leave_client_list(ob3d, (t_jit_ob3d_client_list **) &(ob3d->dest_render_sym->s_thing)); 02558 } 02559 ob3d->dest_name = v; 02560 02561 // post ("dest_name_set: got name %s", ob3d->dest_name->s_name); 02562 // hook up with registry symbol for messages from renderer. 02563 strcpy(temp, JIT_GL_RENDER_REG_STR); 02564 strcat(temp, ob3d->dest_name->s_name); 02565 ob3d->next = 0; 02566 ob3d->dest_render_sym = gensym(temp); 02567 02568 //mark as dirty, and forget about previous renderer 02569 ob3d_dirty_set(ob3d,1); 02570 jit_object_method(x, ps_render_ptr, NULL); 02571 02572 ob3d_enter_client_list(ob3d, (t_jit_ob3d_client_list **) &(ob3d->dest_render_sym->s_thing)); 02573 02574 /* now done inside render's do_draw_clients 02575 // send dest_changed method to jit obj. 02576 jit_object_method(ob3d->jitob, ps_dest_changed); 02577 */ 02578 } 02579 } 02580 return result; 02581 } 02582 02583 t_jit_err jit_ob3d_layer_set(t_jit_object *x, void *attr, long argc, t_atom *argv) 02584 { 02585 t_jit_err result = JIT_ERR_NONE; 02586 t_jit_ob3d *ob3d; 02587 long layer=0; 02588 02589 if (x && (ob3d = jit_ob3d_get(x)) && argc && argv) 02590 { 02591 layer = jit_atom_getlong(argv); 02592 if (ob3d->layer != layer) 02593 { 02594 t_jit_ob3d_client_list *ob3dlist = (t_jit_ob3d_client_list *) ob3d->dest_render_sym->s_thing; 02595 if (ob3dlist) { 02596 systhread_mutex_lock(ob3dlist->mutex); 02597 ob3dlist->dirty = 1; 02598 systhread_mutex_unlock(ob3dlist->mutex); 02599 } 02600 ob3d->layer = layer; 02601 } 02602 } 02603 return result; 02604 } 02605 02606 //NOTE: the render can also be set by ob3d_render_ptr_set 02607 t_jit_err jit_ob3d_renderer_set(t_jit_object *x, void *p_render) 02608 { 02609 t_jit_ob3d *ob3d; 02610 02611 if (x && (ob3d = jit_ob3d_get(x))) 02612 { 02613 ob3d->renderer = p_render; 02614 } 02615 return JIT_ERR_NONE; 02616 } 02617 02618 void * jit_ob3d_renderer_get(t_jit_object *x) 02619 { 02620 t_jit_ob3d *ob3d; 02621 02622 if (!(ob3d = jit_ob3d_get(x))) 02623 return 0; 02624 else 02625 return ob3d->renderer; 02626 } 02627 02628 02629 #pragma mark - 02630 02631 /****************************************************************************/ 02632 // jit_ob3d geometry utils 02633 02634 // world_to_screen and screen_to_world treat screen coordinates in GL terms 02635 // usable with glRasterPos2* etc. flipping y is still necessary to convert to QuickDraw screen coords. 02636 02637 t_jit_err jit_ob3d_world_to_screen(t_jit_object *x, t_point_3d p_world, t_point_3d p_screen) 02638 { 02639 GLint viewport[4]; 02640 GLdouble mvmatrix[16], projmatrix[16]; 02641 GLdouble wx, wy, wz; 02642 int result; 02643 t_jit_ob3d *ob3d; 02644 02645 if (!x || !(ob3d = jit_ob3d_get(x))) return JIT_ERR_GENERIC; 02646 02647 if (jit_object_classname(x)==ps_jit_gl_render) { //special case if renderer 02648 if (JIT_ERR_NONE != jit_object_method(x, ps_setup)) return JIT_ERR_GENERIC; 02649 ob3d_draw_preamble(ob3d); 02650 } else { 02651 if (!ob3d->renderer) return JIT_ERR_GENERIC; 02652 //if (JIT_ERR_NONE != jit_object_method(ob3d->renderer, ps_setup)) return JIT_ERR_GENERIC; 02653 } 02654 02655 glGetIntegerv(GL_VIEWPORT, viewport); 02656 glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix); 02657 glGetDoublev(GL_PROJECTION_MATRIX, projmatrix); 02658 02659 result = gluProject(p_world[0], p_world[1], p_world[2], 02660 mvmatrix, projmatrix, viewport, 02661 &wx, &wy, &wz); 02662 02663 if (result == GL_TRUE) 02664 { 02665 jit_gl_set_floats(p_screen, 3, wx, wy, wz); 02666 result = JIT_ERR_NONE; 02667 } 02668 else 02669 { 02670 jit_gl_set_floats(p_screen, 3, 0., 0., 0.); 02671 result = JIT_ERR_GENERIC; 02672 } 02673 02674 return result; 02675 } 02676 02677 02678 t_jit_err jit_ob3d_screen_to_world(t_jit_object *x, t_point_3d p_screen, t_point_3d p_world) 02679 { 02680 GLint viewport[4]; 02681 GLdouble mvmatrix[16], projmatrix[16]; 02682 GLdouble sx, sy, sz, wx, wy, wz; 02683 int result; 02684 t_jit_ob3d *ob3d; 02685 02686 if (!x || !(ob3d = jit_ob3d_get(x))) return JIT_ERR_GENERIC; 02687 02688 if (jit_object_classname(x)==ps_jit_gl_render) { //special case if renderer 02689 if (JIT_ERR_NONE != jit_object_method(x, ps_setup)) return JIT_ERR_GENERIC; 02690 ob3d_draw_preamble(ob3d); 02691 } else { 02692 if (!ob3d->renderer) return JIT_ERR_GENERIC; 02693 if (JIT_ERR_NONE != jit_object_method(ob3d->renderer, ps_setup)) return JIT_ERR_GENERIC; 02694 } 02695 02696 glGetIntegerv(GL_VIEWPORT, viewport); 02697 glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix); 02698 glGetDoublev(GL_PROJECTION_MATRIX, projmatrix); 02699 02700 sx = p_screen[0]; 02701 sy = p_screen[1]; 02702 sz = p_screen[2]; 02703 02704 result = gluUnProject(sx, sy, sz, 02705 mvmatrix, projmatrix, viewport, 02706 &wx, &wy, &wz); 02707 02708 if (result == GL_TRUE) 02709 { 02710 jit_gl_set_floats(p_world, 3, wx, wy, wz); 02711 result = JIT_ERR_NONE; 02712 } 02713 else 02714 { 02715 jit_gl_set_floats(p_world, 3, 0., 0., 0.); 02716 result = JIT_ERR_GENERIC; 02717 } 02718 02719 return result; 02720 } 02721 02722 02723 02724 02725 #pragma mark - 02726 02727 /****************************************************************************/ 02728 02729 /** 02730 * Draws one t_jit_glchunk 02731 * If the OB3D is not in matrixoutput mode, the drawing call is 02732 * made directly to the renderer. Otherwise, the chunk is sent 02733 * out the OB3D's outlet as a message compatible with jit.gl.render. 02734 * 02735 * @ingroup ob3dmod 02736 * 02737 * @param v t_jit_ob3d pointer 02738 * @param chunk t_jit_glchunk pointer 02739 * 02740 * @return t_jit_err error code 02741 * 02742 */ 02743 t_jit_err jit_ob3d_draw_chunk(void *v, t_jit_glchunk * chunk) 02744 { 02745 t_symbol *s = ps_jit_glchunk; 02746 t_jit_ob3d * ob3d = v; 02747 Atom av[8]; 02748 t_jit_err result = JIT_ERR_NONE; 02749 02750 if (!ob3d || !chunk) return JIT_ERR_INVALID_PTR; 02751 02752 if (!ob3d->matrixoutput) 02753 { 02754 jit_atom_setlong(av, (long)(void *)chunk); 02755 jit_object_method(ob3d->renderer, s, s, 1, av); 02756 } 02757 else 02758 { 02759 if (ob3d->jitob) 02760 { 02761 ob3d->p_chunk = chunk; 02762 jit_object_notify(ob3d->jitob, ps_draw_chunk, NULL); 02763 } 02764 } 02765 02766 return result; 02767 } 02768 02769 // max objects call this to get the chunk when we notify them to draw in matrixoutput mode. 02770 t_jit_err jit_ob3d_get_chunk(t_jit_object *x, t_jit_glchunk ** chunk) 02771 { 02772 t_jit_ob3d *ob3d; 02773 if (!x || !(ob3d = jit_ob3d_get(x))) 02774 { 02775 chunk = NULL; 02776 return JIT_ERR_GENERIC; 02777 } 02778 // post ("3. getting chunk from ob3d"); 02779 *chunk = ob3d->p_chunk; 02780 return JIT_ERR_NONE; 02781 } 02782 02783 02784 /****************************************************************************/ 02785 02786 t_max_err jit_gl_worldtoscreen(t_jit_object *x, t_point_3d p_world, t_point_3d p_screen) 02787 { 02788 GLint viewport[4]; 02789 GLdouble mvmatrix[16], projmatrix[16]; 02790 GLdouble wx, wy, wz; 02791 int result; 02792 02793 glGetIntegerv(GL_VIEWPORT, viewport); 02794 glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix); 02795 glGetDoublev(GL_PROJECTION_MATRIX, projmatrix); 02796 02797 result = gluProject(p_world[0], p_world[1], p_world[2], 02798 mvmatrix, projmatrix, viewport, 02799 &wx, &wy, &wz); 02800 02801 if (result == GL_TRUE) 02802 { 02803 p_screen[0] = wx; 02804 p_screen[1] = viewport[3] - wy; 02805 p_screen[2] = wz; 02806 result = MAX_ERR_NONE; 02807 } 02808 else 02809 { 02810 p_screen[0] = 0; 02811 p_screen[1] = 0; 02812 p_screen[2] = 0; 02813 result = MAX_ERR_GENERIC; 02814 } 02815 02816 return result; 02817 } 02818 02819 t_max_err jit_gl_screentoworld(t_jit_object *x, t_point_3d p_screen, t_point_3d p_world) 02820 { 02821 GLint viewport[4]; 02822 GLdouble mvmatrix[16], projmatrix[16]; 02823 GLdouble sx, sy, sz, wx, wy, wz; 02824 int result; 02825 02826 glGetIntegerv(GL_VIEWPORT, viewport); 02827 glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix); 02828 glGetDoublev(GL_PROJECTION_MATRIX, projmatrix); 02829 02830 sx = p_screen[0]; 02831 sy = viewport[3] - p_screen[1]; 02832 sz = p_screen[2]; 02833 02834 result = gluUnProject(sx, sy, sz, 02835 mvmatrix, projmatrix, viewport, 02836 &wx, &wy, &wz); 02837 02838 if (result == GL_TRUE) 02839 { 02840 p_world[0] = wx; 02841 p_world[1] = wy; 02842 p_world[2] = wz; 02843 result = MAX_ERR_NONE; 02844 } 02845 else 02846 { 02847 p_world[0] = 0; 02848 p_world[1] = 0; 02849 p_world[2] = 0; 02850 result = MAX_ERR_GENERIC; 02851 } 02852 02853 return result; 02854 }
Copyright © 2008, Cycling '74