/* * Camera control routines * * Copyright (C) 2006-2007 Alejandro Valenzuela Roca, * * http://mexinetica.com/~lanjoe9 * * This file is part of MotorJ, a free framework for videogame development. * * * * MotorJ is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * MotorJ is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with MotorJ. If not, see . */ #include "cam_ctl.h" void init_cam_ctl_def(cam_ctl * cam){ cam->mode = DESCENTERA; v3_j(&cam->dirv); v3_k(&cam->dir); mul_scal(-1, &cam->dir); v3_0(&cam->pos); cam->objective = NULL; cam->follow_ctl.displ_factor = 0.04; cam->follow_ctl.spin_factor = 0.05; cam->restr.orientGRVTY = 0; cam->grvty = NULL; cam->follow_ctl.follow_model = GRADUAL; cam->follow_ctl.dist_max_objVR = 10; cam->follow_ctl.dist_min_objVR = 3; cam->follow_ctl.dist_min_objHZ = 3; cam->follow_ctl.dist_max_objHZ = 10; cam->piggy_ctl.piggyback = NULL; v3_0(&cam->piggy_ctl.piggyback_despl); cam->dsc_ctl.fwd = 0; cam->dsc_ctl.backwd = 0; cam->dsc_ctl.ascent = 0; cam->dsc_ctl.descent = 0; cam->dsc_ctl.strf_left = 0; cam->dsc_ctl.strf_right = 0; cam->dsc_ctl.spin_nosedown = 0; cam->dsc_ctl.spin_noseup = 0; cam->dsc_ctl.spin_left = 0; cam->dsc_ctl.spin_right = 0; cam->dsc_ctl.spin_CCW = 0; cam->dsc_ctl.spin_CW = 0; cam->dsc_ctl.factor_mov = 0.18; cam->dsc_ctl.factor_movHZ = 0.18; cam->dsc_ctl.factor_movVR = 0.18; cam->dsc_ctl.factor_spinVR = 0.015; cam->dsc_ctl.factor_spinHZ = 0.015; cam->dsc_ctl.factor_spinCWCCW = 0.020; } void update_cam_auto(cam_ctl * cam){ vector3 tmp, tmp2; // cam->dirhz is now a public variable of cam static float distVR_f = 1; static float distVR_f_0 = 1; static float distHZ_f = 1; switch(cam->mode){ case DESCENTERA:{ if (cam->dsc_ctl.fwd){ vec_sum(cam->dsc_ctl.factor_mov, cam->dir, &cam->pos); } if (cam->dsc_ctl.backwd){ vec_sum(-cam->dsc_ctl.factor_mov, cam->dir, &cam->pos); } if(cam->dsc_ctl.ascent){ vec_sum(cam->dsc_ctl.factor_mov, cam->dirv, &cam->pos); } if(cam->dsc_ctl.descent){ vec_sum(-cam->dsc_ctl.factor_mov, cam->dirv, &cam->pos); } if (cam->dsc_ctl.strf_left){ cross(cam->dir,cam->dirv,&cam->dirhz); normalize(&cam->dirhz); vec_sum(-cam->dsc_ctl.factor_movHZ,cam->dirhz,&cam->pos); } if (cam->dsc_ctl.strf_right){ cross(cam->dir,cam->dirv,&cam->dirhz); normalize(&cam->dirhz); vec_sum(cam->dsc_ctl.factor_movHZ,cam->dirhz,&cam->pos); } if (cam->dsc_ctl.spin_nosedown){ vec_copy(cam->dir,&tmp); vec_copy(cam->dirv,&tmp2); vec_sum(-cam->dsc_ctl.factor_spinVR, cam->dirv, &tmp); vec_sum(cam->dsc_ctl.factor_spinVR, cam->dir, &tmp2); vec_copy(tmp,&cam->dir); vec_copy(tmp2,&cam->dirv); normalize(&cam->dir); normalize(&cam->dirv); } if (cam->dsc_ctl.spin_noseup){ vec_copy(cam->dir,&tmp); vec_copy(cam->dirv,&tmp2); vec_sum(cam->dsc_ctl.factor_spinVR, cam->dirv, &tmp); vec_sum(-cam->dsc_ctl.factor_spinVR, cam->dir, &tmp2); vec_copy(tmp,&cam->dir); vec_copy(tmp2,&cam->dirv); normalize(&cam->dir); normalize(&cam->dirv); } if (cam->dsc_ctl.spin_left){ cross(cam->dirv,cam->dir,&cam->dirhz); vec_copy(cam->dir,&tmp); vec_sum(cam->dsc_ctl.factor_spinHZ, cam->dirhz, &tmp); vec_copy(tmp,&cam->dir); normalize(&cam->dir); } if (cam->dsc_ctl.spin_right){ cross(cam->dirv,cam->dir,&cam->dirhz); vec_copy(cam->dir,&tmp); vec_sum(-cam->dsc_ctl.factor_spinHZ, cam->dirhz, &tmp); vec_copy(tmp,&cam->dir); normalize(&cam->dir); } if (cam->dsc_ctl.spin_CCW){ cross(cam->dirv,cam->dir,&cam->dirhz); vec_copy(cam->dirv,&tmp2); vec_sum(cam->dsc_ctl.factor_spinCWCCW, cam->dirhz, &tmp2); vec_copy(tmp2,&cam->dirv); normalize(&cam->dirv); } if (cam->dsc_ctl.spin_CW){ cross(cam->dirv,cam->dir,&cam->dirhz); vec_copy(cam->dirv,&tmp2); vec_sum(-cam->dsc_ctl.factor_spinCWCCW, cam->dirhz, &tmp2); vec_copy(tmp2,&cam->dirv); normalize(&cam->dirv); } } break; case FREE_FOLLOW:{ vector3 dir, dirv;//, cam->dirhz; float distancia, distanciaHZ, distanciaVR; vector3 movHZ; if (cam->objective){ vector3 dirtmp; //girar cámara para ver el objective vec_copy(*cam->objective,&dir); vec_sum(-1,cam->pos,&dir); normalize(&dir); vec_copy(dir,&dirtmp); vec_sum(-1,cam->dir,&dirtmp); if (cam->follow_ctl.follow_model==GRADUAL){ if (vec_norm(dirtmp)<0.02){ vec_copy(dir,&cam->dir); } else vec_sum(cam->follow_ctl.spin_factor,dirtmp,&cam->dir); } else vec_copy(dir,&cam->dir); // Obtener el vector de la "dirección horizontal" v3_est(dir.z,0,-dir.x,&cam->dirhz); // con este vector, obtener el de la dirección vertical cross(cam->dirhz,dir,&dirv); normalize(&dirv); if (dirv.y < 0){ mul_scal(-1,&dirv); } vec_copy(dirv,&cam->dirv); //if (cam->restr.orientarGRVD){ //FIXME!! soporte para vector gravedad distinto a eje y //} movHZ.x = cam->objective->x-cam->pos.x; movHZ.z = cam->objective->z-cam->pos.z; movHZ.y = 0; distanciaHZ = sqrt((movHZ.x*movHZ.x) + (movHZ.z*movHZ.z)); normalize(&movHZ); if (distanciaHZ > (cam->follow_ctl.dist_max_objHZ/distHZ_f)){ distHZ_f = 1.8; switch(cam->follow_ctl.follow_model){ case GRADUAL:{ vec_sum(cam->follow_ctl.displ_factor*distanciaHZ*distHZ_f,movHZ,&cam->pos); } break; case IMMEDIATE:{ vec_sum((cam->follow_ctl.dist_min_objHZ-distanciaHZ),movHZ,&cam->pos); } break; } } else{ distHZ_f = 1; } if (distanciaHZ < cam->follow_ctl.dist_min_objHZ){ switch(cam->follow_ctl.follow_model){ case GRADUAL:{ vec_sum(-cam->follow_ctl.displ_factor*3/(3.0+(distanciaHZ-cam->follow_ctl.dist_min_objHZ)),movHZ,&cam->pos); } break; case IMMEDIATE:{ vec_sum(-(cam->follow_ctl.dist_min_objHZ-distanciaHZ),movHZ,&cam->pos); } break; } } distanciaVR = fabs((cam->objective->y - cam->pos.y)); if (distanciaVR > cam->follow_ctl.dist_max_objVR){ vector3 tmpvert; v3_j(&tmpvert); if (cam->objective->y>cam->pos.y) tmpvert.y *= -1; switch(cam->follow_ctl.follow_model){ case GRADUAL:{ vec_sum(-cam->follow_ctl.displ_factor*distanciaVR,tmpvert,&cam->pos); } break; case IMMEDIATE:{ cam->pos.y = cam->objective->y+cam->follow_ctl.dist_min_objVR; //vec_sum(-(cam->follow_ctl.dist_min_obj-distancia),dir,&cam->pos); } break; } } if (cam->restr.viewSUP && (cam->pos.y - (cam->follow_ctl.dist_min_objVR*distVR_f) < cam->objective->y)){ vector3 tmpvert; //alejar distVR_f = 2.0; v3_j(&tmpvert); tmpvert.y = fabs(cam->pos.y - cam->objective->y)+1.0; switch(cam->follow_ctl.follow_model){ case GRADUAL:{ vec_sum(cam->follow_ctl.displ_factor,tmpvert,&cam->pos); } break; case IMMEDIATE:{ cam->pos.y = cam->objective->y+cam->follow_ctl.dist_min_objVR; //vec_sum(-(cam->follow_ctl.dist_min_obj-distancia),dir,&cam->pos); } break; } } else if (distanciaVR < cam->follow_ctl.dist_min_objVR){ vector3 tmpvert; //alejar v3_j(&tmpvert); switch(cam->follow_ctl.follow_model){ case GRADUAL:{ vec_sum(cam->follow_ctl.displ_factor*3/(3.0+fabs(cam->follow_ctl.dist_min_objVR-distanciaVR)),tmpvert,&cam->pos); } break; case IMMEDIATE:{ cam->pos.y = cam->objective->y+cam->follow_ctl.dist_min_objVR; //vec_sum(-(cam->follow_ctl.dist_min_obj-distancia),dir,&cam->pos); } break; } } else{ distVR_f = 1; } } } break; case FIXED_FOLLOW: { }break; } if (distVR_f != distVR_f_0){ //printf("distVR_f: %f -> %f\n",distVR_f_0,distVR_f); distVR_f_0 = distVR_f; } } void actualizar_cam_giros(cam_ctl * cam, ship_ctl &giros){ }