int moto_ray_intersect_plane(MotoRay *self, MotoIntersection *intersection, float point[3], float normal[3]) { float dif[3]; vector3_dif(dif, point, self->pos); float numer = vector3_dot(normal, dif); float denom = vector3_dot(normal, self->dir); if(fabs(denom) < MICRO) /* parallel */ { return 0; } float t = numer/denom; if(t < MICRO) { return 0; } intersection->hits[0].dist = t; intersection->hits[0].is_entering = 1; vector3_copy(intersection->hits[0].point, self->pos); point3_move(intersection->hits[0].point, self->dir, t); vector3_copy(intersection->hits[0].normal, normal); intersection->hits_num = 1; return 1; }
void moto_ray_transform(MotoRay *self, float m[16]) { float p[3], d[3]; point3_transform(p, m, self->pos); vector3_transform(d, m, self->dir); vector3_copy(self->pos, p); vector3_copy(self->dir, d); }
void moto_object_node_zoom(MotoObjectNode *self, gfloat val) { gfloat to_target[3], eye[3]; gfloat loc_pos[] = {0, 0, 0}; gfloat *matrix = moto_object_node_get_matrix(self, TRUE); point3_transform(eye, matrix, loc_pos); vector3_dif(to_target, self->priv->target, eye); if(vector3_length(to_target) < MICRO) { if(val > 0) return; gfloat az[] = {0, 0, 1}; gfloat n[3]; vector3_transform(n, matrix, az); point3_move(eye, n, 0.5); } else point3_move(eye, to_target, val); if(self->priv->parent) { gfloat *inverse = moto_object_node_get_inverse_matrix(self->priv->parent, TRUE); point3_transform(loc_pos, inverse, eye); } else { vector3_copy(loc_pos, eye); } moto_object_node_set_translate_array(self, loc_pos); }
void vector3_multiply_matrix3x3(const vector3* vector, const matrix3x3* matrix, vector3* result) { vector3 vector_t; if (vector==result){ vector3_copy(vector, &vector_t); vector=&vector_t; } result->x = vector->x * matrix->m[0][0] + vector->y * matrix->m[0][1] + vector->z * matrix->m[0][2]; result->y = vector->x * matrix->m[1][0] + vector->y * matrix->m[1][1] + vector->z * matrix->m[1][2]; result->z = vector->x * matrix->m[2][0] + vector->y * matrix->m[2][1] + vector->z * matrix->m[2][2]; }
static void add_some_enemies(u32b_t level) { vector3_t color; u32b_t i,n; // Get a random color for this wave based on the level color.s.x = random_rnd(&State->random,level-1)+2; color.s.y = random_rnd(&State->random,level-1)+2; color.s.z = random_rnd(&State->random,level-1)+2; // Add a wave n = State->nenemies; enemy_new_wave(&color, State->time, &State->random, &State->enemies, &State->nenemies, &State->senemies); // Update position of each enemy for(i=n; i<State->nenemies; i++) { vector3_copy(&State->path->position, &State->enemies[i].position); State->enemies[i].path = State->path->next; } }
void moto_object_node_set_rotate_order(MotoObjectNode *self, MotoRotateOrder order) { gfloat to_target[3], eye[3]; gfloat loc_pos[] = {0, 0, 0}; gfloat *matrix = moto_object_node_get_matrix(self, TRUE); point3_transform(eye, matrix, loc_pos); vector3_dif(to_target, self->priv->target, eye); gfloat dist = vector3_length(to_target); gfloat az[] = {0, 0, 1}; gfloat n[3]; vector3_transform(n, matrix, az); vector3_mult(to_target, n, -dist); vector3_copy(self->priv->target, eye); point3_move(self->priv->target, to_target, 1); moto_node_set_param_enum((MotoNode *)self, "ro", order); }
void vector3_test() { vector3 zero = {0,0,0}; vector3 one = {1,1,1}; vector3 y = {0,1,0}; vector3 half = {0.5,0.5,0.5}; vector3 a; vector3_invert(&a, &one); vector3_subtract(&a, &one, &a); vector3_add(&a, &a, &one); vector3_print(&a); vector3_multiply(&a, &one, 0.5); vector3_divide(&a, &a, 2); vector3_print(&a); vector3_reflect(&a, &one, &y); vector3_print(&a); vector3_scalar_sub(&a, &zero, -0.5); vector3_scalar_add(&a, &a, 0.5); vector3_print(&a); vector3_cross(&a, &one, &y); vector3_print(&a); srand(3); vector3_random(&a); vector3_print(&a); printf("%.2f %.2f\n", vector3_dot(&half, &y), vector3_angle(&half, &y)); printf("%.2f %.2f\n", vector3_distance(&one, &y), vector3_distancesq(&one, &y)); vector3_copy(&a, &one); printf("%.2f %.2f\n", vector3_length(&one), vector3_length(vector3_normalize(&a)) ); }
static void update_enemies_path() { vector3_t v; u32b_t i; // Update position of each enemy that has "started" for(i=0; i<State->nenemies; ) { // Move enemy towards next path point if( (State->enemies[i].start_time < State->time) && (State->enemies[i].path != State->path) ) { // Build vector poiting toward waypoint vector3_sub_vector(&State->enemies[i].path->position, &State->enemies[i].position, &v); // If waypoint is in reach, simply jump there and assign next node if( vector3_length(&v) < State->enemies[i].speed*BASE_SPEED ) { vector3_copy(&State->enemies[i].path->position, &State->enemies[i].position); State->enemies[i].path = State->enemies[i].path->next; // Move on to next entry i++; } else { // Just move towards it vector3_normalize(&v, &v); vector3_mult_scalar(&v,&v,State->enemies[i].speed*BASE_SPEED); vector3_add_vector(&State->enemies[i].position, &v, &State->enemies[i].position); // Move on to next entry i++; } } else if( State->enemies[i].path == State->path ) { // Enemy reached last path node! // Remove points from mana. State->player.mana -= State->enemies[i].health*0.1; // Notify GUI of the player hit. gui_game_event_hit(State->time,&State->enemies[i]); // Kill it (will move last entry into current); retest current. enemy_kill_enemy(i, State->enemies, &State->nenemies, State->senemies); } else { // Move on to next entry. i++; } } }
void moto_object_node_tumble_v(MotoObjectNode *self, gfloat da) { da = da*RAD_PER_DEG; gfloat ax[] = {1, 0, 0}; gfloat ay[] = {0, 1, 0}; gfloat az[] = {0, 0, 1}; gfloat u[3], v[3], n[3], t[3]; gfloat to_u[3], to_v[3], to_n[3]; gfloat to_eye[3], eye[3]; gfloat loc_pos[] = {0, 0, 0}; gfloat tumble_axis[] = {0, 1, 0}; gfloat target[3]; vector3_copy(target, self->priv->target); gfloat *matrix = moto_object_node_get_matrix(self, TRUE); vector3_transform(u, matrix, ax); vector3_transform(v, matrix, ay); vector3_transform(n, matrix, az); point3_transform(eye, matrix, loc_pos); vector3_dif(to_eye, eye, target); vector3_sum(to_u, to_eye, u); vector3_sum(to_v, to_eye, v); vector3_sum(to_n, to_eye, n); gfloat rm[16]; matrix44_rotate_from_axis(rm, da, tumble_axis[0], tumble_axis[1], tumble_axis[2]); /* eye rotation */ gfloat to_eye2[3]; point3_transform(to_eye2, rm, to_eye); /* u rotation */ gfloat to_u2[3]; vector3_transform(to_u2, rm, to_u); /* v rotation */ gfloat to_v2[3]; vector3_transform(to_v2, rm, to_v); /* n rotation */ gfloat to_n2[3]; vector3_transform(to_n2, rm, to_n); /* new eye, u, v, n */ vector3_sum(eye, to_eye2, target); vector3_dif(u, to_u2, to_eye2); vector3_dif(v, to_v2, to_eye2); vector3_dif(n, to_n2, to_eye2); vector3_normalize(u, t[0]); vector3_normalize(v, t[0]); vector3_normalize(n, t[0]); /* inverse global matrix */ gfloat igm[16]; matrix44_camera_inverse(igm, eye, u, v, n); /* global matrix */ gfloat gm[16], ambuf[16], detbuf; matrix44_inverse(gm, igm, ambuf, detbuf); if(fabs(detbuf) < MICRO) { moto_error("(moto_object_node_tumble) determinant is zero"); return; } /* local matrix */ gfloat lm[16]; gfloat *lmp = gm; if(self->priv->parent) { gfloat *parent_inverse = moto_object_node_get_inverse_matrix(self->priv->parent, TRUE); matrix44_mult(lm, parent_inverse, gm); lmp = lm; } gfloat translate[3]; translate_from_matrix44(translate, lmp); moto_object_node_set_translate_array(self, translate); gfloat euler[3], cosbuf; switch(self->priv->rotate_order) { case MOTO_ROTATE_ORDER_XYZ: euler_xyz_from_matrix44(euler, lmp, cosbuf); break; case MOTO_ROTATE_ORDER_XZY: euler_xzy_from_matrix44(euler, lmp, cosbuf); break; case MOTO_ROTATE_ORDER_YXZ: euler_yxz_from_matrix44(euler, lmp, cosbuf); break; case MOTO_ROTATE_ORDER_YZX: euler_yzx_from_matrix44(euler, lmp, cosbuf); break; case MOTO_ROTATE_ORDER_ZXY: euler_zxy_from_matrix44(euler, lmp, cosbuf); break; case MOTO_ROTATE_ORDER_ZYX: euler_zyx_from_matrix44(euler, lmp, cosbuf); break; } euler[0] *= DEG_PER_RAD; euler[1] *= DEG_PER_RAD; euler[2] *= DEG_PER_RAD; moto_object_node_set_rotate_array(self, euler); }
void moto_object_node_roll(MotoObjectNode *self, gfloat da) { da *= RAD_PER_DEG; gfloat ax[] = {1, 0, 0}; gfloat ay[] = {0, 1, 0}; gfloat az[] = {0, 0, 1}; gfloat u[3], v[3], n[3], t[3]; gfloat eye[3]; gfloat loc_pos[] = {0, 0, 0}; gfloat *matrix = moto_object_node_get_matrix(self, TRUE); point3_transform(eye, matrix, loc_pos); vector3_transform(u, matrix, ax); vector3_transform(v, matrix, ay); vector3_transform(n, matrix, az); gfloat c = cos(da); gfloat s = sin(da); vector3_copy(t, u); vector3_set(u, c*t[0] - s*v[0], c*t[1] - s*v[1], c*t[2] - s*v[2]); vector3_set(v, s*t[0] + c*v[0], s*t[1] + c*v[1], s*t[2] + c*v[2]); /* inverse global matrix */ gfloat igm[16]; matrix44_camera_inverse(igm, eye, u, v, n); /* global matrix */ gfloat gm[16], ambuf[16], detbuf; matrix44_inverse(gm, igm, ambuf, detbuf); if(fabs(detbuf) < MICRO) { moto_error("(moto_object_node_roll) determinant is zero"); return; } /* local matrix */ gfloat lm[16]; gfloat *lmp = gm; if(self->priv->parent) { gfloat *parent_inverse = moto_object_node_get_inverse_matrix(self->priv->parent, TRUE); matrix44_mult(lm, parent_inverse, gm); lmp = lm; } gfloat euler[3], cosbuf; switch(self->priv->rotate_order) { case MOTO_ROTATE_ORDER_XYZ: euler_xyz_from_matrix44(euler, lmp, cosbuf); break; case MOTO_ROTATE_ORDER_XZY: euler_xzy_from_matrix44(euler, lmp, cosbuf); break; case MOTO_ROTATE_ORDER_YXZ: euler_yxz_from_matrix44(euler, lmp, cosbuf); break; case MOTO_ROTATE_ORDER_YZX: euler_yzx_from_matrix44(euler, lmp, cosbuf); break; case MOTO_ROTATE_ORDER_ZXY: euler_zxy_from_matrix44(euler, lmp, cosbuf); break; case MOTO_ROTATE_ORDER_ZYX: euler_zyx_from_matrix44(euler, lmp, cosbuf); break; } euler[0] *= DEG_PER_RAD; euler[1] *= DEG_PER_RAD; euler[2] *= DEG_PER_RAD; moto_object_node_set_rotate_array(self, euler); }
int moto_ray_intersect_bound(MotoRay *self, MotoIntersection *intersection, float bound[6]) { float t_hit, numer, denom; float t_in = -100000; float t_out = 100000; int in_surf = 0, out_surf = 1; int i; for(i = 0; i < 6; i++) { switch(i) { case 0: numer = max_y - self->pos[1]; denom = self->dir[1]; break; case 1: numer = -min_y + self->pos[1]; denom = -self->dir[1]; break; case 2: numer = max_x - self->pos[0]; denom = self->dir[0]; break; case 3: numer = -min_x + self->pos[0]; denom = -self->dir[0]; break; case 4: numer = max_z - self->pos[2]; denom = self->dir[2]; break; case 5: numer = -min_z + self->pos[2]; denom = -self->dir[2]; break; } if(fabs(denom) < MICRO) /* parallel */ { if(numer < 0) return 0; } else { t_hit = numer / denom; if(denom > 0) { if(t_hit < t_out) { t_out = t_hit; out_surf = i; } } else { if(t_hit > t_in) { t_in = t_hit; in_surf = i; } } } if(t_in >= t_out) return 0; } intersection->hits_num = 0; if(t_in > MICRO) { intersection->hits[0].dist = t_in; intersection->hits[0].is_entering = 1; vector3_copy(intersection->hits[0].point, self->pos); point3_move(intersection->hits[0].point, self->dir, t_in); cube_normal(intersection->hits[0].normal, in_surf); intersection->hits_num++; } if(t_out > MICRO) { intersection->hits[intersection->hits_num].dist = t_out; intersection->hits[intersection->hits_num].is_entering = 0; vector3_copy(intersection->hits[intersection->hits_num].point, self->pos); point3_move(intersection->hits[intersection->hits_num].point, self->dir, t_out); cube_normal(intersection->hits[intersection->hits_num].normal, out_surf); intersection->hits_num++; } return (intersection->hits_num > 0); }
int moto_ray_intersect_sphere_2(MotoRay *self, MotoIntersection *intersection, float origin[3], float square_radius) { float tmp, dst[3]; vector3_dif(dst, self->pos, origin); float B = vector3_dot(dst, self->dir); float C = vector3_dot(dst, dst) - square_radius; float D = B*B - C; if(D > MICRO) { float sqrtD = sqrt(D); intersection->hits_num = 0; intersection->hits[0].dist = sqrtD - B; if(intersection->hits[0].dist > MICRO) { vector3_copy(intersection->hits[0].point, self->pos); point3_move(intersection->hits[0].point, self->dir, intersection->hits[0].dist); vector3_dif(intersection->hits[0].normal, intersection->hits[0].point, origin); vector3_normalize(intersection->hits[0].normal, tmp); intersection->hits[0].is_entering = \ (vector3_dot(intersection->hits[0].normal, self->dir) < 0); intersection->hits_num++; } intersection->hits[intersection->hits_num].dist = -sqrtD - B; if(intersection->hits[intersection->hits_num].dist > MICRO) { vector3_copy(intersection->hits[intersection->hits_num].point, self->pos); point3_move(intersection->hits[intersection->hits_num].point, self->dir, intersection->hits[intersection->hits_num].dist); vector3_dif(intersection->hits[intersection->hits_num].normal, intersection->hits[intersection->hits_num].point, origin); vector3_normalize(intersection->hits[intersection->hits_num].normal, tmp); intersection->hits[intersection->hits_num].is_entering = \ (vector3_dot(intersection->hits[intersection->hits_num].normal, self->dir) < 0); intersection->hits_num++; } return intersection->hits_num > 0; } else if(D >= 0 && D < MICRO) { intersection->hits_num = 0; intersection->hits[0].dist = -B; if(-B < MICRO) { vector3_copy(intersection->hits[0].point, self->pos); point3_move(intersection->hits[0].point, self->dir, intersection->hits[0].dist); vector3_dif(intersection->hits[0].normal, intersection->hits[0].point, origin); vector3_normalize(intersection->hits[0].normal, tmp); intersection->hits[0].is_entering = 0; intersection->hits_num = 1; } return intersection->hits_num > 0; } return 0; }
void moto_ray_copy(MotoRay *self, MotoRay *other) { vector3_copy(self->pos, other->pos); vector3_copy(self->dir, other->dir); }