#include #include "functions.h" #include "variables.h" #include "model.h" extern f32 vtxList_getGlobalNorm(BKVertexList *); extern void points_to_boundingBoxWithMargin(f32 arg0[3], f32 arg1[3], f32 margin, f32 min[3], f32 max[3]); #define ABS_F(s) (((s) >= 0.0f) ? (s) : -(s)) typedef struct { f32 edgeAB[3]; f32 edgeAC[3]; f32 normal[3]; BKCollisionTri *tri_ptr; f32 tri_coord[3][3]; }Struct_core2_5FD90_0; /* .bss */ struct { BKCollisionGeo *unk0[100]; BKCollisionGeo **unk190; }D_8037E910; f32 D_8037EAA8[3][3]; Struct_core2_5FD90_0 D_8037EAD0[100]; /* .code */ void func_802E6D20(BKCollisionTri *arg0, BKVertexList *vtx_list) { Vtx *vtx; Vtx *i_vtx; s32 i; vtx = (Vtx *)(vtx_list + 1); if (arg0 == NULL) return; for(i = 0; i < 3; i++){ i_vtx = vtx + arg0->unk0[i]; D_8037EAA8[i][0] = (f32) i_vtx->v.ob[0]; D_8037EAA8[i][1] = (f32) i_vtx->v.ob[1]; D_8037EAA8[i][2] = (f32) i_vtx->v.ob[2]; } } void collisionList_getIntersecting(BKCollisionList *collision_list, f32 arg1[3], f32 arg2[3], BKCollisionGeo ***arg3, BKCollisionGeo ***arg4) { s32 sp3C[3]; s32 sp30[3]; s32 i; s32 x, y, z; if (collision_list->unk12 == 0) { D_8037E910.unk190 = &D_8037E910.unk0[0]; *(D_8037E910.unk190++) = (s32)collision_list + sizeof(BKCollisionList); *arg3 = &D_8037E910.unk0[0]; *arg4 = D_8037E910.unk190; } else{ for(i = 0 ; i < 3; i++){ if (arg1[i] >= 0.0f) { sp3C[i] = (s32) arg1[i] / collision_list->unk12; } else { sp3C[i] = ((s32) arg1[i] / collision_list->unk12) - 1; } if (arg2[i] >= 0.0f) { sp30[i] = (s32) arg2[i] / collision_list->unk12; } else { sp30[i] = ((s32) arg2[i] / collision_list->unk12) - 1; } if (sp3C[i] < collision_list->unk0[i]) { sp3C[i] = collision_list->unk0[i]; } if (collision_list->unk6[i] < sp3C[i]) { sp3C[i] = collision_list->unk6[i]; } if (sp30[i] < collision_list->unk0[i]) { sp30[i] = collision_list->unk0[i]; } if (collision_list->unk6[i] < sp30[i]) { sp30[i] = collision_list->unk6[i]; } sp3C[i] -= collision_list->unk0[i]; sp30[i] -= collision_list->unk0[i]; } D_8037E910.unk190 = &D_8037E910.unk0[0]; for(z = sp3C[2]; z <= sp30[2]; z++){ for(y = sp3C[1]; y <= sp30[1]; y++){ for(x = sp3C[0]; x <= sp30[0]; x++){ *(D_8037E910.unk190++) = ((collision_list->unkE * z) + (BKCollisionGeo *)(collision_list + 1)) + x + (y * collision_list->unkC); } } } *arg3 = &D_8037E910.unk0[0]; *arg4 = D_8037E910.unk190; } } void func_802E70FC(BKCollisionList *collision_list, s32 min[3], s32 max[3], BKCollisionGeo ***begin_geo_ptr, BKCollisionGeo ***end_geo_ptr) { s32 sp3C[3]; s32 sp30[3]; s32 i; s32 x, y, z; if (collision_list->unk12 == 0) { D_8037E910.unk190 = &D_8037E910.unk0[0]; *(D_8037E910.unk190++) = (s32)collision_list + sizeof(BKCollisionList); *begin_geo_ptr = &D_8037E910.unk0[0]; *end_geo_ptr = D_8037E910.unk190; } else{ for(i = 0 ; i < 3; i++){ if (min[i] >= 0) { sp3C[i] = (s32) min[i] / collision_list->unk12; } else { sp3C[i] = ((s32) min[i] / collision_list->unk12) - 1; } if (max[i] >= 0) { sp30[i] = (s32) max[i] / collision_list->unk12; } else { sp30[i] = ((s32) max[i] / collision_list->unk12) - 1; } if (sp3C[i] < collision_list->unk0[i]) { sp3C[i] = collision_list->unk0[i]; } if (collision_list->unk6[i] < sp3C[i]) { sp3C[i] = collision_list->unk6[i]; } if (sp30[i] < collision_list->unk0[i]) { sp30[i] = collision_list->unk0[i]; } if (collision_list->unk6[i] < sp30[i]) { sp30[i] = collision_list->unk6[i]; } sp3C[i] -= collision_list->unk0[i]; sp30[i] -= collision_list->unk0[i]; } D_8037E910.unk190 = &D_8037E910.unk0[0]; for(z = sp3C[2]; z <= sp30[2]; z++){ for(y = sp3C[1]; y <= sp30[1]; y++){ for(x = sp3C[0]; x <= sp30[0]; x++){ *(D_8037E910.unk190++) = ((collision_list->unkE * z) + (BKCollisionGeo *)(collision_list + 1)) + x + (y * collision_list->unkC); } } } *begin_geo_ptr = &D_8037E910.unk0[0]; *end_geo_ptr = D_8037E910.unk190; } } void func_802E73C8(f32 arg0[3][3]) { s32 i; for(i = 0; i < 3; i++){ arg0[i][0] = D_8037EAA8[i][0]; arg0[i][1] = D_8037EAA8[i][1]; arg0[i][2] = D_8037EAA8[i][2]; } } s32 func_802E7408(BKCollisionList *collisionList) { BKCollisionTri *temp_a1; BKCollisionTri *temp_a2; BKCollisionTri *phi_a2; s32 phi_v1; phi_v1 = 0; temp_a2 = (collisionList->unk10 * 4) + (s32)collisionList + sizeof(BKCollisionList); temp_a1 = (collisionList->unk14 * 0xC) + (s32)temp_a2; for(phi_a2 = temp_a2; phi_a2 < temp_a1; phi_a2++){ if(phi_a2->flags & 0x1E0000){ phi_v1++; } } return phi_v1; } s32 func_802E7468(BKCollisionList *collisionList){ return collisionList->unk14; } void collisionList_getTris(BKCollisionList *collision_list, BKCollisionTri **begin_ptr, BKCollisionTri **end_ptr){ *begin_ptr = (collision_list->unk10 * 4) + (s32)collision_list + sizeof(BKCollisionList); *end_ptr = (collision_list->unk14 * 0xC) + (s32)*begin_ptr; } bool func_802E74A0(f32 arg0[3], f32 arg1, f32 arg2[3], f32 arg3[3]) { f32 sp24[3]; f32 sp20; if (arg1 <= ml_func_802560D0(arg2, arg3, arg0)) { return FALSE; } sp24[0] = (arg2[0] + arg3[0]) / 2; sp24[1] = (arg2[1] + arg3[1]) / 2; sp24[2] = (arg2[2] + arg3[2]) / 2; sp20 = ml_vec3f_distance(sp24, arg0); if ((ml_vec3f_distance(sp24, arg2) + arg1) <= sp20) { return FALSE; } return TRUE; } bool func_802E7588(f32 arg0[3], f32 arg1, f32 arg2[3], f32 arg3) { return (ml_vec3f_distance(arg0, arg2) < (arg1 + arg3)); } void calculateBoundsAndDirection(f32 startPoint[3], f32 endPoint[3], s32 minBounds[3], s32 maxBounds[3], f32 directionVector[3]) { s32 i; for(i = 0; i < 3; i++){ if (startPoint[i] < endPoint[i]) { minBounds[i] = (s32) startPoint[i]; maxBounds[i] = (s32) endPoint[i]; } else { minBounds[i] = (s32) endPoint[i]; maxBounds[i] = (s32) startPoint[i]; } minBounds[i] += -1; maxBounds[i] += 1; } directionVector[0] = (endPoint[0] - startPoint[0]); directionVector[1] = (endPoint[1] - startPoint[1]); directionVector[2] = (endPoint[2] - startPoint[2]); } BKCollisionTri *func_802E76B0(BKCollisionList *collisionList, BKVertexList *vertexList, f32 startPoint[3], f32 endPoint[3], f32 arg4[3], u32 flagFilter) { s32 i; s32 j; BKCollisionGeo **start_geo; BKCollisionGeo **i_geo; BKCollisionGeo **end_geo; BKCollisionTri *start_tri; BKCollisionGeo *temp_v1; BKCollisionTri *end_tri; BKCollisionTri *i_tri; Vtx *vtx_pool; Vtx *sp164[3]; s32 min_bounds[3]; s32 max_bounds[3]; f32 direction_vector[3]; Vtx *temp_a2; f32 sp130[3]; f32 sp124[3]; f32 sp118[3]; f32 sp10C[3]; f32 temp_f0_2; f32 spFC[3]; f32 spF0[3]; f32 spE4[3]; f32 temp_f12_2; f32 temp_f12_3; f32 temp_f12_4; f32 temp_f14_2; f32 temp_f20; f32 temp_f2_2; f32 temp_f2_6; f32 spBC[3]; s32 phi_a0_2; f32 pad; f32 sp90[3][3]; BKCollisionTri *result_collision; result_collision = NULL; temp_f20 = (f32) vertexList->global_norm; calculateBoundsAndDirection(startPoint, endPoint, min_bounds, max_bounds, direction_vector); for(i = 0; i < 3; i++){ if ((max_bounds[i] <= -temp_f20) || (temp_f20 <= min_bounds[i])) { return NULL; } } func_802E70FC(collisionList, min_bounds, max_bounds, &start_geo, &end_geo); for(i_geo = start_geo; i_geo < end_geo; i_geo++){ start_tri = (BKCollisionTri *)((BKCollisionGeo *)(collisionList + 1) + collisionList->unk10) + (*i_geo)->start_tri_index; end_tri = start_tri + (*i_geo)->tri_count; for(i_tri = start_tri; i_tri < end_tri; i_tri++){ vtx_pool = (Vtx*)(vertexList + 1); if((i_tri->flags & flagFilter)) continue; sp164[0] = &vtx_pool[i_tri->unk0[0]]; sp164[1] = &vtx_pool[i_tri->unk0[1]]; sp164[2] = &vtx_pool[i_tri->unk0[2]]; if((sp164[0]->v.ob[0] < min_bounds[0]) && (sp164[1]->v.ob[0] < min_bounds[0]) && (sp164[2]->v.ob[0] < min_bounds[0])) continue; if((max_bounds[0] < sp164[0]->v.ob[0]) && (max_bounds[0] < sp164[1]->v.ob[0]) && (max_bounds[0] < sp164[2]->v.ob[0])) continue; if((sp164[0]->v.ob[2] < min_bounds[2]) && (sp164[1]->v.ob[2] < min_bounds[2]) && (sp164[2]->v.ob[2] < min_bounds[2])) continue; if((max_bounds[2] < sp164[0]->v.ob[2]) && (max_bounds[2] < sp164[1]->v.ob[2]) && (max_bounds[2] < sp164[2]->v.ob[2])) continue; if((sp164[0]->v.ob[1] < min_bounds[1]) && (sp164[1]->v.ob[1] < min_bounds[1]) && (sp164[2]->v.ob[1] < min_bounds[1])) continue; if((max_bounds[1] < sp164[0]->v.ob[1]) && (max_bounds[1] < sp164[1]->v.ob[1]) && (max_bounds[1] < sp164[2]->v.ob[1])) continue; for(i = 0; i < 3; i++){ temp_a2 = &vtx_pool[i_tri->unk0[i]]; for(j = 0; j <3; j++){ sp90[i][j] = temp_a2->v.ob[j]; } } sp130[0] = sp90[1][0] - sp90[0][0]; sp130[1] = sp90[1][1] - sp90[0][1]; sp130[2] = sp90[1][2] - sp90[0][2]; sp124[0] = sp90[2][0] - sp90[0][0]; sp124[1] = sp90[2][1] - sp90[0][1]; sp124[2] = sp90[2][2] - sp90[0][2]; spBC[0] = (sp130[1] * sp124[2]) - (sp130[2] * sp124[1]); spBC[1] = (sp130[2] * sp124[0]) - (sp130[0] * sp124[2]); spBC[2] = (sp130[0] * sp124[1]) - (sp130[1] * sp124[0]); if( (100000.0f < spBC[0]) || (100000.0f < spBC[1]) || (100000.0f < spBC[2]) || (spBC[0] < -100000.0f) || (spBC[1] < -100000.0f) || (spBC[2] < -100000.0f) ) { spBC[0] /= 100000.0f; spBC[1] /= 100000.0f; spBC[2] /= 100000.0f; } sp118[0] = startPoint[0] - sp90[0][0]; sp118[1] = startPoint[1] - sp90[0][1]; sp118[2] = startPoint[2] - sp90[0][2]; sp10C[0] = endPoint[0] - sp90[0][0]; sp10C[1] = endPoint[1] - sp90[0][1]; sp10C[2] = endPoint[2] - sp90[0][2]; temp_f12_2 = sp118[0]*spBC[0] + sp118[1]*spBC[1] + sp118[2]*spBC[2]; temp_f2_2 = sp10C[0]*spBC[0] + sp10C[1]*spBC[1] + sp10C[2]*spBC[2]; pad = temp_f2_2; if ((!((temp_f12_2 >= 0.0f) && (pad >= 0.0f)))) if( !((temp_f12_2 <= 0.0f) && (pad <= 0.0f))) { if ((i_tri->flags & 0x10000) && (temp_f12_2 < 0.0f)) { spBC[0] = -spBC[0]; spBC[1] = -spBC[1]; spBC[2] = -spBC[2]; } temp_f12_3 = spBC[0]*direction_vector[0] + spBC[1]*direction_vector[1] + spBC[2]*direction_vector[2]; pad = (sp90[0][0]*spBC[0] + sp90[0][1]*spBC[1] + sp90[0][2]*spBC[2]); if (temp_f12_3 == 0.0f) continue; temp_f0_2 = -((spBC[0]*startPoint[0] + spBC[1]*startPoint[1] + spBC[2]*startPoint[2]) - pad)/ temp_f12_3; if(temp_f0_2 <= 0.0f || 1.0f <= temp_f0_2) continue; spFC[0] = startPoint[0] + (direction_vector[0] * temp_f0_2); spFC[1] = startPoint[1] + (direction_vector[1] * temp_f0_2); spFC[2] = startPoint[2] + (direction_vector[2] * temp_f0_2); phi_a0_2 = (ABS_F(spBC[0]) > ABS_F(spBC[1])) ? 0 : 1; phi_a0_2 = (ABS_F(spBC[2]) > ABS_F(spBC[phi_a0_2])) ? 2 : phi_a0_2; spF0[0] = spFC[(phi_a0_2 + 1) % 3] - sp90[0][(phi_a0_2 + 1) % 3]; spF0[1] = sp130[(phi_a0_2 + 1) % 3]; spF0[2] = sp124[(phi_a0_2 + 1) % 3]; spE4[0] = spFC[(phi_a0_2 + 2) % 3] - sp90[0][(phi_a0_2 + 2) % 3]; spE4[1] = sp130[(phi_a0_2 + 2) % 3]; spE4[2] = sp124[(phi_a0_2 + 2) % 3]; temp_f14_2 = ((spF0[1] * spE4[2]) - (spE4[1] * spF0[2])); temp_f12_4 = ((spF0[0] * spE4[2]) - (spE4[0] * spF0[2])) / temp_f14_2; if(temp_f12_4 < 0.0f || 1.0f < temp_f12_4) continue; temp_f2_6 = ((spF0[1] * spE4[0]) - (spE4[1] * spF0[0])) / temp_f14_2; if(temp_f2_6 < 0.0f || 1.0f < temp_f2_6) continue; if(1.0f < (temp_f12_4 + temp_f2_6)) continue; result_collision = i_tri; endPoint[0] = spFC[0]; endPoint[1] = spFC[1]; endPoint[2] = spFC[2]; ml_vec3f_normalize_copy(arg4, spBC); calculateBoundsAndDirection(startPoint, endPoint, min_bounds, max_bounds, direction_vector); } } } func_802E6D20(result_collision, vertexList); return result_collision; } BKCollisionTri *func_802E805C(BKCollisionList *collision_list, BKVertexList *vtxList, f32 arg2[3], f32 rotation[3], f32 scale, s32 arg5, s32 arg6, s32 arg7, s32 arg8){ f32 sp44[3]; f32 sp38[3]; int sp34; int i; if(!func_802E74A0(arg2, vtxList->global_norm*scale, arg5, arg6)){ return 0; } else{ mlMtxIdent(); func_80252CC4(arg2, rotation, scale, 0); mlMtx_apply_vec3f(sp44, arg5); mlMtx_apply_vec3f(sp38, arg6); sp34 = func_802E76B0(collision_list, vtxList, sp44, sp38, arg7, arg8); if(!sp34){ return NULL; } else{ mlMtxIdent(); func_80252C08(arg2, rotation, scale, NULL); mlMtx_apply_vec3f(arg6, sp38); mlMtxIdent(); func_80252C08(NULL, rotation, 1.0f, 0); mlMtx_apply_vec3f(arg7, arg7); mlMtxIdent(); func_80252C08(arg2, rotation, scale, 0); for(i = 0; i < 3; i++){ mlMtx_apply_vec3f(D_8037EAA8[i], D_8037EAA8[i]); } } } return sp34; } s32 func_802E81CC(BKCollisionList *collisionList, BKVertexList *vertexList, f32 p1[3], f32 p2[3], f32 velocity[3], f32 margin, s32 flagFilter, s32 **activeTriStartPtr, s32 *activeTriEndPtr) { BKCollisionGeo **start_geo; BKCollisionGeo **i_geo; BKCollisionGeo **end_geo; f32 spC0[3]; BKCollisionTri *start_tri; BKCollisionTri *end_tri; f32 min[3]; f32 max[3]; BKCollisionTri *i_tri; Vtx *vertex_pool; Vtx *i_vtx; s32 i; s32 j; f32 tri_min_coord[3]; f32 tri_max_coord[3]; Struct_core2_5FD90_0 *var_s2; f32 temp_f0; points_to_boundingBoxWithMargin(p1, p2, margin, min, max); temp_f0 = vtxList_getGlobalNorm(vertexList); for(i = 0; i < 3; i++){ if ((max[i] <= -temp_f0) || (temp_f0 <= min[i])) { return 0; } } collisionList_getIntersecting(collisionList, min, max, &start_geo, &end_geo); vertex_pool = vtxList_getVertices(vertexList); var_s2 = D_8037EAD0; for(i_geo = start_geo; i_geo < end_geo; i_geo++){ start_tri = (BKCollisionTri *)((BKCollisionGeo *)(collisionList + 1) + collisionList->unk10) + (*i_geo)->start_tri_index; end_tri = start_tri + (*i_geo)->tri_count; for(i_tri = start_tri; i_tri < end_tri; i_tri++){ if (!(i_tri->flags & flagFilter)) { for(i = 0; i < 3; i++){ i_vtx = vertex_pool + i_tri->unk0[i]; for(j = 0; j < 3; j++){ var_s2->tri_coord[i][j] = i_vtx->v.ob[j]; } } //get min/max bounds of triangle tri_min_coord[0] = var_s2->tri_coord[0][0];\ tri_min_coord[1] = var_s2->tri_coord[0][1];\ tri_min_coord[2] = var_s2->tri_coord[0][2]; tri_max_coord[0] = var_s2->tri_coord[0][0];\ tri_max_coord[1] = var_s2->tri_coord[0][1];\ tri_max_coord[2] = var_s2->tri_coord[0][2]; for(i = 1; i < 3; i++){ for(j = 0; j < 3; j++){ if (var_s2->tri_coord[i][j] < tri_min_coord[j]) { tri_min_coord[j] = var_s2->tri_coord[i][j]; } if (tri_max_coord[j] < var_s2->tri_coord[i][j]) { tri_max_coord[j] = var_s2->tri_coord[i][j]; } } } //check if tri intersects region if ((max[0] < tri_min_coord[0]) || (tri_max_coord[0] < min[0])) continue; if ((max[1] < tri_min_coord[1]) || (tri_max_coord[1] < min[1])) continue; if ((max[2] < tri_min_coord[2]) || (tri_max_coord[2] < min[2])) continue; //calculate normal of tri var_s2->edgeAB[0] = var_s2->tri_coord[1][0] - var_s2->tri_coord[0][0]; var_s2->edgeAB[1] = var_s2->tri_coord[1][1] - var_s2->tri_coord[0][1]; var_s2->edgeAB[2] = var_s2->tri_coord[1][2] - var_s2->tri_coord[0][2]; var_s2->edgeAC[0] = var_s2->tri_coord[2][0] - var_s2->tri_coord[0][0]; var_s2->edgeAC[1] = var_s2->tri_coord[2][1] - var_s2->tri_coord[0][1]; var_s2->edgeAC[2] = var_s2->tri_coord[2][2] - var_s2->tri_coord[0][2]; var_s2->normal[0] = (var_s2->edgeAB[1] * var_s2->edgeAC[2]) - (var_s2->edgeAB[2] * var_s2->edgeAC[1]); var_s2->normal[1] = (var_s2->edgeAB[2] * var_s2->edgeAC[0]) - (var_s2->edgeAB[0] * var_s2->edgeAC[2]); var_s2->normal[2] = (var_s2->edgeAB[0] * var_s2->edgeAC[1]) - (var_s2->edgeAB[1] * var_s2->edgeAC[0]); ml_vec3f_normalize( var_s2->normal); if (i_tri->flags & 0x10000) {//invert normal? spC0[0] = p1[0] - var_s2->tri_coord[0][0]; spC0[1] = p1[1] - var_s2->tri_coord[0][1]; spC0[2] = p1[2] - var_s2->tri_coord[0][2]; if (((spC0[0]*var_s2->normal[0]) + (spC0[1]*var_s2->normal[1]) + (spC0[2]*var_s2->normal[2])) < 0.0f) { var_s2->normal[0] = -var_s2->normal[0];\ var_s2->normal[1] = -var_s2->normal[1];\ var_s2->normal[2] = -var_s2->normal[2]; } } else{ if (((var_s2->normal[0]*velocity[0]) + (var_s2->normal[1]*velocity[1]) + (var_s2->normal[2]*velocity[2])) > 0.0f) continue; //velocity is same direction as triangle normal } //add tri to active tri collisions var_s2->tri_ptr = i_tri; var_s2++; if ((var_s2 - D_8037EAD0) > 100) break; } } if ((var_s2 - D_8037EAD0) > 100) break; } *activeTriStartPtr = (s32) D_8037EAD0; //activeTriPool *activeTriEndPtr = (s32) var_s2; //activeTriPoolEnd return var_s2 - D_8037EAD0 > 0; //Count } Struct_core2_5FD90_0 *func_802E879C(Struct_core2_5FD90_0 *startTri, Struct_core2_5FD90_0 *endTri, f32 position[3], f32 radius, f32 arg4[3]) { s32 i; Struct_core2_5FD90_0 *i_tri; f32 sp144[3][3]; f32 sp120[3][3]; f32 normal_length; f32 temp_f0_3; f32 temp_f0_4; f32 temp_f12_3; f32 temp_f18; f32 temp_f22; f32 spFC[3]; f32 spF0[3]; u32 var_a0; s32 var_a1; s32 var_a2; f32 projected_position[3]; f32 temp_f2_4; Struct_core2_5FD90_0 *spD0; f32 temp_f8; f32 *var_s0; spD0 = 0; arg4[0] = 0.0f; arg4[1] = 0.0f; arg4[2] = 0.0f; for(i_tri = startTri; i_tri < endTri; i_tri++){ //project point onto plane of triangle sp120[0][0] = position[0] - i_tri->tri_coord[0][0]; sp120[0][1] = position[1] - i_tri->tri_coord[0][1]; sp120[0][2] = position[2] - i_tri->tri_coord[0][2]; temp_f18 = (sp120[0][0] * i_tri->normal[0]) + (sp120[0][1] * i_tri->normal[1]) + (sp120[0][2] * i_tri->normal[2]); if ((-(radius - 0.5)>= temp_f18) || ((radius -0.5) <= temp_f18)) continue; temp_f8 = i_tri->normal[0]; normal_length = (temp_f8 * i_tri->normal[0]) + (i_tri->normal[1] * i_tri->normal[1]) + (i_tri->normal[2] * i_tri->normal[2]); if(normal_length == 0.0f) continue; normal_length = -temp_f18 / normal_length; projected_position[0] = position[0] + (i_tri->normal[0] * normal_length); projected_position[1] = position[1] + (i_tri->normal[1] * normal_length); projected_position[2] = position[2] + (i_tri->normal[2] * normal_length); //check if projected point is inside of triangle var_a2 = (ABS_F(i_tri->normal[0]) > ABS_F(i_tri->normal[1])) ? 0 : 1; var_a2 = (ABS_F(i_tri->normal[2]) > ABS_F(i_tri->normal[var_a2])) ? 2 : var_a2; spFC[0] = projected_position[(var_a2 + 1)%3] - i_tri->tri_coord[0][(var_a2 + 1)%3]; spFC[1] = i_tri->edgeAB[(var_a2 + 1)%3]; spFC[2] = i_tri->edgeAC[(var_a2 + 1)%3]; spF0[0] = projected_position[(var_a2 + 2)%3] - i_tri->tri_coord[0][(var_a2 + 2)%3]; spF0[1] = i_tri->edgeAB[(var_a2 + 2)%3]; spF0[2] = i_tri->edgeAC[(var_a2 + 2)%3]; temp_f2_4 = (spFC[1] * spF0[2]) - (spF0[1] * spFC[2]); temp_f12_3 = ((spFC[0] * spF0[2]) - (spF0[0] * spFC[2]))/temp_f2_4; temp_f0_4 = ((spFC[1] * spF0[0]) - (spF0[1] * spFC[0]))/ temp_f2_4; if ((0.0f <= temp_f12_3) && (temp_f12_3 <= 1.0f) && (0.0f <= temp_f0_4) && (temp_f0_4 <= 1.0f)) if ((0 <= 1.0f - (temp_f12_3 + temp_f0_4))) { //projected point lies on triangle spD0 = i_tri; arg4[0] = arg4[0] + i_tri->normal[0]; arg4[1] = arg4[1] + i_tri->normal[1]; arg4[2] = arg4[2] + i_tri->normal[2]; continue; } //projected point lies outside triangle for(i = 0; i < 3; i++){ sp120[i][0] = position[0] - i_tri->tri_coord[i][0]; sp120[i][1] = position[1] - i_tri->tri_coord[i][1]; sp120[i][2] = position[2] - i_tri->tri_coord[i][2]; if (sp120[i][0]*sp120[i][0] + sp120[i][1]*sp120[i][1] + sp120[i][2]*sp120[i][2] < radius * radius) { spD0 = i_tri; arg4[0] = arg4[0] + i_tri->normal[0]; arg4[1] = arg4[1] + i_tri->normal[1]; arg4[2] = arg4[2] + i_tri->normal[2]; break; } } if(i < 3) continue; for(i = 0; i < 3; i++){ sp144[i][0] = i_tri->tri_coord[(i + 1) % 3][0] - i_tri->tri_coord[i][0]; sp144[i][1] = i_tri->tri_coord[(i + 1) % 3][1] - i_tri->tri_coord[i][1]; sp144[i][2] = i_tri->tri_coord[(i + 1) % 3][2] - i_tri->tri_coord[i][2]; temp_f22 = sp144[i][0]*sp144[i][0] + sp144[i][1]*sp144[i][1] + sp144[i][2]*sp144[i][2]; ml_vec3f_normalize(sp144[i]); temp_f0_3 = (sp144[i][0]*sp120[i][0]) + (sp144[i][1]*sp120[i][1]) + (sp144[i][2]*sp120[i][2]); if ((0.0f <= temp_f0_3) && ((temp_f0_3 * temp_f0_3) <= temp_f22)){ projected_position[0] = sp120[i][0] - sp144[i][0]*temp_f0_3; projected_position[1] = sp120[i][1] - sp144[i][1]*temp_f0_3; projected_position[2] = sp120[i][2] - sp144[i][2]*temp_f0_3; if(projected_position[0]*projected_position[0] + projected_position[1]*projected_position[1] + projected_position[2]*projected_position[2] < radius * radius){ spD0 = i_tri; arg4[0] = arg4[0] + i_tri->normal[0]; arg4[1] = arg4[1] + i_tri->normal[1]; arg4[2] = arg4[2] + i_tri->normal[2]; break; } } } } return spD0; } BKCollisionTri *func_802E8E88(BKCollisionList *collision_list, BKVertexList *vtx_list, f32 p1[3], f32 p2[3], f32 radius, f32 arg5[3], s32 arg6, s32 flagFilter){ Struct_core2_5FD90_0 * start_active_tri; Struct_core2_5FD90_0 * end_active_tri; f32 spB4[3]; f32 temp_f20; f32 phi_f22; f32 phi_f24; s32 phi_s0; f32 sp98[3]; f32 sp8C[3]; Struct_core2_5FD90_0 *phi_s5; Struct_core2_5FD90_0 *phi_v0; f32 sp78[3]; sp78[0] = p2[0] - p1[0]; sp78[1] = p2[1] - p1[1]; sp78[2] = p2[2] - p1[2]; if (!func_802E81CC(collision_list, vtx_list, p1, p2, sp78, (f32) ((f64) radius + 0.5), flagFilter, &start_active_tri, &end_active_tri)) { return NULL; } phi_s5 = func_802E879C(start_active_tri, end_active_tri, p2, radius, sp8C); if (phi_s5 == NULL) { return NULL; } arg5[0] = sp8C[0]; arg5[1] = sp8C[1]; arg5[2] = sp8C[2]; spB4[0] = p2[0] - p1[0]; spB4[1] = p2[1] - p1[1]; spB4[2] = p2[2] - p1[2]; p2[0] = p1[0]; p2[1] = p1[1]; p2[2] = p1[2]; phi_f22 = 0.0f; phi_f24 = 1.0f; for(phi_s0 = 0; phi_s0 < arg6; phi_s0++){ temp_f20 = (phi_f22 + phi_f24) * 0.5; sp98[0] = p1[0] + (spB4[0] * temp_f20); sp98[1] = p1[1] + (spB4[1] * temp_f20); sp98[2] = p1[2] + (spB4[2] * temp_f20); phi_v0 = func_802E879C(start_active_tri, end_active_tri, sp98, radius, sp8C); if (phi_v0 != NULL) { arg5[0] = sp8C[0]; arg5[1] = sp8C[1]; arg5[2] = sp8C[2]; phi_f24 = temp_f20; phi_s5 = phi_v0; } else { p2[0] = sp98[0]; p2[1] = sp98[1]; p2[2] = sp98[2]; phi_f22 = temp_f20; } } if (phi_s5 == NULL) { return NULL; } ml_vec3f_normalize(arg5); func_802E6D20(phi_s5->tri_ptr, vtx_list); return phi_s5->tri_ptr; } BKCollisionTri *func_802E9118(BKCollisionList * collision_list, BKVertexList *vtx_list, f32 arg2[3], s32 arg3, f32 arg4, f32 arg5[3], f32 arg6[3], f32 arg7, f32 arg8[3], s32 arg9, s32 flagFilter) { f32 sp4C[3]; f32 sp40[3]; BKCollisionTri *sp3C; s32 i; if (((f32)vtx_list->global_norm * arg4) <= (ml_vec3f_distance(arg6, arg2) - arg7)) { return 0; } mlMtxIdent(); func_80252CC4(arg2, arg3, arg4, 0); mlMtx_apply_vec3f(&sp4C, arg5); mlMtx_apply_vec3f(&sp40, arg6); sp3C = func_802E8E88(collision_list, vtx_list, &sp4C, &sp40, arg7 / arg4, arg8, arg9, flagFilter); if (sp3C == NULL) { return NULL; } mlMtxIdent(); func_80252C08(arg2, arg3, arg4, 0); mlMtx_apply_vec3f(arg6, &sp40); mlMtxIdent(); func_80252C08(NULL, arg3, 1.0f, 0); mlMtx_apply_vec3f(arg8, arg8); mlMtxIdent(); func_80252C08(arg2, arg3, arg4, 0); for(i = 0; i < 3; i++){ mlMtx_apply_vec3f(D_8037EAA8[i], D_8037EAA8[i]); } return sp3C; } BKCollisionTri *func_802E92AC(BKCollisionList *collisionList, BKVertexList *vertexList, f32 position[3], f32 radius, f32 arg4[3], s32 flagFilter) { BKCollisionGeo **start_geo; BKCollisionGeo **i_geo; BKCollisionGeo **end_geo; s32 i; s32 j; f32 min[3]; f32 max[3]; BKCollisionTri *start_tri; BKCollisionTri *i_tri; BKCollisionTri *end_tri; f32 tri_vtx_coord[3][3]; Vtx *vtx_pool; Vtx *i_vtx; f32 min_coord[3]; f32 max_coord[3]; BKCollisionGeo *temp_a2; f32 tri_edge[3][3]; f32 sp138[3][3]; f32 temp_f0_10; f32 temp_f0_2; f32 temp_f0_6; f32 tri_normal[3]; f32 temp_f0_8; f32 temp_f12_2; f32 temp_f14_2; f32 sp108[3]; f32 spFC[3]; f32 temp_f2_3; f32 temp_f2_6; f32 temp_f2_7; f32 spE4[3]; f32 projected_position[3]; f32 temp_f8; BKCollisionTri *spD0; s32 var_a2; s32 var_v1_2; for(i = 0; i < 3; i++){ min[i] = position[i] - (radius + 0.5); max[i] = position[i] + (radius + 0.5); } //check if any vertices are within range; temp_f0_2 = vtxList_getGlobalNorm(vertexList); for(i = 0; i < 3; i++){ if((max[i] <= -temp_f0_2)|| temp_f0_2 <= min[i]) return NULL; } //iterate over collision geometry intersect range spD0 = NULL; spE4[0] = spE4[1] = spE4[2] = 0.0f; collisionList_getIntersecting(collisionList, min, max, &start_geo, &end_geo); vtx_pool = vtxList_getVertices(vertexList); for(i_geo = start_geo; i_geo < end_geo; i_geo++){ //iterate over each triangle in collision geometry start_tri = (BKCollisionTri *)((BKCollisionGeo *)(collisionList + 1) + collisionList->unk10) + (*i_geo)->start_tri_index; end_tri = start_tri + (*i_geo)->tri_count; for(i_tri = start_tri; i_tri < end_tri; i_tri++){ //filter tri if (!(i_tri->flags & flagFilter)){ //get tri coords for(i = 0; i < 3; i++){ i_vtx = &vtx_pool[i_tri->unk0[i]]; tri_vtx_coord[i][0] = i_vtx->v.ob[0]; tri_vtx_coord[i][1] = i_vtx->v.ob[1]; tri_vtx_coord[i][2] = i_vtx->v.ob[2]; } //get tri bounding points min_coord[0] = tri_vtx_coord[0][0]; min_coord[1] = tri_vtx_coord[0][1]; min_coord[2] = tri_vtx_coord[0][2]; max_coord[0] = tri_vtx_coord[0][0]; max_coord[1] = tri_vtx_coord[0][1]; max_coord[2] = tri_vtx_coord[0][2]; for(i = 1; i < 3; i++){ for(j = 0; j < 3; j++){ if(tri_vtx_coord[i][j] < min_coord[j]){ min_coord[j] = tri_vtx_coord[i][j]; } if(max_coord[j] < tri_vtx_coord[i][j]){ max_coord[j] = tri_vtx_coord[i][j]; } } } //check if tri is within collision region if ((max[0] < min_coord[0]) || (max_coord[0] < min[0])) continue; if ((max[1] < min_coord[1]) || (max_coord[1] < min[1])) continue; if ((max[2] < min_coord[2]) || (max_coord[2] < min[2])) continue; //caluclate normal tri_edge[0][0] = tri_vtx_coord[1][0] - tri_vtx_coord[0][0];\ tri_edge[0][1] = tri_vtx_coord[1][1] - tri_vtx_coord[0][1];\ tri_edge[0][2] = tri_vtx_coord[1][2] - tri_vtx_coord[0][2]; tri_edge[1][0] = tri_vtx_coord[2][0] - tri_vtx_coord[0][0]; tri_edge[1][1] = tri_vtx_coord[2][1] - tri_vtx_coord[0][1]; tri_edge[1][2] = tri_vtx_coord[2][2] - tri_vtx_coord[0][2]; tri_normal[0] = (tri_edge[0][1] * tri_edge[1][2]) - (tri_edge[0][2] * tri_edge[1][1]); tri_normal[1] = (tri_edge[0][2] * tri_edge[1][0]) - (tri_edge[0][0] * tri_edge[1][2]); tri_normal[2] = (tri_edge[0][0] * tri_edge[1][1]) - (tri_edge[0][1] * tri_edge[1][0]); ml_vec3f_normalize(tri_normal); if ((tri_normal[0] == 0.0f) && (tri_normal[1] == 0.0f) && (tri_normal[2] == 0.0f)) continue; //project point onto triangle? sp138[0][0] = position[0] - tri_vtx_coord[0][0]; sp138[0][1] = position[1] - tri_vtx_coord[0][1]; sp138[0][2] = position[2] - tri_vtx_coord[0][2]; temp_f12_2 = (sp138[0][0] * tri_normal[0]) + (sp138[0][1] * tri_normal[1]) + (sp138[0][2] * tri_normal[2]); if((temp_f12_2 <= -(radius - 0.5)) || ((radius - 0.5) <= temp_f12_2)) continue; temp_f2_3 = (tri_normal[0] * tri_normal[0]) + (tri_normal[1] * tri_normal[1]) + (tri_normal[2]*tri_normal[2]); if (temp_f2_3 == 0.0f) continue; temp_f0_6 = -temp_f12_2 / temp_f2_3; projected_position[0] = position[0] + (tri_normal[0] * temp_f0_6); projected_position[1] = position[1] + (tri_normal[1] * temp_f0_6); projected_position[2] = position[2] + (tri_normal[2] * temp_f0_6); //??? var_a2 = (ABS_F(tri_normal[0]) > ABS_F(tri_normal[1])) ? 0 : 1; var_a2 = (ABS_F(tri_normal[2]) > ABS_F(tri_normal[var_a2])) ? 2 : var_a2; sp108[0] = projected_position[(var_a2 + 1) % 3] - tri_vtx_coord[0][(var_a2 + 1) % 3]; sp108[1] = tri_edge[0][(var_a2 + 1) % 3]; sp108[2] = tri_edge[1][(var_a2 + 1) % 3]; spFC[0] = projected_position[(var_a2 + 2) % 3] - tri_vtx_coord[0][(var_a2 + 2) % 3]; spFC[1] = tri_edge[0][(var_a2 + 2) % 3]; spFC[2] = tri_edge[1][(var_a2 + 2) % 3]; temp_f14_2 = (sp108[1] * spFC[2]) - (spFC[1] * sp108[2]); temp_f2_6 = ((sp108[0] * spFC[2]) - (spFC[0] * sp108[2]))/ temp_f14_2; if ((0.0f <= temp_f2_6) && (temp_f2_6 <= 1)){ temp_f0_8 = ((sp108[1] * spFC[0]) - (spFC[1] * sp108[0]))/temp_f14_2; if(1) if((0.0f <= temp_f0_8) && ((temp_f0_8 <= 1))){ if((temp_f2_6 + temp_f0_8 <= 1)){ spD0 = i_tri; spE4[0] = spE4[0] + tri_normal[0]; spE4[1] = spE4[1] + tri_normal[1]; spE4[2] = spE4[2] + tri_normal[2]; continue; } } } for(i = 0; i < 3; i++){ sp138[i][0] = position[0] - tri_vtx_coord[i][0]; sp138[i][1] = position[1] - tri_vtx_coord[i][1]; sp138[i][2] = position[2] - tri_vtx_coord[i][2]; if((sp138[i][0] * sp138[i][0]) + (sp138[i][1] * sp138[i][1]) + (sp138[i][2] * sp138[i][2]) < (radius *radius)){ spD0 = i_tri; spE4[0] = spE4[0] + tri_normal[0]; spE4[1] = spE4[1] + tri_normal[1]; spE4[2] = spE4[2] + tri_normal[2]; break; } } if(i < 3) continue; for(i = 0; i < 3; i++){ tri_edge[i][0] = tri_vtx_coord[(i + 1)%3][0] - tri_vtx_coord[i][0];\ tri_edge[i][1] = tri_vtx_coord[(i + 1)%3][1] - tri_vtx_coord[i][1];\ tri_edge[i][2] = tri_vtx_coord[(i + 1)%3][2] - tri_vtx_coord[i][2]; temp_f2_7 = (tri_edge[i][0] * tri_edge[i][0]) + (tri_edge[i][1] * tri_edge[i][1]) + (tri_edge[i][2] * tri_edge[i][2]); ml_vec3f_normalize(tri_edge[i]); temp_f0_10 = (tri_edge[i][0] * sp138[i][0]) + (tri_edge[i][1] * sp138[i][1]) + (tri_edge[i][2] * sp138[i][2]); if ((temp_f0_10 >= 0.0f) && ((temp_f0_10 *temp_f0_10) <= temp_f2_7)){ projected_position[0] = sp138[i][0] - (tri_edge[i][0] * temp_f0_10); projected_position[1] = sp138[i][1] - (tri_edge[i][1] * temp_f0_10); projected_position[2] = sp138[i][2] - (tri_edge[i][2] * temp_f0_10); if((projected_position[0] * projected_position[0]) + (projected_position[1] * projected_position[1]) + (projected_position[2] * projected_position[2]) < (radius * radius)) { spD0 = i_tri; spE4[0] = spE4[0] + tri_normal[0]; spE4[1] = spE4[1] + tri_normal[1]; spE4[2] = spE4[2] + tri_normal[2]; break; } } } } } } if (spD0 != NULL) { ml_vec3f_normalize_copy(arg4, spE4); } func_802E6D20(spD0, vertexList); return spD0; } BKCollisionTri *func_802E9DD8(BKCollisionList *collisionList, BKVertexList *vtxList, f32 posA[3], f32 *rotA, f32 scaleA, f32 posB[3], f32 radB, f32 arg7[3], s32 arg8) { f32 sp34[3]; BKCollisionTri *sp30; s32 i; // check if (sphere around vtx's) <= ((distance between origins) - (radius of B)) if ((vtxList->global_norm * scaleA) <= (ml_vec3f_distance(posB, posA) - radB)) { return NULL; } mlMtxIdent(); func_80252CC4(posA, rotA, scaleA, NULL); mlMtx_apply_vec3f(sp34, posB); sp30 = func_802E92AC(collisionList, vtxList, &sp34, radB / scaleA, arg7, arg8); if (sp30 == 0) { return NULL; } mlMtxIdent(); func_80252C08(posA, rotA, scaleA, NULL); mlMtx_apply_vec3f(posB, sp34); mlMtxIdent(); func_80252C08(NULL, rotA, 1.0f, NULL); mlMtx_apply_vec3f(arg7, arg7); mlMtxIdent(); func_80252C08(posA, rotA, scaleA, NULL); for(i = 0; i < 3; i++){ mlMtx_apply_vec3f(D_8037EAA8[i], D_8037EAA8[i]); } return sp30; }