#include "m_lights.h" #include "m_rcp.h" #include "libultra/libultra.h" #include "m_play.h" #include "sys_matrix.h" Light_buffer light_list_buf; extern Gfx point_light_init_model[]; extern Gfx point_light_model[]; static void Light_point_color_set(Lights* lights, u8 r, u8 g, u8 b, s16 radius); static void Global_light_list_ct(Global_light* light); static void Global_light_ambient_set(Global_light* light, u8 r,u8 g,u8 b); static void Global_light_fog_set(Global_light* light ,u8 r,u8 g,u8 b,s16 near,s16 far); static LightsN* new_LightsN(GRAPH*, u8 r, u8 g, u8 b); static void point_data_set(Lights* lights, s16 x, s16 y, s16 z,u8 r, u8 g, u8 b, s16 radius, int type ){ lights->type = type; lights->lights.point.x = x; lights->lights.point.y = y; lights->lights.point.z = z; Light_point_color_set(lights,r,g,b,radius); } extern void Light_point_ct(Lights* lights, s16 x, s16 y, s16 z, u8 r, u8 g, u8 b, s16 radius){ point_data_set(lights, x, y, z, r,g,b,radius,0); } static void Light_point_color_set(Lights* lights, u8 r, u8 g, u8 b, s16 radius){ lights->lights.point.color[0] = r; lights->lights.point.color[1] = g; lights->lights.point.color[2] = b; lights->lights.point.radius = radius; } extern void Light_diffuse_ct(Lights* lights, s8 x, s8 y, s8 z, u8 r, u8 g, u8 b){ lights->type = 1; lights->lights.diffuse.x = x; lights->lights.diffuse.y = y; lights->lights.diffuse.z = z; lights->lights.diffuse.color[0] = r; lights->lights.diffuse.color[1] = g; lights->lights.diffuse.color[2] = b; } extern void LightsN_disp_BG(LightsN* lights, GRAPH* graph){ Light_new* light; int i; OPEN_DISP(graph); gSPNumLights(NOW_BG_OPA_DISP++, lights->diffuse_count); light = lights->l; for(i = 0; i < lights->diffuse_count; i){ i++; gSPLight(NOW_BG_OPA_DISP++, light, i); gSPLight(NOW_BG_XLU_DISP++, light, i); light++; } i++; gSPLight(NOW_BG_OPA_DISP++, &lights->a.l, i); gSPLight(NOW_BG_XLU_DISP++, &lights->a.l, i); CLOSE_DISP(graph); } extern void LightsN_disp(LightsN* lights, GRAPH* graph){ Light_new* light; int i; Gfx* opa_gfx; Gfx* xlu_gfx; OPEN_DISP(graph); opa_gfx = NOW_POLY_OPA_DISP; xlu_gfx = NOW_POLY_XLU_DISP; gSPNumLights(opa_gfx++, lights->diffuse_count); gSPNumLights(xlu_gfx++, lights->diffuse_count); light = lights->l; for(i = 0; i < lights->diffuse_count;){ i++; gSPLight(opa_gfx++, light, i); gSPLight(xlu_gfx++, light, i); light++; } i++; gSPLight(opa_gfx++, &lights->a.l, i); gSPLight(xlu_gfx++, &lights->a.l, i); SET_POLY_OPA_DISP(opa_gfx); SET_POLY_XLU_DISP(xlu_gfx); CLOSE_DISP(graph); } static Light_new* LightsN_new_diffuse(LightsN* lights){ if(lights->diffuse_count >= 7){ return NULL; } return &lights->l[lights->diffuse_count++]; } static void LightsN__point_proc(LightsN* lights, LightParams* lightInfo, xyz_t* point){ f32 xdiff; f32 ydiff; f32 zdiff; f32 pointd; f32 rad; Light_new* light; if((point != NULL) && (lightInfo->point.radius > 0)){ xdiff = lightInfo->point.x - point->x; ydiff = lightInfo->point.y - point->y; zdiff = lightInfo->point.z - point->z; pointd = (xdiff * xdiff) + (ydiff * ydiff) + (zdiff * zdiff); rad = lightInfo->point.radius; if(pointd < (rad * rad)){ light = LightsN_new_diffuse(lights); if(light != NULL){ pointd = sqrtf(pointd); rad = pointd / rad; rad = 1 - (rad* rad); light->l.col[0] = light->l.colc[0] = lightInfo->point.color[0] * rad; light->l.col[1] = light->l.colc[1] = lightInfo->point.color[1] * rad; light->l.col[2] = light->l.colc[2] = lightInfo->point.color[2] * rad; rad = (pointd < 1) ? 120.0f : 120.0f / pointd; light->l.dir[0] = xdiff * rad; light->l.dir[1] = ydiff * rad; light->l.dir[2] = zdiff * rad; } } } } static void LightsN__P_point_proc(LightsN* lights, LightParams* lightInfo, xyz_t* pos){ f32 rad; xyz_t point; Light_new* light; f32 kq; if(lightInfo->point.radius > 0){ light = LightsN_new_diffuse(lights); if(light != NULL){ rad = lightInfo->point.radius; kq = 4500000.0f / (rad * rad); if(kq > 255.0f){ kq = 255.0f; } else if(kq < 20.0f){ kq = 20.0f; } light->l.col[0] = lightInfo->point.color[0]; light->l.colc[0] = light->l.col[0]; light->l.col[1] = lightInfo->point.color[1]; light->l.colc[1] = light->l.col[1]; light->l.col[2] = lightInfo->point.color[2]; light->l.colc[2] = light->l.col[2]; light->p.pos[0] = lightInfo->point.x; light->p.pos[1] = lightInfo->point.y; light->p.pos[2] = lightInfo->point.z; light->p.kc = 8; light->p.kl = -1; light->p.kq = kq; } } } static void LightsN__diffuse_proc(LightsN* lights, LightParams* lightInfo){ Light_new* light; light = LightsN_new_diffuse(lights); if(light != NULL){ light->l.col[0] = light->l.colc[0] = lightInfo->diffuse.color[0]; light->l.col[1] = light->l.colc[1] = lightInfo->diffuse.color[1]; light->l.col[2] = light->l.colc[2] = lightInfo->diffuse.color[2]; light->l.dir[0] = lightInfo->diffuse.x; light->l.dir[1] = lightInfo->diffuse.y; light->l.dir[2] = lightInfo->diffuse.z; } } extern void LightsN_list_check(LightsN* lights, Light_list* node, xyz_t* pos){ const static light_point_proc poslight_type_proc[] = { LightsN__point_proc, (light_point_proc)LightsN__diffuse_proc, LightsN__point_proc }; const static light_P_point_proc light_type_proc[] = { LightsN__P_point_proc, (light_P_point_proc)LightsN__diffuse_proc, LightsN__P_point_proc }; if(pos == NULL){ while(node != NULL) { light_type_proc[node->info->type](lights, &node->info->lights, pos); node = node->next; } } else{ while(node != NULL) { poslight_type_proc[node->info->type](lights, &node->info->lights, pos); node = node->next; } } } static Light_list* Light_list_buf_new(){ Light_list* light; if(light_list_buf.current >= 32){ return NULL; } light = &light_list_buf.lights[light_list_buf.idx]; while(light->info != NULL){ light_list_buf.idx++; if(light_list_buf.idx < 32){ light++; } else{ light_list_buf.idx = 0; light = &light_list_buf.lights[0]; } } light_list_buf.current++; return light; } static void Light_list_buf_delete(Light_list* light){ if(light != NULL){ light_list_buf.current--; light->info = NULL; light_list_buf.idx = (light - light_list_buf.lights) / (int)(sizeof(Light_list)); } } extern void Global_light_ct(Global_light* glight){ Global_light_list_ct(glight); Global_light_ambient_set(glight, 80,80,80); Global_light_fog_set(glight, 0,0,0, 996, 1600); bzero(&light_list_buf, sizeof(Light_buffer)); } static void Global_light_ambient_set(Global_light* glight, u8 r, u8 g, u8 b){ glight->ambientColor[0] = r; glight->ambientColor[1] = g; glight->ambientColor[2] = b; } static void Global_light_fog_set(Global_light* glight, u8 r, u8 g, u8 b, s16 near, s16 far){ glight->fogColor[0] = r; glight->fogColor[1] = g; glight->fogColor[2] = b; glight->fogNear = near; glight->fogFar = far; } extern LightsN* Global_light_read(Global_light* glight, GRAPH* graph){ return new_LightsN(graph, glight->ambientColor[0], glight->ambientColor[1], glight->ambientColor[2]); } static void Global_light_list_ct(Global_light* glight){ glight->list = NULL; } extern Light_list* Global_light_list_new(GAME_PLAY* play, Global_light* glight, Lights* light){ Light_list* clight; clight = Light_list_buf_new(); if(clight != NULL){ clight->info = light; clight->prev = NULL; clight->next = glight->list; if(glight->list != NULL){ glight->list->prev = clight; } glight->list = clight; } return clight; } extern void Global_light_list_delete(Global_light* glight, Light_list* light){ if(light != NULL){ if(light->prev != NULL){ light->prev->next = light->next; } else{ glight->list = light->next; } if(light->next != NULL){ light->next->prev = light->prev; } Light_list_buf_delete(light); } } static LightsN* new_LightsN(GRAPH* graph, u8 r, u8 g, u8 b){ LightsN* light; light = GRAPH_ALLOC(graph, sizeof(LightsN)); light->a.l.col[0] = light->a.l.colc[0] = r; light->a.l.col[1] = light->a.l.colc[1] = g; light->a.l.col[2] = light->a.l.colc[2] = b; light->diffuse_count = 0; return light; } extern void Light_list_point_draw(GAME_PLAY* play){ LightPoint* lightInfo; Light_list* light; GRAPH* g = play->game.graph; f32 rad; Gfx* dl; light = play->global_light.list; OPEN_DISP(g); dl = gfx_softsprite_prim_xlu(NOW_POLY_XLU_DISP); gDPSetAlphaDither(dl++, G_AD_NOISE); gDPSetColorDither(dl++, G_CD_MAGICSQ); gSPDisplayList(dl++,point_light_init_model); while(light != NULL) { if(light->info->type == 2){ lightInfo = &light->info->lights.point; if(lightInfo->drawGlow){ rad = (lightInfo->radius * lightInfo->radius) * 2.60000001617e-06f; gDPSetPrimColor(dl++, 0, 0, lightInfo->color[0], lightInfo->color[1], lightInfo->color[2], 50); Matrix_translate(lightInfo->x, lightInfo->y, lightInfo->z, 0); Matrix_scale(rad,rad,rad, 1); gSPMatrix(dl++, _Matrix_to_Mtx_new(play->game.graph),G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(dl++,point_light_model); } } light = light->next; } SET_POLY_XLU_DISP(dl); CLOSE_DISP(g); }