33#include <libFreeWRL.h>
35#include "../vrml_parser/Structs.h"
36#include "../vrml_parser/CRoutes.h"
37#include "../main/headers.h"
39#include "../world_script/fieldSet.h"
40#include "../x3d_parser/Bindable.h"
42#include "quaternion.h"
44#include "../opengl/Frustum.h"
45#include "../opengl/LoadTextures.h"
46#include "../opengl/Material.h"
47#include "../opengl/OpenGL_Utils.h"
48#include "../input/EAIHelpers.h"
51#include "RenderFuncs.h"
52#include "LinearAlgebra.h"
55#include "Component_Shape.h"
56#include "../opengl/Textures.h"
60}* ppComponent_ParticleSystems;
61void *Component_ParticleSystems_constructor(){
66void Component_ParticleSystems_init(
struct tComponent_ParticleSystems *t){
69 t->prv = Component_ParticleSystems_constructor();
71 ppComponent_ParticleSystems p = (ppComponent_ParticleSystems)t->prv;
75void Component_ParticleSystems_clear(
struct tComponent_ParticleSystems *t){
251 srand((
unsigned int) TickTime());
254 rx = (float)ix/(
float)RAND_MAX;
257float uniformRandCentered(){
258 return uniformRand() - .5f;
260void circleRand2D(
float *xy){
264 xy[0] = 2.0f*(uniformRand() - .5f);
265 xy[1] = 2.0f*(uniformRand() - .5f);
266 radius2 = xy[0]*xy[0] + xy[1]*xy[1];
267 if(radius2 <= 1.0f)
break;
281 return (
float)(rxy[0]*.5);
284void randomTriangleCoord_dug9_uneducated_guess(
float *p,
float* p1,
float *p2,
float *p3){
293 p[i] = b1*p1[i] + b2*p2[i] + (1.0f - b1 - b2)*p3[i];
296void randomTriangleCoord(
float *p,
float* p1,
float *p2,
float *p3){
299 float r1, r2, sqr1,sqr2;
305 p[i] = (1.0f - sqr1)*p1[i] + (sqr1*(1.0f - sqr2))*p2[i] + (r2*sqr1)*p3[i];
309void randomPoint3D(
float *xyz){
311 xyz[0] = (uniformRand() - .5f);
312 xyz[1] = (uniformRand() - .5f);
313 xyz[2] = (uniformRand() - .5f);
315void randomDirection(
float *xyz){
326 radius3 = xyz[0]*xyz[0] + xyz[1]*xyz[1] + xyz[2]*xyz[2];
327 if(radius3 <= 1.0f && radius3 > 0.0000001f){
330 vecscale3f(xyz,xyz,1.0f/sqrtf(radius3));
352 double transitionStart[2];
353 double transitionTime[2];
354 double _startTime[2];
355 int lastMotionsEnabled[2];
357 int permutationIndex;
372} geomtype_table [] = {
376{
"SPRITE",GEOM_SPRITE},
377{
"TRIANGLE",GEOM_TRIANGLE},
378{
"GEOMETRY",GEOM_GEOMETRY},
383int lookup_geomtype(
const char *name){
387 if(geomtype_table[i].name == NULL)
break;
388 if(!strcmp(geomtype_table[i].name,name)){
389 iret = geomtype_table[i].type;
397static GLfloat quadtris [18] = {-.5f,-.5f,0.0f, .5f,-.5f,0.0f, .5f,.5f,0.0f, .5f,.5f,0.0f, -.5f,.5f,0.0f, -.5f,-.5f,0.0f,};
398static GLfloat twotrisnorms [18] = {0.f,0.f,1.f, 0.f,0.f,1.f, 0.f,0.f,1.f, 0.f,0.f,1.f, 0.f,0.f,1.f, 0.f,0.f,1.f,};
399static GLfloat twotristex [12] = {0.f,0.f, 1.f,0.f, 1.f,1.f, 1.f,1.f, 0.f,1.f, 0.f,0.f};
401void compile_Shape (
struct X3D_Shape *node);
412 if (node->_tris == NULL) {
413 node->_tris = MALLOC(
void*, 18 *
sizeof(
float));
416 vertices = (
float*)(node->_tris);
418 for (i = 0; i < 6; i++) {
419 float* vert, * vert0;
420 vert0 = &quadtris[i * 3];
421 vert = &vertices[i * 3];
422 vert[0] = vert0[0] * node->particleSize.c[0];
423 vert[1] = vert0[1] * node->particleSize.c[1];
427 if (node->texCoordRamp || node->texCoord) {
430 if (node->texCoordRamp)
434 n = node->texCoordKey.n;
441 node->_ttex = MALLOC(
void*, mt * 2 *
sizeof(
float));
443 node->_ltex = MALLOC(
void*, ml * 2 *
sizeof(
float));
444 if (tc->point.n == mq) {
450 ttex = (
float*)node->_ttex;
451 for (i = 0; i < n; i++) {
453 for (j = 0, k = 0; j < 4; j++, k++) {
454 float* p = (
float*)(
float*)&tc->point.p[i * 4 + j];
455 veccopy2f(&ttex[(i * 6 + k) * 2], p);
457 veccopy2f(&ttex[(i * 6 + 5) * 2], p);
461 veccopy2f(&ttex[(i * 6 + k) * 2], p);
465 if (0)
for (i = 0; i < n; i++) {
466 for (j = 0; j < 6; j++)
467 printf(
"%f %f,", ttex[(i * 6 + j) * 2 + 0], ttex[(i * 6 + j) * 2 + 1]);
474 ltex = (
float*)node->_ltex;
475 for (i = 0; i < n; i++) {
477 for (j = 0; j < 2; j++) {
481 p[1] = min(sf->c[1], .9999f);
482 veccopy2f(<ex[(i * 2 + j) * 2], p);
487 if (tc->point.n == ml) {
491 ltex = (
float*)node->_ltex;
492 for (i = 0; i < n; i++) {
494 for (j = 0; j < 2; j++) {
498 p[1] = min(sf->c[1], .9999f);
499 veccopy2f(<ex[(i * 2 + j) * 2], p);
502 if (0)
for (i = 0; i < n; i++) {
503 printf(
"%f %f, %f %f\n", ltex[i * 2 * 2 + 0], ltex[i * 2 * 2 + 1], ltex[i * 2 * 2 + 2], ltex[i * 2 * 2 + 3]);
506 ttex = (
float*)node->_ttex;
507 for (i = 0; i < n; i++) {
510 p = (
float*)(
float*)&tc->point.p[j * 2 + 0];
511 veccopy2f(&ttex[(i * 6 + 0) * 2], p);
512 veccopy2f(&ttex[(i * 6 + 5) * 2], p);
513 p = (
float*)(
float*)&tc->point.p[j * 2 + 1];
514 veccopy2f(&ttex[(i * 6 + 1) * 2], p);
516 j = j == n ? j - 1 : j;
517 p = (
float*)(
float*)&tc->point.p[j * 2 + 1];
518 veccopy2f(&ttex[(i * 6 + 2) * 2], p);
519 veccopy2f(&ttex[(i * 6 + 3) * 2], p);
520 p = (
float*)(
float*)&tc->point.p[j * 2 + 0];
521 veccopy2f(&ttex[(i * 6 + 4) * 2], p);
531 int i,j, maxparticles;
535 node->_geometryType = lookup_geomtype(node->geometryType->strptr);
536 if (node->_geometryType < GEOM_HANIM) {
537 compile_geom_particle(node);
540 if (node->_geometryType == GEOM_HANIM) {
541 compile_hanim_particle(node);
545 maxparticles = min(node->maxParticles,10000);
546 if(node->_particles == NULL)
547 node->_particles = newVector(
particle,maxparticles);
548 _particles = node->_particles;
549 if(_particles->allocn < maxparticles) {
551 _particles->data = realloc(_particles->data,maxparticles);
552 _particles->allocn = maxparticles;
556 if(!node->_lasttime || node->enabled && !node->_lastEnabled)
557 node->_lasttime = TickTime();
558 if(node->enabled && !node->_lastEnabled){
559 node->isActive = TRUE;
561 }
else if(!node->enabled && node->_lastEnabled){
562 node->isActive = FALSE;
565 node->_lastEnabled = node->enabled;
571void prep_windphysics(
struct X3D_Node *physics){
575 speed = px->speed * (1.0f + uniformRandCentered()*px->gustiness);
576 px->_frameSpeed = speed;
581 if(px->enabled && pp->mass != 0.0f){
584 float turbdir[3], pdir[3],acceleration[3], v2[3];
585 speed = px->_frameSpeed;
586 pressure = powf(10.0f,2.0f*log10f(speed)) * .64615f;
587 force = pressure * pp->surfaceArea;
588 randomDirection(turbdir);
589 vecscale3f(turbdir,turbdir,px->turbulence);
590 vecadd3f(pdir,px->direction.c,turbdir);
591 vecnormalize3f(pdir,pdir);
592 vecscale3f(pdir,pdir,force);
594 vecscale3f(acceleration,pdir,1.0f/pp->mass);
595 vecscale3f(v2,acceleration,dtime);
596 vecadd3f(pp->velocity,pp->velocity,v2);
597 float flen = veclength3f(pp->velocity);
599 vecscale3f(pp->direction, pp->velocity, 1.0f / flen);
604int intersect_polyrep(
struct X3D_Node *node,
float *p1,
float *p2,
float *nearest,
float *normal);
606void compile_geometry(
struct X3D_Node *gnode){
609 switch(gnode->_nodeType){
610 case NODE_IndexedFaceSet:
614 if (!compile_poly_if_required(node, node->coord, node->fogCoord, node->color, node->normal, node->texCoord))
return;
622int intersect_geometry(
struct X3D_Node *gnode,
float *p1,
float *p2,
float *nearest,
float *normal){
626 switch(gnode->_nodeType){
627 case NODE_IndexedFaceSet:
628 iret = intersect_polyrep(gnode,p1,p2,nearest,normal);
635void apply_boundedphysics(
particle *pp,
struct X3D_Node *physics,
float *positionChange){
637 if(px->enabled && px->geometry ) {
642 float pos1[3], pos2[3], pnearest[3],normal[3], delta[3];
647 if(NODE_NEEDS_COMPILING)
648 compile_geometry(node);
653 veccopy3f(pos1,pp->origin);
655 vecadd3f(pos2,pp->position,positionChange);
662 nintersections = intersect_geometry(px->geometry,pos1,pos2,pnearest,normal);
663 if(nintersections > 0){
664 float d[3], r[3], rn[3], rd[3], n[3], ddotnn[3], orthogn[3], orthogn2[3];
665 float ddotn, speed, dlengthi,dlength;
666 vecdif3f(delta,pos2,pos1);
667 dlength = veclength3f(delta);
686 vecdif3f(d,pnearest,pos1);
687 dlengthi = veclength3f(d);
688 vecnormalize3f(n,normal);
689 ddotn = vecdot3f(d,n);
691 vecscale3f(ddotnn,n,ddotn);
692 vecdif3f(orthogn,d,ddotnn);
693 vecscale3f(orthogn2,orthogn,2.0f);
694 vecdif3f(r,d,orthogn2);
695 vecscale3f(r,r,-1.0f);
696 vecnormalize3f(rn,r);
699 speed = veclength3f(pp->velocity);
700 vecscale3f(pp->velocity,rn,speed);
701 float flen = veclength3f(pp->velocity);
703 vecscale3f(pp->direction, pp->velocity, 1.0f / flen);
707 vecscale3f(rd,rn,dlength - dlengthi);
708 vecadd3f(pp->position,pnearest,rd);
709 vecscale3f(positionChange,positionChange,0.0f);
710 veccopy3f(pos1,pnearest);
711 veccopy3f(pp->origin,pos1);
712 veccopy3f(pos2,pp->position);
713 if(0) pp->age = 1000.0f;
723void apply_forcephysics(
particle *pp,
struct X3D_Node *physics,
float dtime){
731 if(px->enabled && pp->mass != 0.0f){
732 float acceleration[3], v2[3];
733 vecscale3f(acceleration,px->force.c,1.0f/pp->mass);
734 vecscale3f(v2,acceleration,dtime);
735 vecadd3f(pp->velocity,pp->velocity,v2);
736 float flen = veclength3f(pp->velocity);
738 vecscale3f(pp->direction, pp->velocity, 1.0f / flen);
744void apply_resistancephysics(
particle* pp,
struct X3D_Node* physics,
float dtime) {
748 if (px->enabled && pp->mass != 0.0f) {
749 float deceleration, v2;
750 deceleration = px->force / pp->mass;
751 v2 = 1.0f - deceleration * dtime;
752 vecscale3f(pp->velocity, pp->velocity, v2);
753 float flen = veclength3f(pp->velocity);
755 vecscale3f(pp->direction, pp->velocity, 1.0f / flen);
767 float direction[3], tilt, azimuth, speed;
773 float orthog1[3],orthog2[3];
775 vecnormalize3f(direction,e->direction.c);
776 amin = min(min(fabsf(direction[0]),fabsf(direction[1])),fabsf(direction[2]));
779 if(fabsf(direction[i]) == amin){
784 for(i=0;i<3;i++) orthog1[i] = 0.0f;
785 orthog1[imin] = 1.0f;
788 veccross3f(orthog2,direction,orthog1);
791 veccross3f(orthog1,direction,orthog2);
807 float az[3],az1[3],az2[3],ctilt,stilt,caz,saz;
808 tilt = uniformRand()*e->angle;
811 azimuth = uniformRand()*2.0f*(float)PI;
814 vecscale3f(az1,orthog1,caz);
815 vecscale3f(az2,orthog2,saz);
816 vecadd3f(az,az1,az2);
818 vecscale3f(az,az,stilt);
820 vecscale3f(direction,direction,ctilt);
822 vecadd3f(direction,direction,az);
831 float xy[2], orx[3],ory[3], orthog[3];
834 vecscale3f(orx,orthog1,xy[0]);
835 vecscale3f(ory,orthog2,xy[1]);
836 vecadd3f(orthog,orx,ory);
837 vecscale3f(orthog,orthog,sinf(e->angle));
838 vecscale3f(direction,direction,cosf(e->angle));
840 vecadd3f(direction,orthog,direction);
842 vecnormalize3f(direction,direction);
846 memcpy(pp->position,e->position.c,3*
sizeof(
float));
847 speed = e->speed*(1.0f + uniformRandCentered()*e->variation);
848 vecscale3f(pp->velocity,direction,speed);
849 float flen = veclength3f(direction);
851 vecscale3f(pp->direction, direction, 1.0f / flen);
853 pp->mass = e->mass*(1.0f + uniformRandCentered()*e->variation);
854 pp->surfaceArea = e->surfaceArea*(1.0f + uniformRandCentered()*e->variation);
862 float direction[3], speed;
863 memcpy(pp->position,e->position.c,3*
sizeof(
float));
864 randomDirection(direction);
865 speed = e->speed*(1.0f + uniformRandCentered()*e->variation);
866 vecscale3f(pp->velocity,direction,speed);
867 float flen = veclength3f(direction);
869 vecscale3f(pp->direction, direction, 1.0f / flen);
871 pp->mass = e->mass*(1.0f + uniformRandCentered()*e->variation);
872 pp->surfaceArea = e->surfaceArea*(1.0f + uniformRandCentered()*e->variation);
878 float direction[3], speed;
879 memcpy(pp->position,e->position.c,3*
sizeof(
float));
880 if(veclength3f(e->direction.c) < .00001){
881 randomDirection(direction);
883 memcpy(direction,e->direction.c,3*
sizeof(
float));
884 vecnormalize3f(direction,direction);
886 speed = e->speed*(1.0f + uniformRandCentered()*e->variation);
887 vecscale3f(pp->velocity,direction,speed);
888 float flen = veclength3f(direction);
890 vecscale3f(pp->direction, direction, 1.0f / flen);
892 pp->mass = e->mass*(1.0f + uniformRandCentered()*e->variation);
893 pp->surfaceArea = e->surfaceArea*(1.0f + uniformRandCentered()*e->variation);
897 POLYLINEEMITTER_METHODA = 1,
898 POLYLINEEMITTER_METHODB = 2,
900void compile_PolylineEmitter(
struct X3D_Node *node){
904 e->_method = POLYLINEEMITTER_METHODB;
905 if(e->coord && e->coordIndex.n > 1){
907 int i,k,ind, n,nseg = 0;
911 segs = MALLOC(
void*,2*3*
sizeof(
float) *n*2 );
914 for(i=0;i<e->coordIndex.n;i++){
915 ind = e->coordIndex.p[i];
920 pts[k] = (
float*)&coord->point.p[ind];
923 veccopy3f(&segs[(nseg*2 +0)*3],pts[0]);
924 veccopy3f(&segs[(nseg*2 +1)*3],pts[1]);
933 if(e->_method == POLYLINEEMITTER_METHODB){
935 float *portions, totaldist, dist, delta[3];
936 portions = MALLOC(
float *,e->_nseg *
sizeof(
float));
937 e->_portions = portions;
939 for(i=0;i<e->_nseg;i++){
940 vecdif3f(delta,&segs[(i*2 + 1)*3],&segs[(i*2 + 0)*3]);
941 dist = veclength3f(delta);
946 for(i=0;i<e->_nseg;i++){
947 portions[i] = portions[i]/totaldist;
955 float direction[3], speed;
961 if(NODE_NEEDS_COMPILING)
962 compile_PolylineEmitter(node);
963 memset(pp->position,0,3*
sizeof(
float));
964 if(e->_method == POLYLINEEMITTER_METHODA && e->_nseg){
965 float *segs, delta[3], pos[3];
967 int iseg = (int) floorf(uniformRand() * (
float)e->_nseg);
969 float fraction = uniformRand();
970 segs = (
float *)e->_segs;
971 vecdif3f(delta,&segs[(iseg*2 + 1)*3],&segs[(iseg*2 + 0)*3]);
972 vecscale3f(delta,delta,fraction);
973 vecadd3f(pos,&segs[(iseg*2 + 0)*3],delta);
974 veccopy3f(pp->position,pos);
976 if(e->_method == POLYLINEEMITTER_METHODB && e->_nseg){
979 float cumulative, fraction, *portions, *segs, delta[3], pos[3], segfraction;
980 fraction = uniformRand();
981 portions = (
float*)e->_portions;
983 for(i=0;i<e->_nseg;i++){
984 cumulative +=portions[i];
985 if(cumulative > fraction){
986 segfraction = (cumulative - fraction) / portions[i];
987 segs = (
float *)e->_segs;
988 vecdif3f(delta,&segs[(i*2 + 1)*3],&segs[(i*2 + 0)*3]);
989 vecscale3f(delta,delta,segfraction);
990 vecadd3f(pos,&segs[(i*2 + 0)*3],delta);
991 veccopy3f(pp->position,pos);
999 if(veclength3f(e->direction.c) < .00001){
1000 randomDirection(direction);
1002 memcpy(direction,e->direction.c,3*
sizeof(
float));
1003 vecnormalize3f(direction,direction);
1005 speed = e->speed*(1.0f + uniformRandCentered()*e->variation);
1006 vecscale3f(pp->velocity,direction,speed);
1007 float flen = veclength3f(direction);
1009 vecscale3f(pp->direction, direction, 1.0f / flen);
1011 pp->mass = e->mass*(1.0f + uniformRandCentered()*e->variation);
1012 pp->surfaceArea = e->surfaceArea*(1.0f + uniformRandCentered()*e->variation);
1015int getPolyrepTriangleCount(
struct X3D_Node *node);
1016int getPolyrepTriangleByIndex(
struct X3D_Node *node,
int index,
float *v1,
float *v2,
float *v3);
1022 node = e->surface ? e->surface : e->geometry;
1027 float xyz[3], v1[3],v2[3],v3[3],e1[3],e2[3], normal[3], direction[3];
1029 if(NODE_NEEDS_COMPILING){
1030 compile_geometry(X3D_NODE(node));
1034 fraction = uniformRand();
1035 ntri = getPolyrepTriangleCount(node);
1037 index = (int)floorf(fraction * (
float)(ntri-1));
1038 getPolyrepTriangleByIndex(node,index,v1,v2,v3);
1039 randomTriangleCoord(xyz,v1,v2,v3);
1042 veccross3f(normal,e1,e2);
1043 vecnormalize3f(direction,normal);
1048 memcpy(pp->position,xyz,3*
sizeof(
float));
1049 speed = e->speed*(1.0f + uniformRandCentered()*e->variation);
1050 vecscale3f(pp->velocity,direction,speed);
1051 float flen = veclength3f(direction);
1053 vecscale3f(pp->direction, direction, 1.0f / flen);
1055 pp->mass = e->mass*(1.0f + uniformRandCentered()*e->variation);
1056 pp->surfaceArea = e->surfaceArea*(1.0f + uniformRandCentered()*e->variation);
1065 if (!e->_ifs && e->coord) {
1067 ifs = createNewX3DNode0(NODE_IndexedFaceSet);
1068 ifs->coord = e->coord;
1069 ifs->coordIndex = e->coordIndex;
1070 compile_geometry(X3D_NODE(ifs));
1074 int nint, i, isInside;
1075 float xyz[3], plumb[3], nearest[3], normal[3];
1076 float direction[3], speed;
1080 for (i = 0; i < 10; i++) {
1083 xyz[0] *= ifs->EXTENT_MAX_X - ifs->EXTENT_MIN_X;
1084 xyz[1] *= ifs->EXTENT_MAX_Y - ifs->EXTENT_MIN_Y;
1085 xyz[2] *= ifs->EXTENT_MAX_Z - ifs->EXTENT_MIN_Z;
1086 veccopy3f(plumb, xyz);
1087 plumb[2] = ifs->EXTENT_MIN_Z - 1.0f;
1088 nint = intersect_geometry(e->_ifs, xyz, plumb, nearest, normal);
1089 nint = abs(nint) % 2;
1096 vecscale3f(xyz, xyz, 0.0f);
1098 memcpy(pp->position, xyz, 3 *
sizeof(
float));
1099 if (veclength3f(e->direction.c) < .00001) {
1100 randomDirection(direction);
1103 memcpy(direction, e->direction.c, 3 *
sizeof(
float));
1104 vecnormalize3f(direction, direction);
1106 speed = e->speed * (1.0f + uniformRandCentered() * e->variation);
1107 vecscale3f(pp->velocity, direction, speed);
1108 float flen = veclength3f(direction);
1110 vecscale3f(pp->direction, direction, 1.0f / flen);
1112 pp->mass = e->mass * (1.0f + uniformRandCentered() * e->variation);
1113 pp->surfaceArea = e->surfaceArea * (1.0f + uniformRandCentered() * e->variation);
1119struct rgba {
unsigned char r, g, b, a; };
1121 unsigned char bytes[4];
1127unsigned char* sample_image(textureTableIndexStruct_s* tt,
float x,
float y) {
1132 ix = (int)( px * x );
1133 ix = ix < 0 ? 0 : ix >= tt->x ? tt->x - 1 : ix;
1135 iy = iy < 0 ? 0 : iy >= tt->y ? tt->y - 1 : iy;
1136 unsigned char* pixel = &tt->texdata[(iy * px + ix) * 4];
1139void set_image_pixel_color(
unsigned char * image,
int cols,
int rows,
unsigned char * pixel,
int x,
int y) {
1140 memcpy(&image[(y * cols + x) * 4], pixel, 3);
1142unsigned char* get_image_pixel_color(
unsigned char* image,
int cols,
int rows,
int x,
int y) {
1143 return &image[(y * cols + x) * 4];
1145void set_image_pixel_transparency(
unsigned char* image,
int cols,
int rows,
unsigned char transparency,
int x,
int y) {
1146 image[(y * cols + x) * 4 + 3] = transparency;
1148unsigned char get_image_pixel_transparency(
unsigned char* image,
int cols,
int rows,
int x,
int y) {
1149 return image[(y * cols + x) * 4 + 3];
1151unsigned char get_image_pixel_channel(
unsigned char* image,
int cols,
int rows,
int channel,
int x,
int y) {
1152 return image[(y * cols + x) * 4 + channel];
1154void set_image_pixel_channel(
unsigned char* image,
int cols,
int rows,
unsigned char c,
int channel,
int x,
int y) {
1155 image[(y * cols + x) * 4 + channel] = c;
1157void print_image_channel(
unsigned char* imageRGBA,
int channel,
int width,
int height) {
1158 for (
int k = 0; k < width; k += 10) printf(
"%d ", k / 10);
1160 for (
int j = 0; j < height; j++) {
1161 for (
int k = 0; k < width; k++) {
1162 unsigned char c = get_image_pixel_channel(imageRGBA, width, height, channel, k, j);
1164 printf(
"%c", c +
'A');
1168 printf(
" %2d\n", j);
1173float* extent4f_clear(
float* e) {
1180int extent4f_isSet(
float* e4) {
1185 iret = (e[2] >= e[0] && e[3] >= e[1]) ? TRUE : FALSE;
1188float * extent4f_union_extent4f(
float *e4,
float *ein4){
1190 isa = extent4f_isSet(e4);
1191 isb = extent4f_isSet(ein4);
1193 for (i = 0; i < 2; i++) {
1194 e4[i] = min(e4[i], ein4[i]);
1195 e4[i+2] = max(e4[i+2], ein4[i+2]);
1197 else if (isb) veccopy4f(e4, ein4);
1200float* extent4f_union_vec2f(
float* extent4,
float* p2) {
1202 isa = extent4f_isSet(extent4);
1204 for (i = 0; i < 2; i++) {
1206 extent4[i+2] = p2[i];
1208 for (i = 0; i < 2; i++) {
1209 extent4[i] = min(extent4[i], p2[i]);
1210 extent4[i+2] = max(extent4[i+2], p2[i]);
1214void extent4f_printf(
float* extent4) {
1215 printf(
"min %f %f max %f %f \n", extent4[0], extent4[1], extent4[2], extent4[3]);
1217float* pixel2color3(
float * color,
unsigned char* pixel) {
1218 for (
int i = 0; i < 3; i++)
1219 color[i] = ((
float)(
int)pixel[i]) / 255.0f;
1224 vecset3f(pp->position, 0.0f, 0.0f, 0.0f);
1226 pp->speed = normalRand() * e->variation + e->speed;
1227 pp->speed = pp->speed <= 0.0 ? e->speed : pp->speed;
1228 pp->_startTime[0] = pp->_startTime[1] = TickTime();
1232 if (e->functionMap) {
1234 render_node(e->functionMap);
1235 textureTableIndexStruct_s* tt = getTableTableFromTextureNode(e->functionMap);
1236 if (tt && tt->status >= TEX_READ) {
1237 if (e->emitterColor.n)
1239 if (!e->classified) {
1242 printf(
"start classifying emitter..\n");
1243 e->eboxes.p = malloc(e->emitterColor.n *
sizeof(
struct SFVec4f));
1244 e->eboxes.n = e->emitterColor.n;
1245 e->iboxes.p = malloc(e->emitterColor.n *
sizeof(
struct SFVec4f));
1246 e->iboxes.n = e->emitterColor.n;
1247 for (
int i = 0; i < e->eboxes.n; i++) {
1248 extent4f_clear(e->eboxes.p[i].c);
1249 extent4f_clear(e->iboxes.p[i].c);
1253 isteps[0] = (int)(e->gridSize.c[0] + .5f);
1254 isteps[1] = (int)(e->gridSize.c[1] + .5f);
1255 for(
int i=0; i< isteps[0];i++)
1256 for (
int j = 0; j < isteps[1]; j++) {
1257 float x, y, s[3], exy[2], ixy[2];
1259 x = (float)i / (
float)e->gridSize.c[0];
1260 y = (float)j / (
float)e->gridSize.c[1];
1264 exy[0] = (float)i - e->gridSize.c[0]/2.0f;
1265 exy[1] = (float)j - e->gridSize.c[1]/2.0f;
1266 unsigned char* pixel = sample_image(tt, x, y);
1267 pixel2color3(s, pixel);
1269 for (
int k = 0; k < e->emitterColor.n; k++) {
1270 float* c = e->emitterColor.p[k].c;
1271 int is_close = vecclose3f(s, c, e->colorMatchTolerance);
1273 extent4f_union_vec2f(e->iboxes.p[k].c, ixy);
1274 extent4f_union_vec2f(e->eboxes.p[k].c, exy);
1280 for (
int i = 0; i < e->eboxes.n; i++) {
1281 extent4f_printf(e->eboxes.p[i].c);
1282 extent4f_printf(e->iboxes.p[i].c);
1284 printf(
"..end classfying emitter\n");
1285 e->classified = TRUE;
1289 int valid_regions = 0;
1290 for (
int i = 0; i < e->iboxes.n; i++)
1291 if (extent4f_isSet(e->eboxes.p[i].c)) valid_regions++;
1292 int iregion = (int)(uniformRand() * (
float)(valid_regions));
1295 for (
int i = 0; i < e->iboxes.n; i++)
1297 int is_set = extent4f_isSet(e->iboxes.p[i].c);
1298 if (is_set) nvalid++;
1299 if (is_set && nvalid == iregion) {
1301 float x, y, xyz[3], s[3];
1302 float exy[2], ixy[2];
1308 ixy[0] = x * (e->iboxes.p[i].c[2] - e->iboxes.p[i].c[0]) + e->iboxes.p[i].c[0];
1309 ixy[1] = y * (e->iboxes.p[i].c[3] - e->iboxes.p[i].c[1]) + e->iboxes.p[i].c[1];
1311 exy[0] = x * (e->eboxes.p[i].c[2] - e->eboxes.p[i].c[0]) + e->eboxes.p[i].c[0];
1312 exy[1] = y * (e->eboxes.p[i].c[3] - e->eboxes.p[i].c[1]) + e->eboxes.p[i].c[1];
1314 unsigned char* pixel = sample_image(tt, ixy[0], ixy[1]);
1315 pixel2color3(s, pixel);
1316 if (vecclose3f(s, e->emitterColor.p[i].c, e->colorMatchTolerance))
1319 vecset3f(xyz, exy[0], exy[1], 0.0f);
1321 printf(
"iregion %d xy %f %f valid_regions %d", iregion, exy[0], exy[1], valid_regions);
1322 veccopy3f(pp->position, xyz);
1324 pp->permutationIndex = -1;
1334int emitter_loaded(
struct X3D_Node* emitter) {
1336 switch (emitter->_nodeType) {
1337 case NODE_MapEmitter:
1340 if (e->functionMap) {
1341 textureTableIndexStruct_s* tt = getTableTableFromTextureNode(e->functionMap);
1343 render_node(e->functionMap);
1344 if (tt && tt->status >= TEX_READ) loaded = TRUE;
1355void norm2image(
int *ixy,
int *isize,
float *fxy) {
1357 ixy[0] = (int)(fxy[0] * (
float)isize[0] + .5f);
1358 ixy[1] = (int)(fxy[1] * (
float)isize[1] + .5f);
1359 ixy[0] = max(min(isize[0] - 1, ixy[0]),0);
1360 ixy[1] = max(min(isize[1] - 1, ixy[1]),0);
1362void image2norm(
float* fxy,
int* ixy,
int* isize) {
1364 fxy[0] = (float)ixy[0] / (
float)isize[0];
1365 fxy[1] = (float)ixy[1] / (
float)isize[1];
1367void saveSnapshotBMP(
char* pathname,
char* buffer,
int bytesPerPixel,
int width,
int height);
1368void set_debug_quad(
int which_debug_shader,
int textureID);
1369void render_debug_quad();
1370void display_imagedata4(
unsigned char* texdata,
int width,
int height,
int imageIndex) {
1373 static textureTableIndexStruct_s tts;
1374 static int once = 0;
1378 tts.texdata = texdata;
1381 FW_GL_GENTEXTURES(1, &tts.OpenGLTexture);
1387 sprintf(namebuf,
"C:\\tmp\\sinkmap%d.web3dit", imageIndex);
1388 saveImage_web3dit(&tts, namebuf);
1390 sprintf(namebuf,
"C:\\tmp\\sinkmap%d.bmp", imageIndex);
1391 saveSnapshotBMP(namebuf, tts.texdata, tts.channels, tts.x, tts.y);
1395 glBindTexture(GL_TEXTURE_2D,tts.OpenGLTexture);
1396 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tts.x, tts.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, tts.texdata);
1397 set_debug_quad(1, tts.OpenGLTexture);
1402void apply_mapphysics(
particle* pp,
struct X3D_Node* physics,
float dtime) {
1407 if (!px->classified) {
1408 if (px->functionMap) {
1410 textureTableIndexStruct_s* tt = getTableTableFromTextureNode(px->functionMap);
1412 render_node(px->functionMap);
1414 if (tt && tt->status >= TEX_READ) {
1416 if (px->sinkColor.n)
1418 printf(
"start classifying physics..\n");
1421 px->eboxes.p = malloc(px->sinkColor.n *
sizeof(
struct SFVec4f));
1422 px->eboxes.n = px->sinkColor.n;
1423 px->iboxes.p = malloc(px->sinkColor.n *
sizeof(
struct SFVec4f));
1424 px->iboxes.n = px->sinkColor.n;
1425 for (
int i = 0; i < px->eboxes.n; i++) {
1426 extent4f_clear(px->eboxes.p[i].c);
1427 extent4f_clear(px->iboxes.p[i].c);
1431 isteps[0] = ((int)(px->gridSize.c[0] + .5f));
1432 isteps[1] = ((int)(px->gridSize.c[1] + .5f));
1433 for (
int i = 0; i < isteps[0]; i++)
1434 for (
int j = 0; j < isteps[1]; j++) {
1435 float x, y, s[3], exy[2], ixy[2];
1437 x = (float)i / (
float)px->gridSize.c[0];
1438 y = (float)j / (
float)px->gridSize.c[1];
1442 exy[0] = (float)i - px->gridSize.c[0] / 2.0f;
1443 exy[1] = (float)j - px->gridSize.c[1] / 2.0f;
1444 unsigned char* pixel = sample_image(tt, x, y);
1445 pixel2color3(s, pixel);
1447 for (
int k = 0; k < px->sinkColor.n; k++) {
1448 float* c = px->sinkColor.p[k].c;
1449 int is_close = vecclose3f(s, c, px->colorMatchTolerance);
1451 extent4f_union_vec2f(px->iboxes.p[k].c, ixy);
1452 extent4f_union_vec2f(px->eboxes.p[k].c, exy);
1458 printf(
"sink boxes\n");
1459 for (
int i = 0; i < px->eboxes.n; i++) {
1460 extent4f_printf(px->eboxes.p[i].c);
1461 extent4f_printf(px->iboxes.p[i].c);
1465 jsteps[0] = isteps[0] * 2;
1466 jsteps[1] = isteps[1] * 2;
1467 int sinkmapsize = jsteps[0] * jsteps[1] * 4;
1468 px->_sinkmaps = malloc(sinkmapsize * (px->eboxes.n + 1));
1469 unsigned char* sinkmaps = (
unsigned char*)px->_sinkmaps;
1470 unsigned char* popmap = &sinkmaps[0];
1471 memset(popmap, 0, sinkmapsize);
1473 for (
int i = 0; i < px->iboxes.n; i++)
1476 int is_set = extent4f_isSet(px->iboxes.p[i].c);
1480 unsigned char* texdata = &sinkmaps[(i+1) * sinkmapsize];
1481 memset(texdata, 0, jsteps[0] * jsteps[1] * 4);
1485 float* bbox = &px->iboxes.p[i].c[0];
1486 fcenter[0] = ((bbox[0] + bbox[2]) / 2.0f);
1487 fcenter[1] = ((bbox[1] + bbox[3]) / 2.0f);
1488 norm2image(icenter, jsteps, fcenter);
1491 set_image_pixel_color(texdata, jsteps[0], jsteps[1], pixel.bytes, icenter[0], icenter[1]);
1496 struct ixy {
int x, y, steps; };
1497 struct Vector* current = newVector(
struct ixy, 100);
1498 struct Vector* next = newVector(
struct ixy, 100);
1500 struct ixy p, q, nebor[8];
1501 unsigned char done, steps, * funcp;
1507 for (
int i = 0; i < 8; i++) {
1508 nebor[i].x = nebor[i].y = 0;
1511 nebor[0].y = nebor[1].y = nebor[2].y = -1;
1512 nebor[0].x = nebor[3].x = nebor[5].x = -1;
1513 nebor[2].x = nebor[4].x = nebor[7].x = 1;
1514 nebor[5].y = nebor[6].y = nebor[7].y = 1;
1515 nebor[0].steps = nebor[2].steps = nebor[5].steps = nebor[7].steps = 3;
1519 set_image_pixel_transparency(texdata, jsteps[0], jsteps[1], 1, p.x, p.y);
1520 stack_push(
struct ixy, current, p);
1529 for (
int i = 0; i < vectorSize(current); i++) {
1530 p = vector_get(
struct ixy, current, i);
1531 done = get_image_pixel_transparency(texdata, jsteps[0], jsteps[1], p.x, p.y);
1535 pixel.int16[0] = p.steps;
1537 set_image_pixel_transparency(texdata, jsteps[0], jsteps[1], 2, p.x, p.y);
1538 set_image_pixel_color(texdata, jsteps[0], jsteps[1], pixel.bytes, p.x, p.y);
1540 for (
int j = 0; j < 8; j++) {
1541 q.x = p.x + nebor[j].x;
1542 q.y = p.y + nebor[j].y;
1543 q.steps = p.steps + nebor[j].steps;
1545 if (q.x < 0 || q.x >= jsteps[0] || q.y < 0 || q.y >= jsteps[1])
continue;
1549 xx = (float)q.x / (
float)jsteps[0];
1550 yy = (float)q.y / (
float)jsteps[1];
1551 funcp = sample_image(tt, xx,yy);
1552 pixel2color3(color, funcp);
1553 int is_close = vecclose3f(color, px->obstacleColor.c, px->colorMatchTolerance);
1554 if (is_close)
continue;
1557 done = get_image_pixel_transparency(texdata, jsteps[0], jsteps[1], q.x, q.y);
1558 if (done == 2)
continue;
1561 for (
int k = 0; k < vectorSize(next); k++) {
1562 struct ixy* qq = vector_get_ptr(
struct ixy, next, k);
1563 if (qq->x == q.x && qq->y == q.y) {
1564 if (qq->steps > q.steps) {
1565 qq->steps = q.steps;
1574 stack_push(
struct ixy, next, q);
1575 set_image_pixel_transparency(texdata, jsteps[0], jsteps[1], 1, q.x, q.y);
1581 vector_clear(current);
1585 more = vectorSize(current);
1590 printf(
"flood map %d x steps %d y steps %d\n", i, jsteps[0], jsteps[1]);
1591 print_image_channel(texdata, 0, jsteps[0], jsteps[1]);
1595 for (
int jj = 0; jj < jsteps[1]; jj++)
1596 for (
int ii = 0; ii < jsteps[0]; ii++) {
1600 texdata[(jj * jsteps[0] + ii) * 4 + 3] = 0xff;
1602 display_imagedata4(texdata, jsteps[0], jsteps[1],i);
1609 px->classified = TRUE;
1610 printf(
"..end classifying physics\n");
1626 int isteps[2], jsteps[2];
1627 isteps[0] = ((int)(px->gridSize.c[0] + .5f));
1628 isteps[1] = ((int)(px->gridSize.c[1] + .5f));
1629 jsteps[0] = isteps[0] * 2;
1630 jsteps[1] = isteps[1] * 2;
1631 int sinkmapsize = jsteps[0] * jsteps[1] * 4;
1632 unsigned char* sinkmaps = (
unsigned char*)px->_sinkmaps;
1635 unsigned char* popmap = &sinkmaps[0];
1637 unsigned char* sinkmap;
1638 pix * sinkcolor, * funccolor, sinkuchar;
1640 struct ixy {
int x, y; };
1641 struct ixy p, q, nebor[8];
1644 textureTableIndexStruct_s* tt = getTableTableFromTextureNode(px->functionMap);
1647 if (pp->sink == -1) {
1648 pp->sink = (int)(uniformRand() * (
float)px->sinkColor.n);
1649 printf(
"pp.sink = %d\n", pp->sink);
1650 if (pp->sink < 0 || pp->sink >= px->sinkColor.n) {
1651 printf(
"bad sink number %d, should be 0-%d\n", pp->sink, px->sinkColor.n - 1);
1654 sinkmap = &sinkmaps[sinkmapsize * (pp->sink + 1)];
1660 xy[0] = (pp->position[0] + px->gridSize.c[0] * .5f) / px->gridSize.c[0];
1661 xy[1] = (pp->position[1] + px->gridSize.c[1] * .5f) / px->gridSize.c[1];
1663 p.x = (int)(xy[0] * jsteps[0] + .5);
1664 p.y = (int)(xy[1] * jsteps[1] + .5);
1665 if(debug) printf(
"pp.position %f %f p %d %d\n", pp->position[0], pp->position[1], p.x, p.y);
1666 if (p.x < 0 || p.x >= jsteps[0] || p.y < 0 || p.y >= jsteps[1]) {
1669 printf(
"off the sink map\n");
1673 for (
int i = 0; i < 8; i++) nebor[i].x = nebor[i].y = 0;
1674 nebor[0].y = nebor[1].y = nebor[2].y = -1;
1675 nebor[0].x = nebor[3].x = nebor[5].x = -1;
1676 nebor[2].x = nebor[4].x = nebor[7].x = 1;
1677 nebor[5].y = nebor[6].y = nebor[7].y = 1;
1684 sinkcolor = (
pix*)get_image_pixel_color(sinkmap, jsteps[0], jsteps[1], p.x, p.y);
1685 if (sinkcolor->int16[0] < 3) {
1688 set_image_pixel_channel(popmap, jsteps[0], jsteps[1],0, 0, p.x, p.y);
1689 pp->age = pp->lifespan+1.0f;
1694 funccolor = (
pix*)sample_image(tt, xy[0], xy[1]);
1695 pixel2color3(color, funccolor->bytes);
1696 int on_wait = vecclose3f(color, px->pauseColor.c, px->colorMatchTolerance);
1700 int nlist, ilist[8], dlist[8], iscore[8];
1702 int dshortest = 1000000;
1703 if (debug) print_image_channel(popmap, 0, jsteps[0], jsteps[1]);
1724 set_image_pixel_channel(popmap, jsteps[0], jsteps[1], 0,0, pp->maplocation[0],pp->maplocation[1]);
1726 for (
int i = 0; i < 8; i++) {
1729 q.x = p.x + nebor[i].x;
1730 q.y = p.y + nebor[i].y;
1732 if (q.x < 0 || q.x >= jsteps[0] || q.y < 0 || q.y >= jsteps[1])
continue;
1735 pix *sinkval = (
pix*)get_image_pixel_color(sinkmap, jsteps[0], jsteps[1], q.x, q.y);
1737 if (sinkval->int16[0] == 0)
continue;
1742 unsigned char populated = get_image_pixel_channel(popmap, jsteps[0], jsteps[1], 0, q.x, q.y);
1744 if (populated)
continue;
1747 dlist[i] = sinkval->int16[0];
1748 if (dlist[i] < dshortest) {
1750 dshortest = dlist[i];
1754 if(0)
if (debug || ishortest < 0) {
1755 for (
int m = 0; m < 8; m++) printf(
"iscore[%d]=%d,", m, iscore[m]);
1758 if (ishortest > -1) {
1761 q.x = p.x + nebor[ishortest].x;
1762 q.y = p.y + nebor[ishortest].y;
1766 xx = (float)q.x / (
float)jsteps[0];
1767 yy = (float)q.y / (
float)jsteps[1];
1768 funccolor = (
pix*)sample_image(tt, xx, yy);
1769 pixel2color3(color, funccolor->bytes);
1770 if (px->pauseState) {
1771 is_wait = vecclose3f(color, px->pauseColor.c, px->colorMatchTolerance);
1775 set_image_pixel_channel(popmap, jsteps[0], jsteps[1], 255, 0, p.x, p.y);
1776 vecset3f(pp->velocity, 0.0f, 0.0f, 0.0f);
1780 float pxy[3], qxy[3], diff[3], dir[3];
1781 pxy[0] = (float)p.x * .5f;
1782 pxy[1] = (float)p.y * .5f;
1784 qxy[0] = (float)q.x * .5f;
1785 qxy[1] = (float)q.y * .5f;
1787 vecdif3f(diff, qxy, pxy);
1788 vecnormalize3f(dir, diff);
1790 vecscale3f(pp->velocity, dir, pp->speed);
1791 float flen = veclength3f(dir);
1793 vecscale3f(pp->direction, dir, 1.0f / flen);
1797 set_image_pixel_channel(popmap, jsteps[0], jsteps[1], 255, 0, q.x, q.y);
1798 pp->maplocation[0] = q.x;
1799 pp->maplocation[1] = q.y;
1800 if (debug) printf(
"shortest %d velocity %f %f particle %p\n", ishortest, pp->velocity[0], pp->velocity[1], pp);
1806 if(debug) printf(
"waiting particle %p\n", pp);
1807 set_image_pixel_channel(popmap, jsteps[0], jsteps[1], 255, 0, p.x, p.y);
1809 vecset3f(pp->velocity, 0.0f, 0.0f, 0.0f);
1813 if(debug) getchar();
1822 int j,k,ifloor, iceil, found;
1823 float rgbaf[4], rgbac[4],
rgba[4], fraclife;
1825 fraclife = pp->age / pp->lifespan;
1826 for(j=0;j<node->colorKey.n;j++){
1827 if(node->colorKey.p[j] <= fraclife && node->colorKey.p[j+1] > fraclife){
1835 float spread, fraction;
1839 if (node->colorRamp) color_ramp = node->colorRamp;
1840 else if (node->color) color_ramp = node->color;
1841 switch(color_ramp->_nodeType){
1842 case NODE_ColorRGBA: crgba = ((
struct X3D_ColorRGBA *)color_ramp)->color.p;
break;
1843 case NODE_Color: crgb = ((
struct X3D_Color *)color_ramp)->color.p;
break;
1847 spread = node->colorKey.p[iceil] - node->colorKey.p[ifloor];
1848 fraction = (fraclife - node->colorKey.p[ifloor]) / spread;
1850 memcpy(rgbaf,&crgba[ifloor],
sizeof(
struct SFColorRGBA));
1851 memcpy(rgbac,&crgba[iceil],
sizeof(
struct SFColorRGBA));
1853 memcpy(rgbaf,&crgb[ifloor],
sizeof(
struct SFColor));
1855 memcpy(rgbac,&crgb[iceil],
sizeof(
struct SFColor));
1859 rgba[k] = (1.0f - fraction)*rgbaf[k] + fraction*rgbac[k];
1861 glUniform4fv(cramp,1,
rgba);
1867 int found, ifloor,j;
1868 float fraclife, fracKey;
1871 fraclife = pp->age / pp->lifespan;
1872 fracKey = 1.0f / (float)(node->texCoordKey.n);
1874 fraclife -= fracKey;
1877 for(j=0;j<node->texCoordKey.n;j++){
1878 if( node->texCoordKey.p[j] > fraclife){
1885 switch(node->_geometryType){
1887 FW_GL_TEXCOORD_POINTER (2,GL_FLOAT,0,(
float *)&texcoord[ifloor*2*2],0);
1892 FW_GL_TEXCOORD_POINTER (2,GL_FLOAT,0,(
float *)&texcoord[ifloor*2*6],0);
1900void reallyDrawOnce();
1902GLfloat linepts [6] = {-.5f,0.f,0.f, .5f,0.f,0.f};
1903int lineindices[2] = {0,1};
1904int getImageChannelCountFromTTI(
struct X3D_Node *appearanceNode );
1905void update_effect_uniforms();
1906void check_compile(
struct X3D_Node* node){
1911 PRINT_GL_ERROR_IF_ANY(
"child_shape depth start");
1912 s_shader_capabilities_t* scap;
1915 shader_requirements.base = node->_shaderflags_base;
1916 shader_requirements.effects = node->_shaderflags_effects;
1917 shader_requirements.usershaders = node->_shaderflags_usershaders;
1919 shader_requirements.depth = TRUE;
1920 shader_requirements.base |= PARTICLE_SHADER;
1922 scap = getMyShaders(shader_requirements);
1923 enableGlobalShader(scap);
1924 sendMatriciesToShader(scap);
1925 switch (node->_geometryType) {
1928 FW_GL_VERTEX_POINTER(3, GL_FLOAT, 0, (
float*)linepts);
1929 sendElementsToGPU(GL_LINES, 2, (
int*)lineindices);
1935 memset(point, 0, 3 *
sizeof(
float));
1936 FW_GL_VERTEX_POINTER(3, GL_FLOAT, 0, (GLfloat*)point);
1937 sendArraysToGPU(GL_POINTS, 0, 1);
1943 FW_GL_VERTEX_POINTER(3, GL_FLOAT, 0, (GLfloat*)node->_tris);
1944 FW_GL_NORMAL_POINTER(GL_FLOAT, 0, twotrisnorms);
1945 sendArraysToGPU(GL_TRIANGLES, 0, 6);
1951 FW_GL_VERTEX_POINTER(3, GL_FLOAT, 0, (GLfloat*)node->_tris);
1952 FW_GL_NORMAL_POINTER(GL_FLOAT, 0, twotrisnorms);
1953 sendArraysToGPU(GL_TRIANGLES, 0, 6);
1959 FW_GL_VERTEX_POINTER(3, GL_FLOAT, 0, (GLfloat*)node->_tris);
1960 FW_GL_NORMAL_POINTER(GL_FLOAT, 0, twotrisnorms);
1961 sendArraysToGPU(GL_TRIANGLES, 0, 6);
1965 render_node(node->geometry);
1970 GLint ppos, pdir, cr, gtype, itrans;
1972 ppos = GET_UNIFORM(scap->myShaderProgram,
"particlePosition");
1973 pdir = GET_UNIFORM(scap->myShaderProgram,
"particleDirection");
1974 itrans = GET_UNIFORM(scap->myShaderProgram,
"particleTransform");
1975 cr = GET_UNIFORM(scap->myShaderProgram,
"fw_UnlitColor");
1976 gtype = GET_UNIFORM(scap->myShaderProgram,
"fw_ParticleGeomType");
1977 glUniform1i(gtype, node->_geometryType);
1981 Stack* _particles = node->_particles;
1984 double matrix[16], * mat[4];
1986 for (i = 0; i < 4; i++)
1987 mat[i] = &matrix[i * 4];
1988 matidentity4d(matrix);
1990 double* rot[4], * rot2[4], matyaw[16], matpitch[16], matrot[16];
1992 for (i = 0; i < 2; i++)
1993 mat[i][i] = node->particleSize.c[i];
1995 for (i = 0; i < 3; i++)
1996 axisangle_rotate3d(mat[i], mat[i], node->particleOrientation.c);
1998 double2float(fmat, matrix, 16);
1999 glUniformMatrix4fv(itrans, 1, TRUE, fmat);
2002 for (
int i = 0; i < vectorSize(_particles); i++) {
2005 glUniform3fv(ppos, 1, pp.position);
2007 glUniform3fv(pdir, 1, pp.direction);
2015 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, 0);
2016 FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER, 0);
2017 finishedWithGlobalShader();
2020 ttglobal tg = gglobal();
2023 GLint ppos, pdir, cr, gtype;
2031 int allowsTexcoordRamp = FALSE;
2032 float* texcoord = NULL;
2033 int haveColorRamp, haveTexcoordRamp;
2036 s_shader_capabilities_t* scap;
2044 RENDER_MATERIAL_SUBNODES(node->appearance);
2049 POSSIBLE_PROTO_EXPANSION(
struct X3D_Node*, node->geometry, tmpNG);
2051 shader_requirements.base = node->_shaderflags_base;
2052 shader_requirements.effects = node->_shaderflags_effects;
2053 shader_requirements.usershaders = node->_shaderflags_usershaders;
2054 isUserShader = shader_requirements.usershaders ? TRUE : FALSE;
2056 if (!isUserShader) {
2074 int channels, modulation, scenefile_specversion;
2085 channels = getImageChannelCountFromTTI(node->appearance);
2088 scenefile_specversion = X3D_PROTO(node->_executionContext)->__specversion;
2090 switch (fwl_get_modulation()) {
2093 modulation = scenefile_specversion >= 400 ? TRUE : FALSE;
2096 modulation = FALSE;
break;
2098 modulation = TRUE;
break;
2102 if (modulation == TRUE) {
2103 shader_requirements.base |= MODULATE_TEXTURE;
2105 if (!channels || (channels == 1 || channels == 3))
2106 shader_requirements.base |= MODULATE_ALPHA;
2107 if (channels && (channels == 1 || channels == 2))
2108 shader_requirements.base |= MODULATE_COLOR;
2115 shader_requirements.base |= getShaderFlags().base;
2116 shader_requirements.effects |= getShaderFlags().effects;
2121 shader_requirements.base |= PARTICLE_SHADER;
2122 if (node->colorRamp || node->color)
2123 shader_requirements.base |= HAVE_UNLIT_COLOR;
2126 scap = getMyShaders(shader_requirements);
2127 enableGlobalShader(scap);
2131 if (tmpNG && tmpNG->_intern && tmpNG->_intern->itype == 2) {
2133 if (tmppr->tcoordtype == NODE_TextureCoordinateGenerator) {
2134 getAppearanceProperties()->texCoordGeneratorType = tmppr->texgentype;
2140#ifdef ALLOW_USERSHADERS
2141 if (isUserShader && p->userShaderNode) {
2145 switch (p->userShaderNode->_nodeType) {
2146 case NODE_ComposedShader:
2147 if (X3D_COMPOSEDSHADER(p->userShaderNode)->isValid) {
2148 if (!X3D_COMPOSEDSHADER(p->userShaderNode)->_initialized) {
2149 sendInitialFieldsToShader(p->userShaderNode);
2153 case NODE_ProgramShader:
2154 if (X3D_PROGRAMSHADER(p->userShaderNode)->isValid) {
2155 if (!X3D_PROGRAMSHADER(p->userShaderNode)->_initialized) {
2156 sendInitialFieldsToShader(p->userShaderNode);
2161 case NODE_PackagedShader:
2162 if (X3D_PACKAGEDSHADER(p->userShaderNode)->isValid) {
2163 if (!X3D_PACKAGEDSHADER(p->userShaderNode)->_initialized) {
2164 sendInitialFieldsToShader(p->userShaderNode);
2173 if (shader_requirements.effects) {
2174 update_effect_uniforms();
2181 clear_textureUnit_used();
2182 clear_material_samplers();
2183 clear_materialparameters_per_draw_counts();
2185 textureTransform_start();
2189 allowsTexcoordRamp = FALSE;
2191 switch (node->_geometryType) {
2194 FW_GL_VERTEX_POINTER(3, GL_FLOAT, 0, (
float*)linepts);
2195 sendElementsToGPU(GL_LINES, 2, (
int*)lineindices);
2196 texcoord = (
float*)node->_ltex;
2197 allowsTexcoordRamp = TRUE;
2203 memset(point, 0, 3 *
sizeof(
float));
2204 FW_GL_VERTEX_POINTER(3, GL_FLOAT, 0, (GLfloat*)point);
2205 sendArraysToGPU(GL_POINTS, 0, 1);
2211 FW_GL_VERTEX_POINTER(3, GL_FLOAT, 0, (GLfloat*)node->_tris);
2212 FW_GL_NORMAL_POINTER(GL_FLOAT, 0, twotrisnorms);
2213 sendArraysToGPU(GL_TRIANGLES, 0, 6);
2214 texcoord = (
float*)node->_ttex;
2215 allowsTexcoordRamp = TRUE;
2221 FW_GL_VERTEX_POINTER(3, GL_FLOAT, 0, (GLfloat*)node->_tris);
2222 FW_GL_NORMAL_POINTER(GL_FLOAT, 0, twotrisnorms);
2223 sendArraysToGPU(GL_TRIANGLES, 0, 6);
2229 FW_GL_VERTEX_POINTER(3, GL_FLOAT, 0, (GLfloat*)node->_tris);
2230 FW_GL_NORMAL_POINTER(GL_FLOAT, 0, twotrisnorms);
2231 sendArraysToGPU(GL_TRIANGLES, 0, 6);
2232 texcoord = (
float*)node->_ttex;
2233 allowsTexcoordRamp = TRUE;
2237 render_node(node->geometry);
2243 ppos = GET_UNIFORM(scap->myShaderProgram,
"particlePosition");
2244 pdir = GET_UNIFORM(scap->myShaderProgram,
"particleDirection");
2245 cr = GET_UNIFORM(scap->myShaderProgram,
"fw_UnlitColor");
2246 gtype = GET_UNIFORM(scap->myShaderProgram,
"fw_ParticleGeomType");
2247 int itrans = GET_UNIFORM(scap->myShaderProgram,
"particleTransform");
2248 glUniform1i(gtype, node->_geometryType);
2250 haveColorRamp = node->colorRamp || node->color ? TRUE : FALSE;
2251 haveColorRamp = haveColorRamp && cr > -1;
2252 haveTexcoordRamp = node->texCoordRamp || node->texCoord ? TRUE : FALSE;
2253 haveTexcoordRamp = haveTexcoordRamp && allowsTexcoordRamp && texcoord;
2254 if (haveTexcoordRamp) {
2256 glUniform1i(scap->nTexCoordChannels, 1);
2257 glUniform1i(scap->flipuv, 0);
2260 float estart6[6], eout6[6];
2262 extent6f_clear(estart6);
2265 double matrix[16], * mat[4];
2267 for (i = 0; i < 4; i++)
2268 mat[i] = &matrix[i * 4];
2269 matidentity4d(matrix);
2271 double* rot[4], * rot2[4], matyaw[16], matpitch[16], matrot[16];
2273 for (i = 0; i < 2; i++)
2274 mat[i][i] = node->particleSize.c[i];
2276 for (i = 0; i < 3; i++)
2277 axisangle_rotate3d(mat[i], mat[i], node->particleOrientation.c);
2279 double2float(fmat, matrix, 16);
2280 glUniformMatrix4fv(itrans, 1, TRUE, fmat);
2283 for (i = 0; i < vectorSize(_particles); i++) {
2286 glUniform3fv(ppos, 1, pp.position);
2287 glUniform3fv(pdir, 1, pp.direction);
2291 updateColorRamp(node, &pp, cr);
2292 if (haveTexcoordRamp)
2293 updateTexCoordRamp(node, &pp, texcoord);
2294 if (node->_geometryType == GEOM_LINE) {
2295 float lpts[6], vel[3];
2296 vecnormalize3f(vel, pp.velocity);
2297 vecscale3f(&lpts[3], vel, .5f * node->particleSize.c[1]);
2298 vecscale3f(&lpts[0], vel, -.5f * node->particleSize.c[1]);
2299 FW_GL_VERTEX_POINTER(3, GL_FLOAT, 0, (
float*)lpts);
2306 extent6f_union_vec3f(estart6, pp.position);
2308 memcpy(node->_extent, estart6, 6 *
sizeof(
float));
2311 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, 0);
2312 FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER, 0);
2313 textureTransform_end();
2317 if (node->appearance) {
2319 POSSIBLE_PROTO_EXPANSION(
struct X3D_Appearance*, node->appearance, tmpA);
2320 if (tmpA->effects.n)
2321 fin_sibAffectors(X3D_NODE(tmpA), &tmpA->effects);
2326 finishedWithGlobalShader();
2328 p->material_twoSided = NULL;
2329 p->material_oneSided = NULL;
2330 p->userShaderNode = NULL;
2332 tg->RenderFuncs.shapenode = NULL;
2338 if (p->this_textureTransform) {
2339 p->this_textureTransform = NULL;
2341 FW_GL_MATRIX_MODE(GL_TEXTURE);
2342 FW_GL_LOAD_IDENTITY();
2343 FW_GL_MATRIX_MODE(GL_MODELVIEW);
2349 float gl_linewidth = tg->Mainloop.gl_linewidth;
2350 glLineWidth(gl_linewidth);
2352 p->appearanceProperties.pointSize = gl_linewidth;
2369 double mat[16], xyz[3];
2370 for (
int i = 0; i < vectorSize(_particles); i++) {
2379 FW_GL_PUSH_MATRIX();
2381 FW_GL_TRANSLATE_F(pp->position[0], pp->position[1], pp->position[2]);
2382 FW_GL_ROTATE_RADIANS(1.570796, 1, 0, 0);
2384 float yaw = atan2(pp->direction[1], pp->direction[0]) + 1.570796;
2385 float xydist = sqrt(pp->direction[1] * pp->direction[1] + pp->direction[0] * pp->direction[0]);
2386 float tilt = atan(pp->direction[2] / xydist);
2387 FW_GL_ROTATE_RADIANS(tilt, 1, 0, 0);
2388 FW_GL_ROTATE_RADIANS(yaw, 0, 1, 0);
2392 if (HH->_nodeType == NODE_HAnimPermuter) {
2394 if (pp->permutationIndex == -1)
2395 pp->permutationIndex = uniformRand() * HP->permutations.n;
2396 HP->index = pp->permutationIndex;
2397 render_node(X3D_NODE(HP));
2401 for (
int j = 0; j < 2; j++) {
2403 HM[j]->transitionStart = pp->transitionStart[j];
2404 if(pp->_startTime[j] > 0.0)
2405 HM[j]->_startTime = pp->_startTime[j];
2406 if (HH->_lastMotionsEnabled.n == 0) {
2407 HH->_lastMotionsEnabled.p = malloc(2 *
sizeof(
int));
2408 HH->_lastMotionsEnabled.n = 2;
2410 HH->_lastMotionsEnabled.p[j] = pp->lastMotionsEnabled[j];
2415 HH->motionsEnabled.p[0] = TRUE;
2416 HH->motionsEnabled.p[1] = FALSE;
2421 HH->motionsEnabled.p[0] = FALSE;
2422 HH->motionsEnabled.p[1] = TRUE;
2427 printf(
"HH %p HM0 %p HM1 %p wt %f %f enabled %d %d\n", HH, HM0, HM1, HM0->transitionWeight, HM1->transitionWeight, HH->motionsEnabled.p[0], HH->motionsEnabled.p[1]);
2429 child_HAnimHumanoid(HH);
2431 for (
int j = 0; j < 2; j++) {
2432 pp->transitionStart[j] = HM[j]->transitionStart;
2433 pp->lastMotionsEnabled[j] = HH->_lastMotionsEnabled.p[j] ;
2434 pp->_startTime[j] = HM[j]->_startTime;
2457 ttglobal tg = gglobal();
2464 tg->RenderFuncs.last_texture_type = NOTEXTURE;
2465 tg->RenderFuncs.shapenode = node;
2467 if (renderstate()->render_depth) {
2468 if (node->castShadow) {
2469 child_geom_particle_shadow(node);
2470 PRINT_GL_ERROR_IF_ANY(
"child_shape depth end");
2476 prep_BBox((
struct BBoxFields*)&node->bboxCenter);
2480 initialize_front_and_back_material_params();
2482 if (renderstate()->render_blend == (node->_renderFlags & VF_Blend)) {
2486 int i,j,k,maxparticles;
2494 dtime = (float)(ttime - node->_lasttime);
2501 _particles = node->_particles;
2502 maxparticles = min(node->maxParticles,10000);
2503 for(i=0,j=0;i<vectorSize(_particles);i++){
2506 if(pp.age < pp.lifespan){
2507 vector_set(
particle,_particles,j,pp);
2513 for(k=0;k<node->physics.n;k++){
2514 switch(node->physics.p[k]->_nodeType){
2515 case NODE_WindPhysicsModel:
2516 prep_windphysics(node->physics.p[k]);
break;
2522 for(i=0;i<vectorSize(_particles);i++){
2524 float positionChange[3];
2530 for(k=0;k<node->physics.n;k++){
2531 switch(node->physics.p[k]->_nodeType){
2532 case NODE_WindPhysicsModel:
2533 apply_windphysics(&pp,node->physics.p[k],dtime);
break;
2534 case NODE_ForcePhysicsModel:
2535 apply_forcephysics(&pp,node->physics.p[k],dtime);
break;
2536 case NODE_MapPhysicsModel:
2537 apply_mapphysics(&pp, node->physics.p[k], dtime);
break;
2538 case NODE_ResistancePhysicsModel:
2539 apply_resistancephysics(&pp, node->physics.p[k], dtime);
break;
2546 vecscale3f(positionChange,pp.velocity,.5f * dtime);
2548 for(k=0;k<node->physics.n;k++){
2549 switch(node->physics.p[k]->_nodeType){
2550 case NODE_BoundedPhysicsModel:
2551 apply_boundedphysics(&pp,node->physics.p[k],positionChange);
break;
2556 vecadd3f(pp.position,pp.position,positionChange);
2558 vector_set(
particle,_particles,i,pp);
2563 if(node->createParticles && _particles->n < maxparticles && node->emitter && emitter_loaded(node->emitter)){
2565 int n_per_frame, n_needed, n_this_frame;
2566 float particles_per_second, particles_per_frame;
2567 n_needed = maxparticles - _particles->n;
2572 particles_per_second = (float)node->maxParticles / (
float) node->particleLifetime;
2574 particles_per_frame = particles_per_second * dtime;
2575 particles_per_frame += node->_remainder;
2576 n_per_frame = (int)particles_per_frame;
2577 node->_remainder = particles_per_frame - (float)n_per_frame;
2578 n_this_frame = min(n_per_frame,n_needed);
2579 if(node->emitter->_nodeType == NODE_ExplosionEmitter)
2580 n_this_frame = n_needed;
2582 for(i=0;i<n_this_frame;i++,j++){
2585 vecset3f(pp.origin, 0.0f, 0.0f, 0.0f);
2587 pp.lifespan = node->particleLifetime * (1.0f + uniformRandCentered()*node->lifetimeVariation);
2588 veccopy2f(pp.size,node->particleSize.c);
2590 switch(node->emitter->_nodeType){
2591 case NODE_ConeEmitter: apply_ConeEmitter(&pp,node->emitter);
break;
2592 case NODE_ExplosionEmitter: apply_ExplosionEmitter(&pp,node->emitter);
2593 node->createParticles = FALSE;
2595 case NODE_PointEmitter: apply_PointEmitter(&pp,node->emitter);
break;
2596 case NODE_PolylineEmitter: apply_PolylineEmitter(&pp,node->emitter);
break;
2597 case NODE_SurfaceEmitter: apply_SurfaceEmitter(&pp,node->emitter);
break;
2598 case NODE_VolumeEmitter: apply_VolumeEmitter(&pp,node->emitter);
break;
2599 case NODE_MapEmitter: apply_MapEmitter(&pp, node->emitter);
break;
2604 vector_set(
particle,_particles,j,pp);
2608 if (node->_geometryType < GEOM_HANIM) {
2609 render_geom_particle(node, _particles);
2611 if (node->_geometryType == GEOM_HANIM) {
2612 render_hanim_particle(node, _particles);
2616 node->_lasttime = ttime;