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"
41 #include "Collision.h"
42 #include "quaternion.h"
44 #include "../opengl/Frustum.h"
45 #include "../opengl/Material.h"
46 #include "../opengl/OpenGL_Utils.h"
47 #include "../input/EAIHelpers.h"
50 #include "RenderFuncs.h"
51 #include "LinearAlgebra.h"
54 #include "Component_Shape.h"
55 #include "../opengl/Textures.h"
60 void *Component_ParticleSystems_constructor(){
65 void Component_ParticleSystems_init(
struct tComponent_ParticleSystems *t){
68 t->prv = Component_ParticleSystems_constructor();
74 void Component_ParticleSystems_clear(
struct tComponent_ParticleSystems *t){
250 srand((
unsigned int) TickTime());
253 rx = (float)ix/(
float)RAND_MAX;
256 float uniformRandCentered(){
257 return uniformRand() - .5f;
259 void circleRand2D(
float *xy){
263 xy[0] = 2.0f*(uniformRand() - .5f);
264 xy[1] = 2.0f*(uniformRand() - .5f);
265 radius2 = xy[0]*xy[0] + xy[1]*xy[1];
266 if(radius2 <= 1.0f)
break;
280 return (
float)(rxy[0]*.5);
283 void randomTriangleCoord_dug9_uneducated_guess(
float *p,
float* p1,
float *p2,
float *p3){
292 p[i] = b1*p1[i] + b2*p2[i] + (1.0f - b1 - b2)*p3[i];
295 void randomTriangleCoord(
float *p,
float* p1,
float *p2,
float *p3){
298 float r1, r2, sqr1,sqr2;
304 p[i] = (1.0f - sqr1)*p1[i] + (sqr1*(1.0f - sqr2))*p2[i] + (r2*sqr1)*p3[i];
308 void randomPoint3D(
float *xyz){
310 xyz[0] = (uniformRand() - .5f);
311 xyz[1] = (uniformRand() - .5f);
312 xyz[2] = (uniformRand() - .5f);
314 void randomDirection(
float *xyz){
325 radius3 = xyz[0]*xyz[0] + xyz[1]*xyz[1] + xyz[2]*xyz[2];
326 if(radius3 <= 1.0f && radius3 > 0.0000001f){
329 vecscale3f(xyz,xyz,1.0f/sqrtf(radius3));
359 } geomtype_table [] = {
362 {
"POINT",GEOM_POINT},
363 {
"SPRITE",GEOM_SPRITE},
364 {
"TRIANGLE",GEOM_TRIANGLE},
365 {
"GEOMETRY",GEOM_GEOMETRY},
368 int lookup_geomtype(
const char *name){
372 if(geomtype_table[i].name == NULL)
break;
373 if(!strcmp(geomtype_table[i].name,name)){
374 iret = geomtype_table[i].type;
382 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,};
383 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,};
384 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};
386 void compile_Shape (
struct X3D_Shape *node);
389 int i,j, maxparticles;
393 ConsoleMessage(
"compile_particlesystem\n");
397 node->_geometryType = lookup_geomtype(node->geometryType->strptr);
398 if(node->_tris == NULL){
399 node->_tris = MALLOC(
void *,18 *
sizeof(
float));
402 vertices = (
float*)(node->_tris);
406 vert0 = &quadtris[i*3];
407 vert = &vertices[i*3];
408 vert[0] = vert0[0]*node->particleSize.c[0];
409 vert[1] = vert0[1]*node->particleSize.c[1];
412 if(node->texCoordRamp){
415 n = node->texCoordKey.n;
422 node->_ttex = MALLOC(
void *,mt*2*
sizeof(
float));
424 node->_ltex = MALLOC(
void *,ml*2*
sizeof(
float));
425 if(tc->point.n == mq){
431 ttex = (
float*)node->_ttex;
434 for(j=0,k=0;j<4;j++,k++){
435 float *p = (
float*)(
float *)&tc->point.p[i*4 + j];
436 veccopy2f(&ttex[(i*6 + k)*2],p);
438 veccopy2f(&ttex[(i*6 + 5)*2],p);
442 veccopy2f(&ttex[(i*6 + k)*2],p);
446 if(0)
for(i=0;i<n;i++){
448 printf(
"%f %f,",ttex[(i*6 + j)*2 +0],ttex[(i*6 + j)*2 +1]);
455 ltex = (
float*)node->_ltex;
462 p[1] = min(sf->c[1],.9999f);
463 veccopy2f(<ex[(i*2 + j)*2],p);
468 if(tc->point.n == ml){
472 ltex = (
float*)node->_ltex;
479 p[1] = min(sf->c[1],.9999f);
480 veccopy2f(<ex[(i*2 + j)*2],p);
483 if(0)
for(i=0;i<n;i++){
484 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]);
487 ttex = (
float*)node->_ttex;
491 p = (
float*)(
float *)&tc->point.p[j*2 + 0];
492 veccopy2f(&ttex[(i*6 + 0)*2],p);
493 veccopy2f(&ttex[(i*6 + 5)*2],p);
494 p = (
float*)(
float *)&tc->point.p[j*2 + 1];
495 veccopy2f(&ttex[(i*6 + 1)*2],p);
497 j = j == n ? j - 1 : j;
498 p = (
float*)(
float *)&tc->point.p[j*2 + 1];
499 veccopy2f(&ttex[(i*6 + 2)*2],p);
500 veccopy2f(&ttex[(i*6 + 3)*2],p);
501 p = (
float*)(
float *)&tc->point.p[j*2 + 0];
502 veccopy2f(&ttex[(i*6 + 4)*2],p);
506 maxparticles = min(node->maxParticles,10000);
507 if(node->_particles == NULL)
508 node->_particles = newVector(
particle,maxparticles);
509 _particles = node->_particles;
510 if(_particles->allocn < maxparticles) {
512 _particles->data = realloc(_particles->data,maxparticles);
513 _particles->allocn = maxparticles;
515 node->_lasttime = TickTime();
517 node->isActive = TRUE;
524 void prep_windphysics(
struct X3D_Node *physics){
528 speed = px->speed * (1.0f + uniformRandCentered()*px->gustiness);
529 px->_frameSpeed = speed;
531 void apply_windphysics(
particle *pp,
struct X3D_Node *physics,
float dtime){
534 if(px->enabled && pp->mass != 0.0f){
537 float turbdir[3], pdir[3],acceleration[3], v2[3];
538 speed = px->_frameSpeed;
539 pressure = powf(10.0f,2.0f*log10f(speed)) * .64615f;
540 force = pressure * pp->surfaceArea;
541 randomDirection(turbdir);
542 vecscale3f(turbdir,turbdir,px->turbulence);
543 vecadd3f(pdir,px->direction.c,turbdir);
544 vecnormalize3f(pdir,pdir);
545 vecscale3f(pdir,pdir,force);
547 vecscale3f(acceleration,pdir,1.0f/pp->mass);
548 vecscale3f(v2,acceleration,dtime);
549 vecadd3f(pp->velocity,pp->velocity,v2);
553 int intersect_polyrep(
struct X3D_Node *node,
float *p1,
float *p2,
float *nearest,
float *normal);
555 void compile_geometry(
struct X3D_Node *gnode){
558 switch(gnode->_nodeType){
559 case NODE_IndexedFaceSet:
562 COMPILE_POLY_IF_REQUIRED (node->coord, node->fogCoord, node->color, node->normal, node->texCoord)
570 int intersect_geometry(
struct X3D_Node *gnode,
float *p1,
float *p2,
float *nearest,
float *normal){
574 switch(gnode->_nodeType){
575 case NODE_IndexedFaceSet:
576 iret = intersect_polyrep(gnode,p1,p2,nearest,normal);
583 void apply_boundedphysics(
particle *pp,
struct X3D_Node *physics,
float *positionChange){
585 if(px->enabled && px->geometry ) {
590 float pos1[3], pos2[3], pnearest[3],normal[3], delta[3];
595 if(NODE_NEEDS_COMPILING)
596 compile_geometry(node);
601 veccopy3f(pos1,pp->origin);
603 vecadd3f(pos2,pp->position,positionChange);
610 nintersections = intersect_geometry(px->geometry,pos1,pos2,pnearest,normal);
611 if(nintersections > 0){
612 float d[3], r[3], rn[3], rd[3], n[3], ddotnn[3], orthogn[3], orthogn2[3];
613 float ddotn, speed, dlengthi,dlength;
614 vecdif3f(delta,pos2,pos1);
615 dlength = veclength3f(delta);
634 vecdif3f(d,pnearest,pos1);
635 dlengthi = veclength3f(d);
636 vecnormalize3f(n,normal);
637 ddotn = vecdot3f(d,n);
639 vecscale3f(ddotnn,n,ddotn);
640 vecdif3f(orthogn,d,ddotnn);
641 vecscale3f(orthogn2,orthogn,2.0f);
642 vecdif3f(r,d,orthogn2);
643 vecscale3f(r,r,-1.0f);
644 vecnormalize3f(rn,r);
647 speed = veclength3f(pp->velocity);
648 vecscale3f(pp->velocity,rn,speed);
650 vecscale3f(rd,rn,dlength - dlengthi);
651 vecadd3f(pp->position,pnearest,rd);
652 vecscale3f(positionChange,positionChange,0.0f);
653 veccopy3f(pos1,pnearest);
654 veccopy3f(pp->origin,pos1);
655 veccopy3f(pos2,pp->position);
656 if(0) pp->age = 1000.0f;
666 void apply_forcephysics(
particle *pp,
struct X3D_Node *physics,
float dtime){
674 if(px->enabled && pp->mass != 0.0f){
675 float acceleration[3], v2[3];
676 vecscale3f(acceleration,px->force.c,1.0f/pp->mass);
677 vecscale3f(v2,acceleration,dtime);
678 vecadd3f(pp->velocity,pp->velocity,v2);
688 float direction[3], tilt, azimuth, speed;
694 float orthog1[3],orthog2[3];
696 vecnormalize3f(direction,e->direction.c);
697 amin = min(min(fabsf(direction[0]),fabsf(direction[1])),fabsf(direction[2]));
700 if(fabsf(direction[i]) == amin){
705 for(i=0;i<3;i++) orthog1[i] = 0.0f;
706 orthog1[imin] = 1.0f;
709 veccross3f(orthog2,direction,orthog1);
712 veccross3f(orthog1,direction,orthog2);
728 float az[3],az1[3],az2[3],ctilt,stilt,caz,saz;
729 tilt = uniformRand()*e->angle;
732 azimuth = uniformRand()*2.0f*(float)PI;
735 vecscale3f(az1,orthog1,caz);
736 vecscale3f(az2,orthog2,saz);
737 vecadd3f(az,az1,az2);
739 vecscale3f(az,az,stilt);
741 vecscale3f(direction,direction,ctilt);
743 vecadd3f(direction,direction,az);
752 float xy[2], orx[3],ory[3], orthog[3];
755 vecscale3f(orx,orthog1,xy[0]);
756 vecscale3f(ory,orthog2,xy[1]);
757 vecadd3f(orthog,orx,ory);
758 vecscale3f(orthog,orthog,sinf(e->angle));
759 vecscale3f(direction,direction,cosf(e->angle));
761 vecadd3f(direction,orthog,direction);
763 vecnormalize3f(direction,direction);
767 memcpy(pp->position,e->position.c,3*
sizeof(
float));
768 speed = e->speed*(1.0f + uniformRandCentered()*e->variation);
769 vecscale3f(pp->velocity,direction,speed);
770 pp->mass = e->mass*(1.0f + uniformRandCentered()*e->variation);
771 pp->surfaceArea = e->surfaceArea*(1.0f + uniformRandCentered()*e->variation);
779 float direction[3], speed;
780 memcpy(pp->position,e->position.c,3*
sizeof(
float));
781 randomDirection(direction);
782 speed = e->speed*(1.0f + uniformRandCentered()*e->variation);
783 vecscale3f(pp->velocity,direction,speed);
784 pp->mass = e->mass*(1.0f + uniformRandCentered()*e->variation);
785 pp->surfaceArea = e->surfaceArea*(1.0f + uniformRandCentered()*e->variation);
791 float direction[3], speed;
792 memcpy(pp->position,e->position.c,3*
sizeof(
float));
793 if(veclength3f(e->direction.c) < .00001){
794 randomDirection(direction);
796 memcpy(direction,e->direction.c,3*
sizeof(
float));
797 vecnormalize3f(direction,direction);
799 speed = e->speed*(1.0f + uniformRandCentered()*e->variation);
800 vecscale3f(pp->velocity,direction,speed);
801 pp->mass = e->mass*(1.0f + uniformRandCentered()*e->variation);
802 pp->surfaceArea = e->surfaceArea*(1.0f + uniformRandCentered()*e->variation);
806 POLYLINEEMITTER_METHODA = 1,
807 POLYLINEEMITTER_METHODB = 2,
809 void compile_PolylineEmitter(
struct X3D_Node *node){
813 e->_method = POLYLINEEMITTER_METHODB;
814 if(e->coord && e->coordIndex.n > 1){
816 int i,k,ind, n,nseg = 0;
820 segs = MALLOC(
void*,2*3*
sizeof(
float) *n*2 );
823 for(i=0;i<e->coordIndex.n;i++){
824 ind = e->coordIndex.p[i];
829 pts[k] = (
float*)&coord->point.p[ind];
832 veccopy3f(&segs[(nseg*2 +0)*3],pts[0]);
833 veccopy3f(&segs[(nseg*2 +1)*3],pts[1]);
842 if(e->_method == POLYLINEEMITTER_METHODB){
844 float *portions, totaldist, dist, delta[3];
845 portions = MALLOC(
float *,e->_nseg *
sizeof(
float));
846 e->_portions = portions;
848 for(i=0;i<e->_nseg;i++){
849 vecdif3f(delta,&segs[(i*2 + 1)*3],&segs[(i*2 + 0)*3]);
850 dist = veclength3f(delta);
855 for(i=0;i<e->_nseg;i++){
856 portions[i] = portions[i]/totaldist;
864 float direction[3], speed;
870 if(NODE_NEEDS_COMPILING)
871 compile_PolylineEmitter(node);
872 memset(pp->position,0,3*
sizeof(
float));
873 if(e->_method == POLYLINEEMITTER_METHODA && e->_nseg){
874 float *segs, delta[3], pos[3];
876 int iseg = (int) floorf(uniformRand() * (float)e->_nseg);
878 float fraction = uniformRand();
879 segs = (
float *)e->_segs;
880 vecdif3f(delta,&segs[(iseg*2 + 1)*3],&segs[(iseg*2 + 0)*3]);
881 vecscale3f(delta,delta,fraction);
882 vecadd3f(pos,&segs[(iseg*2 + 0)*3],delta);
883 veccopy3f(pp->position,pos);
885 if(e->_method == POLYLINEEMITTER_METHODB && e->_nseg){
888 float cumulative, fraction, *portions, *segs, delta[3], pos[3], segfraction;
889 fraction = uniformRand();
890 portions = (
float*)e->_portions;
892 for(i=0;i<e->_nseg;i++){
893 cumulative +=portions[i];
894 if(cumulative > fraction){
895 segfraction = (cumulative - fraction) / portions[i];
896 segs = (
float *)e->_segs;
897 vecdif3f(delta,&segs[(i*2 + 1)*3],&segs[(i*2 + 0)*3]);
898 vecscale3f(delta,delta,segfraction);
899 vecadd3f(pos,&segs[(i*2 + 0)*3],delta);
900 veccopy3f(pp->position,pos);
908 if(veclength3f(e->direction.c) < .00001){
909 randomDirection(direction);
911 memcpy(direction,e->direction.c,3*
sizeof(
float));
912 vecnormalize3f(direction,direction);
914 speed = e->speed*(1.0f + uniformRandCentered()*e->variation);
915 vecscale3f(pp->velocity,direction,speed);
916 pp->mass = e->mass*(1.0f + uniformRandCentered()*e->variation);
917 pp->surfaceArea = e->surfaceArea*(1.0f + uniformRandCentered()*e->variation);
920 int getPolyrepTriangleCount(
struct X3D_Node *node);
921 int getPolyrepTriangleByIndex(
struct X3D_Node *node,
int index,
float *v1,
float *v2,
float *v3);
927 node = e->surface ? e->surface : e->geometry;
928 if(NODE_NEEDS_COMPILING){
929 compile_geometry(X3D_NODE(node));
935 float xyz[3], v1[3],v2[3],v3[3],e1[3],e2[3], normal[3], direction[3];
937 fraction = uniformRand();
938 ntri = getPolyrepTriangleCount(node);
940 index = (int)floorf(fraction * (
float)(ntri-1));
941 getPolyrepTriangleByIndex(node,index,v1,v2,v3);
942 randomTriangleCoord(xyz,v1,v2,v3);
945 veccross3f(normal,e1,e2);
946 vecnormalize3f(direction,normal);
951 memcpy(pp->position,xyz,3*
sizeof(
float));
952 speed = e->speed*(1.0f + uniformRandCentered()*e->variation);
953 vecscale3f(pp->velocity,direction,speed);
954 pp->mass = e->mass*(1.0f + uniformRandCentered()*e->variation);
955 pp->surfaceArea = e->surfaceArea*(1.0f + uniformRandCentered()*e->variation);
961 if(!e->_ifs && e->coord){
963 ifs = createNewX3DNode0(NODE_IndexedFaceSet);
964 ifs->coord = e->coord;
965 ifs->coordIndex = e->coordIndex;
966 compile_geometry(X3D_NODE(ifs));
970 int nint, i, isInside;
971 float xyz[3], plumb[3], nearest[3], normal[3];
972 float direction[3], speed;
979 xyz[0] *= ifs->EXTENT_MAX_X - ifs->EXTENT_MIN_X;
980 xyz[1] *= ifs->EXTENT_MAX_Y - ifs->EXTENT_MIN_Y;
981 xyz[2] *= ifs->EXTENT_MAX_Z - ifs->EXTENT_MIN_Z;
982 veccopy3f(plumb,xyz);
983 plumb[2] = ifs->EXTENT_MIN_Z - 1.0f;
984 nint = intersect_geometry(e->_ifs,xyz,plumb,nearest,normal);
985 nint = abs(nint) % 2;
992 vecscale3f(xyz,xyz,0.0f);
994 memcpy(pp->position,xyz,3*
sizeof(
float));
995 if(veclength3f(e->direction.c) < .00001){
996 randomDirection(direction);
998 memcpy(direction,e->direction.c,3*
sizeof(
float));
999 vecnormalize3f(direction,direction);
1001 speed = e->speed*(1.0f + uniformRandCentered()*e->variation);
1002 vecscale3f(pp->velocity,direction,speed);
1003 pp->mass = e->mass*(1.0f + uniformRandCentered()*e->variation);
1004 pp->surfaceArea = e->surfaceArea*(1.0f + uniformRandCentered()*e->variation);
1008 int j,k,ifloor, iceil, found;
1009 float rgbaf[4], rgbac[4], rgba[4], fraclife;
1011 fraclife = pp->age / pp->lifespan;
1012 for(j=0;j<node->colorKey.n;j++){
1013 if(node->colorKey.p[j] <= fraclife && node->colorKey.p[j+1] > fraclife){
1021 float spread, fraction;
1024 switch(node->colorRamp->_nodeType){
1025 case NODE_ColorRGBA: crgba = ((
struct X3D_ColorRGBA *)node->colorRamp)->color.p;
break;
1026 case NODE_Color: crgb = ((
struct X3D_Color *)node->colorRamp)->color.p;
break;
1030 spread = node->colorKey.p[iceil] - node->colorKey.p[ifloor];
1031 fraction = (fraclife - node->colorKey.p[ifloor]) / spread;
1033 memcpy(rgbaf,&crgba[ifloor],
sizeof(
struct SFColorRGBA));
1034 memcpy(rgbac,&crgba[iceil],
sizeof(
struct SFColorRGBA));
1036 memcpy(rgbaf,&crgb[ifloor],
sizeof(
struct SFColor));
1038 memcpy(rgbac,&crgb[iceil],
sizeof(
struct SFColor));
1042 rgba[k] = (1.0f - fraction)*rgbaf[k] + fraction*rgbac[k];
1044 glUniform4fv(cramp,1,rgba);
1050 int found, ifloor,j;
1051 float fraclife, fracKey;
1054 fraclife = pp->age / pp->lifespan;
1055 fracKey = 1.0f / (float)(node->texCoordKey.n);
1057 fraclife -= fracKey;
1060 for(j=0;j<node->texCoordKey.n;j++){
1061 if( node->texCoordKey.p[j] > fraclife){
1068 switch(node->_geometryType){
1070 FW_GL_TEXCOORD_POINTER (2,GL_FLOAT,0,(
float *)&texcoord[ifloor*2*2],0);
1075 FW_GL_TEXCOORD_POINTER (2,GL_FLOAT,0,(
float *)&texcoord[ifloor*2*6],0);
1083 void reallyDrawOnce();
1085 GLfloat linepts [6] = {-.5f,0.f,0.f, .5f,0.f,0.f};
1086 ushort lineindices[2] = {0,1};
1087 int getImageChannelCountFromTTI(
struct X3D_Node *appearanceNode );
1088 void update_effect_uniforms();
1103 if (renderstate()->render_blend == (node->_renderFlags & VF_Blend)) {
1106 int i,j,k,maxparticles;
1114 int allowsTexcoordRamp = FALSE;
1115 float *texcoord = NULL;
1116 GLint ppos, cr, gtype;
1117 int haveColorRamp,haveTexcoordRamp;
1123 dtime = (float)(ttime - node->_lasttime);
1130 _particles = node->_particles;
1131 maxparticles = min(node->maxParticles,10000);
1132 for(i=0,j=0;i<vectorSize(_particles);i++){
1135 if(pp.age < pp.lifespan){
1136 vector_set(
particle,_particles,j,pp);
1142 for(k=0;k<node->physics.n;k++){
1143 switch(node->physics.p[k]->_nodeType){
1144 case NODE_WindPhysicsModel:
1145 prep_windphysics(node->physics.p[k]);
break;
1151 for(i=0;i<vectorSize(_particles);i++){
1153 float positionChange[3];
1159 for(k=0;k<node->physics.n;k++){
1160 switch(node->physics.p[k]->_nodeType){
1161 case NODE_WindPhysicsModel:
1162 apply_windphysics(&pp,node->physics.p[k],dtime);
break;
1163 case NODE_ForcePhysicsModel:
1164 apply_forcephysics(&pp,node->physics.p[k],dtime);
break;
1171 vecscale3f(positionChange,pp.velocity,.5f * dtime);
1173 for(k=0;k<node->physics.n;k++){
1174 switch(node->physics.p[k]->_nodeType){
1175 case NODE_BoundedPhysicsModel:
1176 apply_boundedphysics(&pp,node->physics.p[k],positionChange);
break;
1181 vecadd3f(pp.position,pp.position,positionChange);
1183 vector_set(
particle,_particles,i,pp);
1188 if(node->createParticles && _particles->n < maxparticles){
1190 int n_per_frame, n_needed, n_this_frame;
1191 float particles_per_second, particles_per_frame;
1192 n_needed = maxparticles - _particles->n;
1197 particles_per_second = (float)node->maxParticles / (
float) node->particleLifetime;
1199 particles_per_frame = particles_per_second * dtime;
1200 particles_per_frame += node->_remainder;
1201 n_per_frame = (int)particles_per_frame;
1202 node->_remainder = particles_per_frame - (float)n_per_frame;
1203 n_this_frame = min(n_per_frame,n_needed);
1204 if(node->emitter->_nodeType == NODE_ExplosionEmitter)
1205 n_this_frame = n_needed;
1207 for(i=0;i<n_this_frame;i++,j++){
1210 memset(pp.origin,0,
sizeof(
float)*3);
1211 pp.lifespan = node->particleLifetime * (1.0f + uniformRandCentered()*node->lifetimeVariation);
1212 memcpy(pp.size,node->particleSize.c,2*
sizeof(
float));
1214 switch(node->emitter->_nodeType){
1215 case NODE_ConeEmitter: apply_ConeEmitter(&pp,node->emitter);
break;
1216 case NODE_ExplosionEmitter: apply_ExplosionEmitter(&pp,node->emitter);
1217 node->createParticles = FALSE;
1219 case NODE_PointEmitter: apply_PointEmitter(&pp,node->emitter);
break;
1220 case NODE_PolylineEmitter: apply_PolylineEmitter(&pp,node->emitter);
break;
1221 case NODE_SurfaceEmitter: apply_SurfaceEmitter(&pp,node->emitter);
break;
1222 case NODE_VolumeEmitter: apply_VolumeEmitter(&pp,node->emitter);
break;
1227 vector_set(
particle,_particles,j,pp);
1240 RENDER_MATERIAL_SUBNODES(node->appearance);
1244 if (p->material_oneSided != NULL) {
1245 memcpy (&p->appearanceProperties.fw_FrontMaterial, p->material_oneSided->_verifiedColor.p, sizeof (
struct fw_MaterialParameters));
1246 memcpy (&p->appearanceProperties.fw_BackMaterial, p->material_oneSided->_verifiedColor.p, sizeof (
struct fw_MaterialParameters));
1248 memcpy(p->appearanceProperties.emissionColour,p->material_oneSided->_verifiedColor.p, 3*
sizeof(
float));
1250 }
else if (p->material_twoSided != NULL) {
1251 memcpy (&p->appearanceProperties.fw_FrontMaterial, p->material_twoSided->_verifiedFrontColor.p, sizeof (
struct fw_MaterialParameters));
1252 memcpy (&p->appearanceProperties.fw_BackMaterial, p->material_twoSided->_verifiedBackColor.p, sizeof (
struct fw_MaterialParameters));
1254 memcpy(p->appearanceProperties.emissionColour,p->material_twoSided->_verifiedFrontColor.p, 3*
sizeof(
float));
1263 POSSIBLE_PROTO_EXPANSION(
struct X3D_Node *, node->geometry,tmpNG);
1265 shader_requirements.base = node->_shaderflags_base;
1266 shader_requirements.effects = node->_shaderflags_effects;
1267 shader_requirements.usershaders = node->_shaderflags_usershaders;
1268 isUserShader = shader_requirements.usershaders ? TRUE : FALSE;
1300 channels = getImageChannelCountFromTTI(node->appearance);
1303 shader_requirements.base |= MAT_FIRST;
1305 if(shader_requirements.base & COLOUR_MATERIAL_SHADER){
1310 shader_requirements.base |= CPV_REPLACE_PRIOR;
1313 if(channels && (channels == 3 || channels == 4) && modulation < 2)
1314 shader_requirements.base |= TEXTURE_REPLACE_PRIOR;
1317 if(channels && (channels == 2 || channels == 4) && modulation == 0)
1318 shader_requirements.base |= TEXALPHA_REPLACE_PRIOR;
1324 shader_requirements.base |= getShaderFlags().base;
1325 shader_requirements.effects |= getShaderFlags().effects;
1330 shader_requirements.base |= PARTICLE_SHADER;
1332 shader_requirements.base |= HAVE_UNLIT_COLOR;
1335 scap = getMyShaders(shader_requirements);
1336 enableGlobalShader(scap);
1340 if (tmpNG && tmpNG->_intern) {
1341 if (tmpNG->_intern->tcoordtype == NODE_TextureCoordinateGenerator) {
1342 getAppearanceProperties()->texCoordGeneratorType = tmpNG->_intern->texgentype;
1348 #ifdef ALLOW_USERSHADERS
1349 if(isUserShader && p->userShaderNode){
1353 switch (p->userShaderNode->_nodeType) {
1354 case NODE_ComposedShader:
1355 if (X3D_COMPOSEDSHADER(p->userShaderNode)->isValid) {
1356 if (!X3D_COMPOSEDSHADER(p->userShaderNode)->_initialized) {
1357 sendInitialFieldsToShader(p->userShaderNode);
1361 case NODE_ProgramShader:
1362 if (X3D_PROGRAMSHADER(p->userShaderNode)->isValid) {
1363 if (!X3D_PROGRAMSHADER(p->userShaderNode)->_initialized) {
1364 sendInitialFieldsToShader(p->userShaderNode);
1369 case NODE_PackagedShader:
1370 if (X3D_PACKAGEDSHADER(p->userShaderNode)->isValid) {
1371 if (!X3D_PACKAGEDSHADER(p->userShaderNode)->_initialized) {
1372 sendInitialFieldsToShader(p->userShaderNode);
1379 #endif //ALLOW_USERSHADERS
1381 if(shader_requirements.effects){
1382 update_effect_uniforms();
1389 textureTransform_start();
1392 allowsTexcoordRamp = FALSE;
1394 switch(node->_geometryType){
1397 FW_GL_VERTEX_POINTER (3,GL_FLOAT,0,(
float *)linepts);
1398 sendElementsToGPU(GL_LINES,2,(ushort *)lineindices);
1399 texcoord = (
float*)node->_ltex;
1400 allowsTexcoordRamp = TRUE;
1406 memset(point,0,3*
sizeof(
float));
1407 FW_GL_VERTEX_POINTER (3,GL_FLOAT,0,(GLfloat *)point);
1408 sendArraysToGPU (GL_POINTS, 0, 1);
1414 FW_GL_VERTEX_POINTER (3,GL_FLOAT,0,(GLfloat *)node->_tris);
1415 FW_GL_NORMAL_POINTER (GL_FLOAT,0,twotrisnorms);
1416 sendArraysToGPU (GL_TRIANGLES, 0, 6);
1417 texcoord = (
float*)node->_ttex;
1418 allowsTexcoordRamp = TRUE;
1424 FW_GL_VERTEX_POINTER (3,GL_FLOAT,0,(GLfloat *)node->_tris);
1425 FW_GL_NORMAL_POINTER (GL_FLOAT,0,twotrisnorms);
1426 sendArraysToGPU (GL_TRIANGLES, 0, 6);
1432 FW_GL_VERTEX_POINTER (3,GL_FLOAT,0,(GLfloat *)node->_tris);
1433 FW_GL_NORMAL_POINTER (GL_FLOAT,0,twotrisnorms);
1434 sendArraysToGPU (GL_TRIANGLES, 0, 6);
1435 texcoord = (
float*)node->_ttex;
1436 allowsTexcoordRamp = TRUE;
1440 render_node(node->geometry);
1446 ppos = GET_UNIFORM(scap->myShaderProgram,
"particlePosition");
1447 cr = GET_UNIFORM(scap->myShaderProgram,
"fw_UnlitColor");
1448 gtype = GET_UNIFORM(scap->myShaderProgram,
"fw_ParticleGeomType");
1449 glUniform1i(gtype,node->_geometryType);
1451 haveColorRamp = node->colorRamp ? TRUE : FALSE;
1452 haveColorRamp = haveColorRamp && cr > -1;
1453 haveTexcoordRamp = node->texCoordRamp ? TRUE : FALSE;
1454 haveTexcoordRamp = haveTexcoordRamp && allowsTexcoordRamp && texcoord;
1456 for(i=0;i<vectorSize(_particles);i++){
1459 glUniform3fv(ppos,1,pp.position);
1461 updateColorRamp(node,&pp,cr);
1462 if(haveTexcoordRamp)
1463 updateTexCoordRamp(node,&pp,texcoord);
1464 if(node->_geometryType == GEOM_LINE){
1465 float lpts[6], vel[3];
1466 vecnormalize3f(vel,pp.velocity);
1467 vecscale3f(&lpts[3],vel,.5f*node->particleSize.c[1]);
1468 vecscale3f(&lpts[0],vel,-.5f*node->particleSize.c[1]);
1469 FW_GL_VERTEX_POINTER (3,GL_FLOAT,0,(
float *)lpts);
1476 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, 0);
1477 FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER, 0);
1478 textureTransform_end();
1482 if(node->appearance){
1484 POSSIBLE_PROTO_EXPANSION(
struct X3D_Appearance *,node->appearance,tmpA);
1486 fin_sibAffectors(X3D_NODE(tmpA),&tmpA->effects);
1491 finishedWithGlobalShader();
1493 p->material_twoSided = NULL;
1494 p->material_oneSided = NULL;
1495 p->userShaderNode = NULL;
1497 tg->RenderFuncs.shapenode = NULL;
1503 if (p->this_textureTransform) {
1504 p->this_textureTransform = NULL;
1506 FW_GL_MATRIX_MODE(GL_TEXTURE);
1507 FW_GL_LOAD_IDENTITY();
1508 FW_GL_MATRIX_MODE(GL_MODELVIEW);
1514 float gl_linewidth = tg->Mainloop.gl_linewidth;
1515 glLineWidth(gl_linewidth);
1517 p->appearanceProperties.pointSize = gl_linewidth;
1529 node->_lasttime = ttime;