Example #1
0
void render(NODE * node, Vector camPos)
{
	Mtx tmp;
	if(!node->isRenderable()) return;//Skip non-renderable nodes such as empty nodes, regions or lights
	if(node->flags & F_Visible)//Is it visible?
	{
		//Set matrices
		Mtx aux, inv;
		GX_ClearVtxDesc();
		node->absMtx(modelM);
		char msg[64];

		guMtxConcat(view, modelM, modelview);
		GX_LoadPosMtxImm(modelview, GX_PNMTX0);//Load model view matrix
		guMtxInverse(modelview, tmp);
		guMtxTranspose(tmp,inv);
		GX_LoadNrmMtxImm(inv, GX_PNMTX0);//Load normal matrix

		//TODO: Better lighting (multiple lights)
		std::vector<LIGHT*>::iterator light = mainRoot->getLights().begin();
		//if(light == mainRoot->getLights().end())
		//	REVConsole->write("LIGHT");
		GXLightObj lObj[8];
		u8 lightMask = 0, tmpLight = GX_LIGHT0;
		for(u8 i = 0;light != mainRoot->getLights().end(); ++light, ++i)
		{
			Vector lpos = (*light)->getPos();
			guVecMultiply(view, &lpos, &lpos);
			
			GX_InitLightPos(&lObj[i],lpos.x,lpos.y,lpos.z);
			GX_InitLightAttn(&lObj[i], 1.0f,0.0f,0.0f,1.0f,0.0f,0.0f);
			GX_InitLightSpot(&lObj[i],0.0f,GX_SP_OFF);
			GX_InitLightColor(&lObj[i],(*light)->clr);
			GX_LoadLightObj(&lObj[i],tmpLight);
			lightMask |= tmpLight;
			tmpLight *= 2;
		}
		//Render the node
		node->render(lightMask);
	}
}
Example #2
0
void glEnd(void) {
     
     GX_SetCullMode(GX_CULL_FRONT);

	Mtx mvi;
	Mtx mv;
	
//	Mtx inversemodelview;

	// load the modelview matrix into matrix memory
	guMtxConcat(view,model,modelview);
	GX_LoadPosMtxImm(modelview, GX_PNMTX0);

	//for normals first calculate normal matrix (thanks shagkur)
    guMtxInverse(modelview,mvi); 
    guMtxTranspose(mvi,modelview); 
    GX_LoadNrmMtxImm(modelview,GX_PNMTX0); //experimtal leave out (hmm works good?)


	//use global ambient light together with current material ambient and add emissive material color
	GXColor constcolor;
	constcolor.r = (gxcurrentmaterialambientcolor.r*gxglobalambientlightcolor.r) * 0xFF;
	constcolor.g = (gxcurrentmaterialambientcolor.g*gxglobalambientlightcolor.g) * 0xFF;
	constcolor.b = (gxcurrentmaterialambientcolor.b*gxglobalambientlightcolor.b) * 0xFF;
	constcolor.a = (gxcurrentmaterialambientcolor.a*gxglobalambientlightcolor.a) * 0xFF;
	GX_SetTevColor(GX_TEVREG0, constcolor);
	
	GXColor emiscolor;
	emiscolor.r = gxcurrentmaterialemissivecolor.r * 0xFF;
	emiscolor.g = gxcurrentmaterialemissivecolor.g * 0xFF;
	emiscolor.b = gxcurrentmaterialemissivecolor.b * 0xFF;
	emiscolor.a = gxcurrentmaterialemissivecolor.a * 0xFF;
	GX_SetTevColor(GX_TEVREG1, emiscolor);

	//first check if a lightdirtyflag is set (thanks ector) so we do not have to set up light every run
	//also usefull on matrices etc.

	//now set each light
	GXColor gxchanambient;
	gxchanambient.r = gxcurrentmaterialambientcolor.r;
	gxchanambient.g = gxcurrentmaterialambientcolor.g;
	gxchanambient.b = gxcurrentmaterialambientcolor.b;
	gxchanambient.a = gxcurrentmaterialambientcolor.a;
	
	GXColor gxchanspecular;
	gxchanspecular.r = gxcurrentmaterialspecularcolor.r;
	gxchanspecular.g = gxcurrentmaterialspecularcolor.g;
	gxchanspecular.b = gxcurrentmaterialspecularcolor.b;
	gxchanspecular.a = gxcurrentmaterialspecularcolor.a;	
	
	int lightcounter = 0;
	for (lightcounter =0; lightcounter < 4; lightcounter++){

		if(gxlightenabled[lightcounter]){ //when light is enabled

            //somewhere here an error happens?

            //Setup mat/light ambient color 
			gxchanambient.r = ((gxchanambient.r * gxlightambientcolor[lightcounter].r) * 0xFF);
			gxchanambient.g = ((gxchanambient.g * gxlightambientcolor[lightcounter].g) * 0xFF);
			gxchanambient.b = ((gxchanambient.b * gxlightambientcolor[lightcounter].b) * 0xFF);
			gxchanambient.a = ((gxchanambient.a * gxlightambientcolor[lightcounter].a) * 0xFF);
			GX_SetChanAmbColor(GX_COLOR0A0, gxchanambient ); 
			
			//Setup diffuse material color
			GXColor mdc;
			mdc.r = (gxcurrentmaterialdiffusecolor.r * 0xFF);
			mdc.g = (gxcurrentmaterialdiffusecolor.g * 0xFF);
			mdc.b = (gxcurrentmaterialdiffusecolor.b * 0xFF);
			mdc.a = (gxcurrentmaterialdiffusecolor.a * 0xFF);
			GX_SetChanMatColor(GX_COLOR0A0, mdc ); 
			
			//Setup specular material color
//			gxcurrentmaterialshininess *
			gxchanspecular.r = (gxchanspecular.r * gxlightspecularcolor[lightcounter].r) * 0xFF;
			gxchanspecular.g = (gxchanspecular.g * gxlightspecularcolor[lightcounter].g) * 0xFF;
			gxchanspecular.b = (gxchanspecular.b * gxlightspecularcolor[lightcounter].b) * 0xFF;
			gxchanspecular.a = (gxchanspecular.a * gxlightspecularcolor[lightcounter].a) * 0xFF;
			GX_SetChanMatColor(GX_COLOR1A1, gxchanspecular); // use red as test color

            //Setup light diffuse color
            GXColor ldc;
			ldc.r = gxlightdiffusecolor[lightcounter].r * 0xFF;
			ldc.g = gxlightdiffusecolor[lightcounter].g * 0xFF;
			ldc.b = gxlightdiffusecolor[lightcounter].b * 0xFF;
			ldc.a = gxlightdiffusecolor[lightcounter].a * 0xFF;
			GX_InitLightColor(&gxlight[lightcounter], ldc ); //move call to glend or init?;
            GX_InitLightColor(&gxlight[lightcounter+4], ldc ); //move call to glend or init?;

			//Setup light postion
			
			//check on w component when 1. light is positional
			//                     when 0. light is directional at infinite pos
			
			guVector lpos;
			guVector wpos;
            lpos.x = gxlightpos[lightcounter].x;
            lpos.y = gxlightpos[lightcounter].y;
            lpos.z = gxlightpos[lightcounter].z;
               
               
            if (gxlightpos[lightcounter].w == 0){
                guVecNormalize(&lpos);
                lpos.x *= BIG_NUMBER;
                lpos.y *= BIG_NUMBER;
                lpos.z *= BIG_NUMBER;
            }
            
			guVecMultiply(view,&lpos,&wpos);	   //light position should be transformed by world-to-view matrix (thanks h0lyRS)
			GX_InitLightPosv(&gxlight[lightcounter], &wpos); //feed corrected coord to light pos
			GX_InitLightPosv(&gxlight[lightcounter+4], &wpos); //feed corrected coord to light pos
		


            //Setup light direction (when w is 1 dan dir = 0,0,0
            guVector ldir;
            if (gxlightpos[lightcounter].w==0){ 
               //lpos.x = gxlightpos[lightcounter].x;
			   //lpos.y = gxlightpos[lightcounter].y;
               //lpos.z = gxlightpos[lightcounter].z;
                                                
               ldir.x = gxlightpos[lightcounter].x;
               ldir.y = gxlightpos[lightcounter].y;
               ldir.z = gxlightpos[lightcounter].z;
            }
            else
            {
                if (gxspotcutoff[lightcounter] != 180){ //if we have a spot light direction is needed
                   ldir.x = gxspotdirection[lightcounter].x;
                   ldir.y = gxspotdirection[lightcounter].y;
                   ldir.z = gxspotdirection[lightcounter].z;
                }
                else { 
                     ldir.x = 0;
                     ldir.y = 0;
                     ldir.z = -1;
               }
            }
            
            //guVecNormalize(&ldir);
            //ldir.x *= BIG_NUMBER;
            //ldir.y *= BIG_NUMBER;
            //ldir.z *= BIG_NUMBER;
            
            guMtxInverse(view,mvi);
            guMtxTranspose(mvi,view);
            
            guVecMultiply(view,&ldir,&ldir); //and direction should be transformed by inv-transposed of world-to-view (thanks h0lyRS)
            
            GX_InitLightDir(&gxlight[lightcounter], ldir.x, ldir.y, ldir.z); //feed corrected coord to light dir
            GX_InitLightDir(&gxlight[lightcounter+4], ldir.x, ldir.y, ldir.z); //feed corrected coord to light dir
           
            
			if (gxspotcutoff[lightcounter] != 180){
               //Setup specular light (only for spotlight when GL_SPOT_CUTOFF <> 180)
			   //make this line optional? If on it disturbs diffuse light?
               guVector sdir;
               sdir.x = gxspotdirection[lightcounter].x;
               sdir.y = gxspotdirection[lightcounter].y;
               sdir.z = gxspotdirection[lightcounter].z;
               //guVecNormalize(&sdir);
                     
               //sdir.x *= BIG_NUMBER;
               //sdir.y *= BIG_NUMBER;
               //sdir.z *= BIG_NUMBER;       
                              
			   guVecMultiply(view,&sdir,&sdir);
			   
			   guVector light_dir;
			   guVecSub(&sdir, &lpos, &light_dir);
			   
			   GX_TestInitSpecularDir(&gxlight[lightcounter], light_dir.x, light_dir.y, light_dir.z); //needed to enable specular light
               GX_TestInitSpecularDir(&gxlight[lightcounter+4], light_dir.x, light_dir.y, light_dir.z); //needed to enable specular light
               
            };
            
            
            //this calls:
            // #define GX_InitLightShininess(lobj, shininess) (GX_InitLightAttn(lobj, 0.0F, 0.0F, 1.0F, (shininess)/2.0F, 0.0F, 1.0F-(shininess)/2.0F ))

            //Setup distance attinuation (opengl vs gx differences?)
			//GX_InitLightDistAttn(&gxlight[lightcounter], 100.0f, gxspotexponent[lightcounter], GX_DA_GENTLE); //gxspotexponent was 0.5f
                                                     //ref_dist, bright, dist func  
            //k0 = 1.0;                   
            //k1 = 0.5f*(1.0f-ref_brite)/(ref_brite*ref_dist);
 			//k2 = 0.5f*(1.0f-ref_brite)/(ref_brite*ref_dist*ref_dist); or 0.0f;                  
                    
                    
                     
            //Attenuation factor = 1 / (kc + kl*d + kq*d2) 
            //kc = constant attenuation factor (default = 1.0) 
            //kl = linear attenuation factor (default = 0.0) 
            //kq = quadratic attenuation factor (default = 0.0) 
         
            float distance = BIG_NUMBER; //either distance of light or falloff factor
            float factor = 1 / (gxconstantattanuation[lightcounter] + gxlinearattanuation[lightcounter]*distance + gxquadraticattanuation[lightcounter]*distance*distance);                   
             
            //float factor = 5.0; 
             
            //k0 - 0;                            
       		//k1 = 0.5f*(1.0f-ref_brite)/(ref_brite*ref_dist);
 			//k2 = 0.5f*(1.0f-ref_brite)/(ref_brite*ref_dist*ref_dist);                            

/*                           
            GX_InitLightAttn(&gxlight[lightcounter], 
                                                     1.0, //filled by initlightspot
                                                     0.0, //filled by initlightspot
                                                     0.0, //filled by initlightspot
                                                     gxconstantattanuation[lightcounter], 
                                                     gxlinearattanuation[lightcounter]*distance, 
                                                     gxquadraticattanuation[lightcounter]*distance*distance
                                                     
                                                     ) ;
                                                   //  k0              k1   , k2                    
*/                           
                                                     
            //GX_InitLightAttnK(&gxlight[lightcounter],  (gxcurrentmaterialshininess)/2.0F , 0.0F ,1.0F-(gxcurrentmaterialshininess)/2.0F);
            
             
                     
            
            GX_InitLightDistAttn(&gxlight[lightcounter], factor ,1.0, GX_DA_STEEP); //gxspotexponent[lightcounter] GX_DA_GENTLE
            GX_InitLightDistAttn(&gxlight[lightcounter+4], factor ,1.0, GX_DA_STEEP); //gxspotexponent[lightcounter] GX_DA_GENTLE

            
                                                         //ref_dist //ref_brite
            //                                           factor / strenght
//1.0 is //    glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 10.0f); ??
                                                     
                                                           
            //Setup light type (normal/spotlight)
            //0-90 / 255-0
            
            
                                                //cut_off, spot func
            //GX_InitLightSpot(&gxlight[lightcounter], 0.0f, GX_SP_OFF); //not this is not a spot light
            
            //GX_InitLightShininess(&gxlight[lightcounter], gxcurrentmaterialshininess); // /180?
            
            //float testspot = 90 - ((gxcurrentmaterialshininess * 90) / 128); //thanks ector 90 - (x * 90 / 255) 
            //if (gxcurrentmaterialshininess == 0){
            //   testspot = 90;
            //}
            //zid 255-gxcurrentmaterialshininess/(255/90);
            
            //setup specular highlight
            //GX_InitLightSpot(&gxlight[lightcounter], testspot, GX_SP_COS); //not this is not a spot light (gxspotcutoff[lightcounter])
            
            //setup normal spotlight
            GX_InitLightSpot(&gxlight[lightcounter], gxspotcutoff[lightcounter], GX_SP_RING1); //not this is not a spot light ()
            GX_InitLightSpot(&gxlight[1], gxspotcutoff[lightcounter], GX_SP_RING1); //not this is not a spot light ()
            
            if ( gxcurrentmaterialshininess != 0 ) {
                 //if (gxspotcutoff[lightcounter] != 180) {
                    GX_TestInitLightShininess(&gxlight[lightcounter+4], gxcurrentmaterialshininess);
                 //}
            };

			//Load the light up
			switch (lightcounter){
				case 0: 
                     GX_LoadLightObj(&gxlight[lightcounter], GX_LIGHT0);
                     GX_LoadLightObj(&gxlight[lightcounter+4], GX_LIGHT4);  
                     break;
				case 1: 
                     GX_LoadLightObj(&gxlight[lightcounter], GX_LIGHT1);
                     GX_LoadLightObj(&gxlight[lightcounter+4], GX_LIGHT5); 
                     break;
				case 2: 
                     GX_LoadLightObj(&gxlight[lightcounter], GX_LIGHT2); 
                     GX_LoadLightObj(&gxlight[lightcounter+4], GX_LIGHT6);
                     break;
				case 3: 
                     GX_LoadLightObj(&gxlight[lightcounter], GX_LIGHT3); 
                     GX_LoadLightObj(&gxlight[lightcounter+4], GX_LIGHT7);
                     break;
//				case 4: GX_LoadLightObj(&gxlight[lightcounter], GX_LIGHT4); break;
//				case 5: GX_LoadLightObj(&gxlight[lightcounter], GX_LIGHT5); break;
//				case 6: GX_LoadLightObj(&gxlight[lightcounter], GX_LIGHT6); break;
//				case 7: GX_LoadLightObj(&gxlight[lightcounter], GX_LIGHT7); break;
			}
			
			//GX_LoadLightObj(&gxlight[lightcounter], GX_LIGHT0);
			//GX_LoadLightObj(&gxlight[1], GX_LIGHT1);

		}
	}


	//set the curtexture if tex2denabled
	if (tex2denabled){
	GX_LoadTexObj(&gxtextures[curtexture], GX_TEXMAP0); //TODO: make GX_TEXMAP0 dynamic for multitexturing
	};

	//now we can draw the gx way (experiment try render in reverse ivm normals pointing the wrong way)
	
	int countelements = _numelements*2;
	if (gxcullfaceanabled==true){
       countelements = _numelements;
    }
	
	GX_Begin(_type, GX_VTXFMT0, countelements); //dependend on culling setting
	int i =0;
                                //default
//order dependend on glFrontFace(GL_CCW); 
//or GL_CW //	for( i=0; i<_numelements; i++)

//GX_TRIANGLESTRIP   GL_TRIANGLE_STRIP
//0 1 2			     0 1 2
//1 3 2			     2 1 3
//2 3 4			     2 3 4
//better think of a clever swapping routine
//maybe then no need to invert normal for trianglestrip anymore

//also GX_TRIANLES need to be drawn in reverse?
//but GX_QUAD does not

//so GX = CW by default while opengl is CCW by default?

//bushing say cannot i be possibel that opengl reorders vertexes

//u32 reverse = 0;
//int pos = 0;
//int temp = 0;

//GL_POLYGON: http://www.gamedev.net/reference/articles/article425.asp

bool cw = true;
bool ccw = true;

if(gxcullfaceanabled==true){
   cw = false;
   ccw = false;                            
   switch(gxwinding){
      case GL_CW: cw = true; break;
      case GL_CCW: ccw = true; break;
   }                         
}

    if (cw==true){ 
       //CW     
       for( i=_numelements-1; i>=0; i--)
       {
            UploadVertex(i);    	
       }
    }
    
    if (ccw==true){
       //CCW
       for( i=0; i<_numelements; i++)
       {
            UploadVertex(i);    	
       }
    }


	GX_End();

	//clean up just to be sure
	i =0;
	for( i=0; i<_numelements; i++)
	{
		_vertexelements[i].x = 0.0F;
		_vertexelements[i].y = 0.0F;
		_vertexelements[i].z = 0.0F;

		_normalelements[i].x = 0.0F;
		_normalelements[i].y = 0.0F;
		_normalelements[i].z = 0.0F;

		_colorelements[i].r = 0.0F;
		_colorelements[i].g = 0.0F;
		_colorelements[i].b = 0.0F;
		_colorelements[i].a = 0.0F;

		_texcoordelements[i].s = 0.0F;
		_texcoordelements[i].t = 0.0F;

	}
	_numelements =0;
}
Example #3
0
bool TestOBBOBB(OBB& a, OBB& b) {
    f32 ra, rb;
    Mtx R, AbsR;

    // Compute rotation matrix expressing b in a's coordinate frame
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            //R[i][j] = dot(&a.u[i], &b.u[j]);
            R[j][i] = dot(&a.u[i], &b.u[j]);
    
	for (int i = 0; i < 3; i++) {
		//R[i][0] = a.u[i].x * b.u[0].x + a.u[i].y * b.u[1].x + a.u[i].z * b.u[2].x;
		//R[i][1] = a.u[i].x * b.u[0].y + a.u[i].y * b.u[1].y + a.u[i].z * b.u[2].y;
		//R[i][2] = a.u[i].x * b.u[0].z + a.u[i].y * b.u[1].z + a.u[i].z * b.u[2].z;

		//R[i][0] = b.u[i].x * a.u[0].x + b.u[i].y * a.u[1].x + b.u[i].z * a.u[2].x;
		//R[i][1] = b.u[i].x * a.u[0].y + b.u[i].y * a.u[1].y + b.u[i].z * a.u[2].y;
		//R[i][2] = b.u[i].x * a.u[0].z + b.u[i].y * a.u[1].z + b.u[i].z * a.u[2].z;
	}

	SYS_LOG(L"R={ %.3f, %.3f, %.3f",  R[0][0], R[0][1], R[0][2]);
	SYS_LOG(L"    %.3f, %.3f, %.3f",  R[1][0], R[1][1], R[1][2]);
	SYS_LOG(L"    %.3f, %.3f, %.3f}", R[2][0], R[2][1], R[2][2]);

	guMtxTranspose(R, R);
    // Compute translation vector t
    //Vector t = b.c - a.c;
	Vec _t;
	_t.x = b.c.x - a.c.x;
	_t.y = b.c.y - a.c.y;
	_t.z = b.c.z - a.c.z;
    // Bring translation into a's coordinate frame
	f32 t[3];

    t[0] = _t.x*a.u[0].x + _t.y*a.u[0].y + _t.z*a.u[0].z;
    t[1] = _t.x*a.u[1].x + _t.y*a.u[1].y + _t.z*a.u[1].z;
    t[2] = _t.x*a.u[2].x + _t.y*a.u[2].y + _t.z*a.u[2].z;

    
	// Compute common subexpressions. Add in an epsilon term to counteract arithmetic errors when two edges are parallel and
    // their cross product is (near) null (see text for details)
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            AbsR[i][j] = fabs(R[i][j]) + EPSILON;

	SYS_LOG(L"abs(R)={ %.3f, %.3f, %.3f",  AbsR[0][0], AbsR[0][1], AbsR[0][2]);
	SYS_LOG(L"         %.3f, %.3f, %.3f",  AbsR[1][0], AbsR[1][1], AbsR[1][2]);
	SYS_LOG(L"         %.3f, %.3f, %.3f}", AbsR[2][0], AbsR[2][1], AbsR[2][2]);

    // Test axes L = A0, L = A1, L = A2
    for (int i = 0; i < 3; i++) {
        ra = a.e[i];
        rb = b.e[0] * AbsR[i][0] + b.e[1] * AbsR[i][1] + b.e[2] * AbsR[i][2];
		SYS_LOG(L":A%i, t={%.3f, %.3f, %.3f}, ra=%.3f, rb=%.3f", i, t[0], t[1], t[2], ra, rb);
        if (fabs(t[i]) > ra + rb) return 0;
    }
	
    // Test axes L = B0, L = B1, L = B2
    for (int i = 0; i < 3; i++) {
        ra = a.e[0] * AbsR[0][i] + a.e[1] * AbsR[1][i] + a.e[2] * AbsR[2][i];
        rb = b.e[i];
		SYS_LOG(L":B%i", i);
        if (fabs(t[0] * R[0][i] + t[1] * R[1][i] + t[2] * R[2][i]) > ra + rb) return 0;
    }

    // Test axis L = A0 x B0
	SYS_LOG(L":A0 x B0");
    ra = a.e[1] * AbsR[2][0] + a.e[2] * AbsR[1][0];
    rb = b.e[1] * AbsR[0][2] + b.e[2] * AbsR[0][1];
    if (fabs(t[2] * R[1][0] - t[1] * R[2][0]) > ra + rb) return 0;

    // Test axis L = A0 x B1
	SYS_LOG(L":A0 x B1");
    ra = a.e[1] * AbsR[2][1] + a.e[2] * AbsR[1][1];
    rb = b.e[0] * AbsR[0][2] + b.e[2] * AbsR[0][0];
    if (fabs(t[2] * R[1][1] - t[1] * R[2][1]) > ra + rb) return 0;

    // Test axis L = A0 x B2
	SYS_LOG(L":A0 x B2");
    ra = a.e[1] * AbsR[2][2] + a.e[2] * AbsR[1][2];
    rb = b.e[0] * AbsR[0][1] + b.e[1] * AbsR[0][0];
    if (fabs(t[2] * R[1][2] - t[1] * R[2][2]) > ra + rb) return 0;

    // Test axis L = A1 x B0
	SYS_LOG(L":A1 x B0");
    ra = a.e[0] * AbsR[2][0] + a.e[2] * AbsR[0][0];
    rb = b.e[1] * AbsR[1][2] + b.e[2] * AbsR[1][1];
    if (fabs(t[0] * R[2][0] - t[2] * R[0][0]) > ra + rb) return 0;

    // Test axis L = A1 x B1
	SYS_LOG(L":A1 x B1");
    ra = a.e[0] * AbsR[2][1] + a.e[2] * AbsR[0][1];
    rb = b.e[0] * AbsR[1][2] + b.e[2] * AbsR[1][0];
    if (fabs(t[0] * R[2][1] - t[2] * R[0][1]) > ra + rb) return 0;

    // Test axis L = A1 x B2
	SYS_LOG(L":A1 x B2");
    ra = a.e[0] * AbsR[2][2] + a.e[2] * AbsR[0][2];
    rb = b.e[0] * AbsR[1][1] + b.e[1] * AbsR[1][0];
    if (fabs(t[0] * R[2][2] - t[2] * R[0][2]) > ra + rb) return 0;

    // Test axis L = A2 x B0
	SYS_LOG(L":A2 x B0");
    ra = a.e[0] * AbsR[1][0] + a.e[1] * AbsR[0][0];
    rb = b.e[1] * AbsR[2][2] + b.e[2] * AbsR[2][1];
    if (fabs(t[1] * R[0][0] - t[0] * R[1][0]) > ra + rb) return 0;

    // Test axis L = A2 x B1
	SYS_LOG(L":A2 x B1");
    ra = a.e[0] * AbsR[1][1] + a.e[1] * AbsR[0][1];
    rb = b.e[0] * AbsR[2][2] + b.e[2] * AbsR[2][0];
    if (fabs(t[1] * R[0][1] - t[0] * R[1][1]) > ra + rb) return 0;

    // Test axis L = A2 x B2
	SYS_LOG(L":A2 x B2");
    ra = a.e[0] * AbsR[1][2] + a.e[1] * AbsR[0][2];
    rb = b.e[0] * AbsR[2][1] + b.e[1] * AbsR[2][0];
    if (fabs(t[1] * R[0][2] - t[0] * R[1][2]) > ra + rb) return 0;

    // Since no separating axis found, the OBBs must be intersecting
	SYS_LOG(L":INTERSECTION");
    return 1;
}
Example #4
0
void Particle_Render(Mtx M_view, ParticleSystem* psystem, Camera* camera) {
	// setup TEV
	GX_ClearVtxDesc();
	
	GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
	GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT);
    GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);

	GX_SetVtxAttrFmt(GX_VTXFMT6, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
    GX_SetVtxAttrFmt(GX_VTXFMT6, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
	GX_SetVtxAttrFmt(GX_VTXFMT6, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);

	// load model-view matrix
	Mtx M_modelView;
	guMtxIdentity(M_modelView);
	GX_LoadPosMtxImm(M_modelView, GX_PNMTX0);

	// setup tev
	GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
	GX_SetAlphaUpdate(GX_TRUE);

	GX_SetNumChans(1);

	GX_SetTevColorIn( 
		GX_TEVSTAGE0, 
		GX_CC_TEXC,  // a
		GX_CC_RASC,  // b
		GX_CC_TEXA,  // c 
		GX_CC_ZERO); // d

	GX_SetTevColorOp(
		GX_TEVSTAGE0,	// stage
		GX_TEV_ADD,		// op
		GX_TB_ZERO,		// bias
		GX_CS_SCALE_2,	// scale
		GX_ENABLE,		// clamp 0-255
		GX_TEVPREV);	// output reg


	GX_SetTevAlphaIn(
		GX_TEVSTAGE0, 
		GX_CA_ZERO,  // a
		GX_CA_TEXA,  // b
		GX_CA_RASA,  // c 
		GX_CA_ZERO); // d

	GX_SetTevAlphaOp(
		GX_TEVSTAGE0,	// stage
		GX_TEV_ADD,		// op
		GX_TB_ZERO,		// bias
		GX_CS_SCALE_1,	// scale
		GX_ENABLE,		// clamp 0-255
		GX_TEVPREV);	// output reg



	GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);

	GX_SetNumTexGens(1);
	GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);

	GX_LoadTexObj(&psystem->texture, GX_TEXMAP0);

	int n = psystem->n_particles;

	f32 texCoords[] = {
		0, 0,
		0, 1,
		1, 1,
		1, 0
	};

	GX_InvVtxCache();
	Vec3 camPos = camera->position();

	Mtx axisMtx;
	
	System::LogClear();
	
	Particle_Sort(M_view, psystem);

	GX_Begin(GX_QUADS, GX_VTXFMT6, n*4);
		for (int k = 0; k < n; k++) {
			int i = psystem->binsAllocations[k].particleIdx;
			//System::Log(L"p%d", i);
			Vec3& p  = psystem->positions[i];
			f32 lifetime = psystem->lifetimes[i];
			f32 age = psystem->ages[i];

			f32 ratio = age/lifetime;

			Vec3 forward = Math3D::normalized(camPos - p);

			Vec3 worldUp = Vec3(0, 1, 0);
			Vec3 right = Math3D::normalized(Math3D::cross(worldUp, forward));

			Vec3 up = Math3D::cross(forward, right);

			Mtx pm;

			guMtxCopy(M_view, pm);
			guMtxTranspose(pm, pm);
			pm[0][3] = p.x;		pm[1][3] = p.y;		pm[2][3] = p.z;

			guMtxConcat(M_view, pm, pm);
			
			f32 rotation = psystem->rotations[i];
			if (psystem->rotationInterpolator)
				rotation = psystem->rotationInterpolator->getValue(rotation, ratio);

			f32 size = psystem->sizes[i];
			if (psystem->sizeInterpolator)
				size = psystem->sizeInterpolator->getValue(size, ratio);

			if (psystem->colorInterpolator)
				psystem->colors[i] = psystem->colorInterpolator->getValue(ratio);

			Matrix34 M_rot = Math3D::matrixRotationZ(rotation);
			f32 hs = size*0.5f;
			Vec3 p0(-hs, +hs, 0);
			Vec3 p1(-hs, -hs, 0);
			Vec3 p2(+hs, -hs, 0);
			Vec3 p3(+hs, +hs, 0);

			Vec3 vs[4] = {p0, p1, p2, p3};

			for (int i = 0; i < 4; i++) {
				vs[i] = M_rot * vs[i];
				vs[i] = Math3D::matrixVecMul(pm, vs[i]);
			}
			
			for (int i = 0; i < 4; i++) {
				f32* coords = &texCoords[2*i];
				SendVertex(vs[i], psystem->colors[i], coords[0], coords[1]);
			}
		}
	GX_End();


	return;
}