static __inline__ int check_shadow_line_walk(const AABBOX bbox, const FRUSTUM frustum, const VECTOR3 light_dir, Uint32 mask, const float* hit) { AABBOX tmp_bbox; VECTOR3 walk; int i, k, result, intersect; intersect = 0; result = check_aabb_in_frustum_no_out_mask(bbox, frustum, mask); if (result == INSIDE) return result; else if (result == INTERSECT) intersect = 1; for (i = 0, k = 1; k <= mask; i++, k += k) { if ((k & mask) && (hit[i] > 0.0f)) { VScale(walk, light_dir, hit[i]); VAdd(tmp_bbox.bbmin, bbox.bbmin, walk); VAdd(tmp_bbox.bbmax, bbox.bbmax, walk); result = check_aabb_in_frustum_no_out_mask(tmp_bbox, frustum, mask); if (result == INSIDE) return result; else if (result == INTERSECT) intersect = 1; } } if (intersect != 0) return INTERSECT; else return OUTSIDE; }
void DriftCorrection(void) { static float MagHeadingX, MagHeadingY; static float ErrorCourse; static float Scaled_Omega_P[3], Scaled_Omega_I[3]; static float AccMagnitude, AccWeight; // Roll and Pitch AccMagnitude = sqrt(Acc_V[0]*Acc_V[0] + Acc_V[1]*Acc_V[1] + Acc_V[2]*Acc_V[2]); AccMagnitude = AccMagnitude / (float)GRAVITY; // Scale to gravity. // dynamic weighting of Accerometer info (reliability filter) // weight for Accerometer info ( < 0.5G = 0.0, 1G = 1.0 , > 1.5G = 0.0) AccWeight = constrain(1 - 2 * abs(1 - AccMagnitude), 0, 1); VCross(&RollPitchError[0], &Acc_V[0], &DCM_M[2][0]); //adjust the ground of reference VScale(&Omega_P[0], &RollPitchError[0], Kp_RollPitch * AccWeight); VScale(&Scaled_Omega_I[0], &RollPitchError[0], Ki_RollPitch * AccWeight); VAdd(Omega_I,Omega_I, Scaled_Omega_I); // Yaw - drift correction based on compass magnetic heading MagHeadingX = cos(MagHeading); MagHeadingY = sin(MagHeading); ErrorCourse = (DCM_M[0][0] * MagHeadingY) - (DCM_M[1][0] * MagHeadingX); VScale(YawError,&DCM_M[2][0], ErrorCourse); VScale(&Scaled_Omega_P[0], &YawError[0], Kp_Yaw); VAdd(Omega_P, Omega_P, Scaled_Omega_P); VScale(&Scaled_Omega_I[0], &YawError[0], Ki_Yaw); VAdd(Omega_I,Omega_I, Scaled_Omega_I); } // DriftCorrection
void Normalize(void) { static float Error = 0.0; static float Temp[3][3]; static float Renorm = 0.0; static boolean Problem = FALSE; static byte r; Error= -VDot(&DCM_M[0][0], &DCM_M[1][0]) * 0.5; //eq.19 VScale(&Temp[0][0], &DCM_M[1][0], Error); //eq.19 VScale(&Temp[1][0], &DCM_M[0][0], Error); //eq.19 VAdd(&Temp[0][0], &Temp[0][0], &DCM_M[0][0]); //eq.19 VAdd(&Temp[1][0], &Temp[1][0], &DCM_M[1][0]); //eq.19 VCross(&Temp[2][0],&Temp[0][0], &Temp[1][0]); // c= a * b eq.20 #if EXTENDED == 1 for ( r= 0; r < 3; r++ ) { Renorm= VDot(&Temp[r][0],&Temp[r][0]); if ( Renorm < 1.5625 && Renorm > 0.64 ) Renorm = 0.5 * (3.0 - Renorm); //eq.21 else if ( Renorm < 100.0 && Renorm > 0.01 ) Renorm = 1.0 / sqrt( Renorm ); else Problem = TRUE; VScale(&DCM_M[r][0], &Temp[r][0], Renorm); } if ( Problem ) // Our solution is blowing up and we will force back to initial condition. Hope we are not upside down! { DCM_M[0][0] = 1.0; DCM_M[0][1] = 0.0; DCM_M[0][2] = 0.0; DCM_M[1][0] = 0.0; DCM_M[1][1] = 1.0; DCM_M[1][2] = 0.0; DCM_M[2][0] = 0.0; DCM_M[2][1] = 0.0; DCM_M[2][2] = 1.0; Problem = TRUE; } #else for ( r= 0; r < 3; r++ ) { Renorm = 0.5 * (3.0 - VDot(&Temp[r][0], &Temp[r][0])); //eq.21 VScale(&DCM_M[r][0], &Temp[r][0], Renorm); } #endif // EXTENDED } // Normalize
void MUpdate(void) { static byte i, j, k; static float op[3]; for ( i = 0; i < 3 ; i++) { Gyro_V[i] = (float)Gyro[i] * GyroToRadian; Acc_V[i] = (float)Acc[i]; } VAdd(&Omega[0], &Gyro_V[0], &Omega_I[0]); VAdd(&Omega_V[0], &Omega[0], &Omega_P[0]); AccAdjust(); // remove centrifugal accelerations. #if CORRECT_DRIFT == 1 Update_M[0][0] = 0; Update_M[0][1] = -G_Dt * Omega_V[2]; //-z Update_M[0][2] = G_Dt * Omega_V[1]; //y Update_M[1][0] = G_Dt * Omega_V[2]; //z Update_M[1][1] = 0; Update_M[1][2] = -G_Dt * Omega_V[0]; //-x Update_M[2][0] = -G_Dt * Omega_V[1]; //-y Update_M[2][1] = G_Dt * Omega_V[0]; //x Update_M[2][2] = 0; #else // no drift correction Update_M[0][0] = 0; Update_M[0][1] = -G_Dt * Gyro_V[2]; //-z Update_M[0][2] = G_Dt * Gyro_V[1]; //y Update_M[1][0] = G_Dt * Gyro_V[2]; //z Update_M[1][1] = 0; Update_M[1][2] = -G_Dt * Gyro_V[0]; Update_M[2][0] = -G_Dt * Gyro_V[1]; Update_M[2][1] = G_Dt * Gyro_V[0]; Update_M[2][2] = 0; #endif for( i = 0; i < 3; i++ ) for ( j = 0; j < 3; j++ ) { for ( k = 0; k < 3; k++ ) op[k] = DCM_M[i][k] * Update_M[k][j]; Temp_M[i][j] = op[0] + op[1] + op[2]; } for ( i = 0; i < 3; i++ ) for (j = 0; j < 3; j++ ) DCM_M[i][j] += Temp_M[i][j]; } // MUpdate
// キャラクターに当たっていたら押し出す処理を行う( chk_ch に ch が当たっていたら ch が離れる ) void Chara_Collision( CHARA *ch, VECTOR *ch_MoveVec, CHARA *chk_ch ) { VECTOR ChkChToChVec ; VECTOR PushVec ; VECTOR ChPosition ; float Length ; // 移動後の ch の座標を算出 ChPosition = VAdd( ch->Position, *ch_MoveVec ) ; // 当たっていなかったら何もしない if( HitCheck_Capsule_Capsule( ChPosition, VAdd( ChPosition, VGet( 0.0f, CHARA_HIT_HEIGHT, 0.0f ) ), CHARA_HIT_WIDTH, chk_ch->Position, VAdd( chk_ch->Position, VGet( 0.0f, CHARA_HIT_HEIGHT, 0.0f ) ), CHARA_HIT_WIDTH ) == TRUE ) { // 当たっていたら ch が chk から離れる処理をする // chk_ch から ch へのベクトルを算出 ChkChToChVec = VSub( ChPosition, chk_ch->Position ) ; // Y軸は見ない ChkChToChVec.y = 0.0f ; // 二人の距離を算出 Length = VSize( ChkChToChVec ) ; // chk_ch から ch へのベクトルを正規化( ベクトルの長さを 1.0f にする ) PushVec = VScale( ChkChToChVec, 1.0f / Length ) ; // 押し出す距離を算出、もし二人の距離から二人の大きさを引いた値に押し出し力を足して離れてしまう場合は、ぴったりくっつく距離に移動する if( Length - CHARA_HIT_WIDTH * 2.0f + CHARA_HIT_PUSH_POWER > 0.0f ) { float TempY ; TempY = ChPosition.y ; ChPosition = VAdd( chk_ch->Position, VScale( PushVec, CHARA_HIT_WIDTH * 2.0f ) ) ; // Y座標は変化させない ChPosition.y = TempY ; } else { // 押し出し ChPosition = VAdd( ChPosition, VScale( PushVec, CHARA_HIT_PUSH_POWER ) ) ; } } // 当たり判定処理後の移動ベクトルをセット *ch_MoveVec = VSub( ChPosition, ch->Position ) ; }
void Bullet::ShotController(VECTOR start,VECTOR target) { if (counter % 10 == 0) { for (j = 0; j < BULLET; j++) { if (bullet[j] == 2 & bulletLocation[j].z < -50 & bulletLocation[j].z > -150) { Calculator(j, bulletLocation[j], target); } } } for (j = 0; j < BULLET; j++) { if (bullet[j]==1 | bullet[j]==2 | bullet[j]==3) { //現在位置のベクトルに移動ベクトルを加算 bulletLocation[j] = VAdd(bulletLocation[j], move[j]); } if (bulletLocation[j].z < -210.0f | bulletLocation[j].z > 10.0f) { bullet[j] = 0; } } }
static void begin_depthmap_pass(Shader *self) { // 描画先を影用深度記録画像にする SetDrawScreen(self->depthmap_screen); // 影用深度記録画像を真っ白にクリア SetBackgroundColor(255, 255, 255); ClearDrawScreen(); SetBackgroundColor(0, 0, 0); // カメラのタイプを正射影タイプにセット、描画範囲も指定 SetupCamera_Ortho(13250.0f); // 描画する奥行き範囲をセット SetCameraNearFar(10.0f, 13050.0f); // カメラの位置と注視点はステージ全体が見渡せる位置 VECTOR LightTarget = VGet(3620.0f, 0.0f, 3830.0f); // カメラの向きはライトの向き VECTOR LightDirection = VScale(GetLightDirection(), -12400.0f); // カメラの位置と注視点はステージ全体が見渡せる位置 VECTOR LightPosition = VAdd(LightTarget, LightDirection); SetCameraPositionAndTarget_UpVecY(LightPosition, LightTarget); self->light_camera_view_matrix = GetCameraViewMatrix(); self->light_camera_projection_matrix = GetCameraProjectionMatrix(); SetUseVertexShader(self->depthmap_vs); SetUsePixelShader(self->depthmap_ps); }
static int tri_bbox(void * obj, vector * min, vector * max) { tri * t = (tri *) obj; vector v1, v2; VAdd(&t->v0, &t->edge1, &v1); VAdd(&t->v0, &t->edge2, &v2); min->x = MYMIN( t->v0.x , MYMIN( v1.x , v2.x )); min->y = MYMIN( t->v0.y , MYMIN( v1.y , v2.y )); min->z = MYMIN( t->v0.z , MYMIN( v1.z , v2.z )); max->x = MYMAX( t->v0.x , MYMAX( v1.x , v2.x )); max->y = MYMAX( t->v0.y , MYMAX( v1.y , v2.y )); max->z = MYMAX( t->v0.z , MYMAX( v1.z , v2.z )); return 1; }
void Stage::drawMap(){ for(int d = 0; d < depth; ++d){ for(int w = 0; w < width; ++w){ for(int h = 0; h <= mapchip[d][w].height; ++h){ MV1SetPosition(mapchip[d][w].definition->image, VAdd(VGet(d*chipsize, h*chipheight, w*chipsize), VGet(chipsize/2, -chipheight/2, chipsize/2))); MV1DrawModel(mapchip[d][w].definition->image); } } } }
static __inline__ int check_shadow_line_walk_outside(const AABBOX bbox, const FRUSTUM frustum, const VECTOR3 light_dir, Uint32 mask, const float* hit) { AABBOX tmp_bbox; VECTOR3 walk; int i, k; if (check_aabb_outside_frustum(bbox, frustum, mask) != OUTSIDE) return INTERSECT; for (i = 0, k = 1; k <= mask; i++, k += k) { if ((k & mask) && (hit[i] > 0.0f)) { VScale(walk, light_dir, hit[i]); VAdd(tmp_bbox.bbmin, bbox.bbmin, walk); VAdd(tmp_bbox.bbmax, bbox.bbmax, walk); if (check_aabb_outside_frustum(tmp_bbox, frustum, mask) != OUTSIDE) return INTERSECT; } } return OUTSIDE; }
/* void ** Convert_Line_World_To_View(FeaturePtr world_line, Viewport *vp, ** FeaturePtr res) ** Converts a line from world into view. Used by the placement routines. */ void Convert_Line_World_To_View(FeaturePtr world_line, Viewport *vp, FeaturePtr res) { Vector temp_v; /* Convert the direction.*/ MVMul(vp->world_to_view.matrix, world_line->f_vector, res->f_vector); /* Convert the point.*/ MVMul(vp->world_to_view.matrix, world_line->f_point, temp_v); VAdd(vp->world_to_view.displacement, temp_v, res->f_point); }
void GenSiteCoords () { VecR t; int j, n; DO_MOL { for (j = 0; j < sitesMol; j ++) { MVMul (t, mol[n].rMatT.u, mSite[j].r); VAdd (site[sitesMol * n + j].r, mol[n].r, t); } } }
/* ** void ** Convert_World_To_View(Vector *world_verts, Vertex *view_verts, ** short num_verts, Viewport *vp) ** Takes an array of vertices from world to view. ** world_verts: the vertices in world. ** view_verts: the vertices in view. ** num_verts: the number of vertices to convert. ** vp: the viewport to use for the transformation. */ void Convert_World_To_View(Vector *world_verts, Vertex *view_verts, short num_verts, Viewport *vp) { int i; Vector temp_v; for ( i = 0 ; i < num_verts; i++ ) { MVMul(vp->world_to_view.matrix, world_verts[i], temp_v); VAdd(vp->world_to_view.displacement, temp_v, view_verts[i].view); } }
void Cenemy::draw() { if(state != STATE_LIVE) return; //モデルの描画 // MV1DrawModel(model); //ボディの描画 DrawCone3D(VAdd(Penemy->pos,VGet(0,15,0)),VAdd(Penemy->pos,VGet(0,7,0)),4,80,0xff4444,0xff9999,TRUE) ; DrawSphere3D(Penemy->pos,this->body_rudius,80,0xff44444,0xff9999,TRUE); DrawSphere3D(VSub(Penemy->pos,VGet(0,10,0)),3,80,0xff4444,0xff9999,TRUE); DrawCone3D(VSub(Penemy->pos,VGet(0,25,0)),VSub(Penemy->pos,VGet(0,15,0)),2,80,0xff4444,0xff9999,TRUE) ; for(int i = 0;i < 4;i++) { for(int k = 0; k < AMMO_MAX*2;k++) { if(this->enemy_shot_state[i][k] == STATE_LIVE) { DrawSphere3D(this->enemy_shot_pos[i][k],2,24,0xddffdd,0xddffdd,TRUE); } } } }
void Ccamera::draw() { SetCameraPositionAndTarget_UpVecY(VAdd(Pcamera->pos,VGet(0,15,0)),Pplayer->Preticle->pos); /*switch(Pplayer->target_type) { case FREE: SetCameraPositionAndTarget_UpVecY(VAdd(Pplayer->pos,VGet(0,15,0)),Preticle->pos); break; case TARGET: SetCameraPositionAndTarget_UpVecY(VAdd(Pplayer->pos,VGet(0,11,0)),Penemy->pos); break; }*/ }
/* void ** Convert_Plane_World_To_View(FeaturePtr world_plane, Viewport *vp, ** FeaturePtr res) ** Converts a plane from world into view. Used by the placement routines. */ void Convert_Plane_World_To_View(FeaturePtr world_plane, Viewport *vp,FeaturePtr res) { Matrix transp; Vector temp_v; /* Convert the point.*/ MVMul(vp->world_to_view.matrix, world_plane->f_point, temp_v); VAdd(vp->world_to_view.displacement, temp_v, res->f_point); /* Convert the normal. */ MTrans(vp->view_to_world.matrix, transp); MVMul(transp, world_plane->f_vector, res->f_vector); }
void GenSiteCoords () { RMat rMat; VecR t; int j, n; DO_MOL { BuildRotMatrix (&rMat, &mol[n].q, 1); for (j = 0; j < sitesMol; j ++) { MVMul (t, rMat.u, mSite[j].r); VAdd (site[sitesMol * n + j].r, mol[n].r, t); } } }
///BaseObject::MovingManager void BaseObject::MoveManager::move(vector<int>& models, int order, const Position& pos, Position& topos){ current_dir = path[order]; topos = pos + dir[current_dir]; for(auto& model : models){ setObjectDirection(model); } diff = VAdd(diff, VGet(dir[current_dir].y*chipsize*moving_rate, 0.0f, dir[current_dir].x*chipsize*moving_rate)); //高さが違うとき if(Stage::getHeight(topos) != Stage::getHeight(pos)){ initJumpmotion(pos, topos); jump_path -= jump_dist*moving_rate; switch(jump){ case UP: if(jump_path < jump_height){ jump_dist *= -1; } break; case DOWN: if(jump_path < jump_height + step){ jump_dist *= -1; } break; } diff = VAdd(diff, VGet(0.0f, jump_dist*moving_rate, 0.0f)); if(Stage::getID(pos) == 1 && Stage::getID(topos) == 2){ diff = VSub(diff, VGet(0.0f, chipheight/2*moving_rate, 0.0f)); } else if(Stage::getID(pos) == 2 && Stage::getID(topos) == 1){ diff = VAdd(diff, VGet(0.0f, chipheight/2*moving_rate, 0.0f)); } } }
/// <summary> 柵を傾けます </summary> void tilt(const Matrix &mat) { auto w2 = Vec3(0, height, 0).transform(mat); w2.y -= height; for (const auto i : Rep(5)) { vertices[i * 2 + 1].pos = VAdd(vertices[i * 2 + 1].pos, (VECTOR)w2); } }
static Vector Closest_Line_Point(Vector dir, Vector line_pt, Vector pt) { Vector result; double temp_d; /* Need to find a perpendicular from the point to the line. */ VSub(pt, line_pt, result); temp_d = VDot(result, dir) / VDot(dir, dir); VScalarMul(dir, temp_d, result); VAdd(result, line_pt, result); return result; }
void Bullet::Update(char input[]) { if (_bulletType == BULLET_TYPE_PLAYER_HORMING&&_targetEnemy!=NULL) { VECTOR c; c = VSub(_targetEnemy->GetTranslation(), _translation); c = VNorm(c); c = VScale(c, _count*(5.0 / 180.0)); _direction = VAdd(c, _direction); _direction = VNorm(_direction); } _translation = VAdd(_translation, VScale(_direction, _speed)); if (_bulletType == BULLET_TYPE_ENEMY) { if ((_translation.x*_translation.x + _translation.z*_translation.z >= ACTIVE_RADIUS*ACTIVE_RADIUS) || _translation.y <= ACTIVE_LOWEST || _translation.y >= ACTIVE_HIGHEST) { _direction = VScale(_direction, -1); } } ++_count; }
static void Translate_Bicubic_Patch(OBJECT *Object, VECTOR Vector, TRANSFORM *) { int i, j; BICUBIC_PATCH *Patch = (BICUBIC_PATCH *) Object; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { VAdd(Patch->Control_Points[i][j], Patch->Control_Points[i][j], Vector); } } Precompute_Patch_Values(Patch); Compute_Bicubic_Patch_BBox(Patch); }
flt shade_phong(ray * incident, vector * hit, vector * N, vector * L, flt specpower){ vector H, V; flt inten; V = incident->d; VScale(&V, -1.0); VAdd(&V, L, &H); VScale(&H, 0.5); VNorm(&H); inten = VDot(N, &H); if (inten > 0.0) inten = pow(inten, specpower); else inten = 0.0; return inten; }
static FeatureData Combine_Plane_Line_Constraints(FeaturePtr c1, FeaturePtr c2) { double dot; double alpha; Vector temp_v; FeatureData result; /* The result is inconsistent if the line is parallel to but not in the ** plane, the line if it is parallel and in the plane, or the point ** of intersection otherwise. */ dot = VDot( c1->f_vector, c2->f_vector ); if ( IsZero(dot) ) { /* The line and plane are parallel. */ if ( Point_On_Plane(c1->f_vector, c1->f_value, c2->f_point) ) { /* The line lies in the plane. */ return *c2; } else { result.f_type = inconsistent_feature; return result; } } /* Find the intersection point. */ alpha = ( VDot(c1->f_vector, c1->f_point) - VDot(c1->f_vector, c2->f_point) ) / dot; result.f_type = point_feature; VScalarMul(c2->f_vector, alpha, temp_v); VAdd(temp_v, c2->f_point, result.f_point); return result; }
// プレイヤーの処理 void Player_Process( void ) { VECTOR UpMoveVec ; // 方向ボタン「↑」を入力をしたときのプレイヤーの移動方向ベクトル VECTOR LeftMoveVec ; // 方向ボタン「←」を入力をしたときのプレイヤーの移動方向ベクトル VECTOR MoveVec ; // このフレームの移動ベクトル int JumpFlag ; // ジャンプフラグ int i ; // プレイヤーの移動方向のベクトルを算出 { // 方向ボタン「↑」を押したときのプレイヤーの移動ベクトルはカメラの視線方向からY成分を抜いたもの UpMoveVec = VSub( cam.Target, cam.Eye ) ; UpMoveVec.y = 0.0f ; // 方向ボタン「←」を押したときのプレイヤーの移動ベクトルは上を押したときの方向ベクトルとY軸のプラス方向のベクトルに垂直な方向 LeftMoveVec = VCross( UpMoveVec, VGet( 0.0f, 1.0f, 0.0f ) ) ; // 二つのベクトルを正規化( ベクトルの長さを1.0にすること ) UpMoveVec = VNorm( UpMoveVec ) ; LeftMoveVec = VNorm( LeftMoveVec ) ; } // このフレームでの移動ベクトルを初期化 MoveVec = VGet( 0.0f, 0.0f, 0.0f ) ; // ジャンプフラグを倒す JumpFlag = 0 ; // パッドの3ボタンと左シフトがどちらも押されていなかったらプレイヤーの移動処理 if( CheckHitKey( KEY_INPUT_LSHIFT ) == 0 && ( inp.NowInput & PAD_INPUT_C ) == 0 ) { // 方向ボタン「←」が入力されたらカメラの見ている方向から見て左方向に移動する if( inp.NowInput & PAD_INPUT_LEFT ) { // 移動ベクトルに「←」が入力された時の移動ベクトルを加算する MoveVec = VAdd( MoveVec, LeftMoveVec ) ; } else // 方向ボタン「→」が入力されたらカメラの見ている方向から見て右方向に移動する if( inp.NowInput & PAD_INPUT_RIGHT ) { // 移動ベクトルに「←」が入力された時の移動ベクトルを反転したものを加算する MoveVec = VAdd( MoveVec, VScale( LeftMoveVec, -1.0f ) ) ; } // 方向ボタン「↑」が入力されたらカメラの見ている方向に移動する if( inp.NowInput & PAD_INPUT_UP ) { // 移動ベクトルに「↑」が入力された時の移動ベクトルを加算する MoveVec = VAdd( MoveVec, UpMoveVec ) ; } else // 方向ボタン「↓」が入力されたらカメラの方向に移動する if( inp.NowInput & PAD_INPUT_DOWN ) { // 移動ベクトルに「↑」が入力された時の移動ベクトルを反転したものを加算する MoveVec = VAdd( MoveVec, VScale( UpMoveVec, -1.0f ) ) ; } // ボタン1が押されていたらジャンプフラグを立てる if( inp.EdgeInput & PAD_INPUT_A ) { JumpFlag = 1 ; } } // 移動方向を移動速度でスケーリングする MoveVec = VScale( MoveVec, CHARA_MOVE_SPEED ) ; // プレイヤーキャラ以外との当たり判定を行う for( i = 0 ; i < NOTPLAYER_NUM ; i ++ ) { Chara_Collision( &pl.CharaInfo, &MoveVec, &npl[ i ].CharaInfo ) ; } // キャラクターを動作させる処理を行う Chara_Process( &pl.CharaInfo, MoveVec, JumpFlag ) ; }
// キャラクターの移動処理 void Chara_Move( CHARA *ch, VECTOR MoveVector ) { int i, j, k ; // 汎用カウンタ変数 int MoveFlag ; // 水平方向に移動したかどうかのフラグ( 0:移動していない 1:移動した ) int HitFlag ; // ポリゴンに当たったかどうかを記憶しておくのに使う変数( 0:当たっていない 1:当たった ) MV1_COLL_RESULT_POLY_DIM HitDim ; // キャラクターの周囲にあるポリゴンを検出した結果が代入される当たり判定結果構造体 int KabeNum ; // 壁ポリゴンと判断されたポリゴンの数 int YukaNum ; // 床ポリゴンと判断されたポリゴンの数 MV1_COLL_RESULT_POLY *Kabe[ CHARA_MAX_HITCOLL ] ; // 壁ポリゴンと判断されたポリゴンの構造体のアドレスを保存しておくためのポインタ配列 MV1_COLL_RESULT_POLY *Yuka[ CHARA_MAX_HITCOLL ] ; // 床ポリゴンと判断されたポリゴンの構造体のアドレスを保存しておくためのポインタ配列 MV1_COLL_RESULT_POLY *Poly ; // ポリゴンの構造体にアクセスするために使用するポインタ( 使わなくても済ませられますがプログラムが長くなるので・・・ ) HITRESULT_LINE LineRes ; // 線分とポリゴンとの当たり判定の結果を代入する構造体 VECTOR OldPos ; // 移動前の座標 VECTOR NowPos ; // 移動後の座標 // 移動前の座標を保存 OldPos = ch->Position ; // 移動後の座標を算出 NowPos = VAdd( ch->Position, MoveVector ) ; // キャラクターの周囲にあるステージポリゴンを取得する // ( 検出する範囲は移動距離も考慮する ) HitDim = MV1CollCheck_Sphere( stg.ModelHandle, -1, ch->Position, CHARA_ENUM_DEFAULT_SIZE + VSize( MoveVector ) ) ; // x軸かy軸方向に 0.01f 以上移動した場合は「移動した」フラグを1にする if( fabs( MoveVector.x ) > 0.01f || fabs( MoveVector.z ) > 0.01f ) { MoveFlag = 1 ; } else { MoveFlag = 0 ; } // 検出されたポリゴンが壁ポリゴン( XZ平面に垂直なポリゴン )か床ポリゴン( XZ平面に垂直ではないポリゴン )かを判断する { // 壁ポリゴンと床ポリゴンの数を初期化する KabeNum = 0 ; YukaNum = 0 ; // 検出されたポリゴンの数だけ繰り返し for( i = 0 ; i < HitDim.HitNum ; i ++ ) { // XZ平面に垂直かどうかはポリゴンの法線のY成分が0に限りなく近いかどうかで判断する if( HitDim.Dim[ i ].Normal.y < 0.000001f && HitDim.Dim[ i ].Normal.y > -0.000001f ) { // 壁ポリゴンと判断された場合でも、キャラクターのY座標+1.0fより高いポリゴンのみ当たり判定を行う if( HitDim.Dim[ i ].Position[ 0 ].y > ch->Position.y + 1.0f || HitDim.Dim[ i ].Position[ 1 ].y > ch->Position.y + 1.0f || HitDim.Dim[ i ].Position[ 2 ].y > ch->Position.y + 1.0f ) { // ポリゴンの数が列挙できる限界数に達していなかったらポリゴンを配列に追加 if( KabeNum < CHARA_MAX_HITCOLL ) { // ポリゴンの構造体のアドレスを壁ポリゴンポインタ配列に保存する Kabe[ KabeNum ] = &HitDim.Dim[ i ] ; // 壁ポリゴンの数を加算する KabeNum ++ ; } } } else { // ポリゴンの数が列挙できる限界数に達していなかったらポリゴンを配列に追加 if( YukaNum < CHARA_MAX_HITCOLL ) { // ポリゴンの構造体のアドレスを床ポリゴンポインタ配列に保存する Yuka[ YukaNum ] = &HitDim.Dim[ i ] ; // 床ポリゴンの数を加算する YukaNum ++ ; } } } } // 壁ポリゴンとの当たり判定処理 if( KabeNum != 0 ) { // 壁に当たったかどうかのフラグは初期状態では「当たっていない」にしておく HitFlag = 0 ; // 移動したかどうかで処理を分岐 if( MoveFlag == 1 ) { // 壁ポリゴンの数だけ繰り返し for( i = 0 ; i < KabeNum ; i ++ ) { // i番目の壁ポリゴンのアドレスを壁ポリゴンポインタ配列から取得 Poly = Kabe[ i ] ; // ポリゴンとキャラクターが当たっていなかったら次のカウントへ if( HitCheck_Capsule_Triangle( NowPos, VAdd( NowPos, VGet( 0.0f, CHARA_HIT_HEIGHT, 0.0f ) ), CHARA_HIT_WIDTH, Poly->Position[ 0 ], Poly->Position[ 1 ], Poly->Position[ 2 ] ) == FALSE ) continue ; // ここにきたらポリゴンとキャラクターが当たっているということなので、ポリゴンに当たったフラグを立てる HitFlag = 1 ; // 壁に当たったら壁に遮られない移動成分分だけ移動する { VECTOR SlideVec ; // キャラクターをスライドさせるベクトル // 進行方向ベクトルと壁ポリゴンの法線ベクトルに垂直なベクトルを算出 SlideVec = VCross( MoveVector, Poly->Normal ) ; // 算出したベクトルと壁ポリゴンの法線ベクトルに垂直なベクトルを算出、これが // 元の移動成分から壁方向の移動成分を抜いたベクトル SlideVec = VCross( Poly->Normal, SlideVec ) ; // それを移動前の座標に足したものを新たな座標とする NowPos = VAdd( OldPos, SlideVec ) ; } // 新たな移動座標で壁ポリゴンと当たっていないかどうかを判定する for( j = 0 ; j < KabeNum ; j ++ ) { // j番目の壁ポリゴンのアドレスを壁ポリゴンポインタ配列から取得 Poly = Kabe[ j ] ; // 当たっていたらループから抜ける if( HitCheck_Capsule_Triangle( NowPos, VAdd( NowPos, VGet( 0.0f, CHARA_HIT_HEIGHT, 0.0f ) ), CHARA_HIT_WIDTH, Poly->Position[ 0 ], Poly->Position[ 1 ], Poly->Position[ 2 ] ) == TRUE ) break ; } // j が KabeNum だった場合はどのポリゴンとも当たらなかったということなので // 壁に当たったフラグを倒した上でループから抜ける if( j == KabeNum ) { HitFlag = 0 ; break ; } } } else { // 移動していない場合の処理 // 壁ポリゴンの数だけ繰り返し for( i = 0 ; i < KabeNum ; i ++ ) { // i番目の壁ポリゴンのアドレスを壁ポリゴンポインタ配列から取得 Poly = Kabe[ i ] ; // ポリゴンに当たっていたら当たったフラグを立てた上でループから抜ける if( HitCheck_Capsule_Triangle( NowPos, VAdd( NowPos, VGet( 0.0f, CHARA_HIT_HEIGHT, 0.0f ) ), CHARA_HIT_WIDTH, Poly->Position[ 0 ], Poly->Position[ 1 ], Poly->Position[ 2 ] ) == TRUE ) { HitFlag = 1 ; break ; } } } // 壁に当たっていたら壁から押し出す処理を行う if( HitFlag == 1 ) { // 壁からの押し出し処理を試みる最大数だけ繰り返し for( k = 0 ; k < CHARA_HIT_TRYNUM ; k ++ ) { // 壁ポリゴンの数だけ繰り返し for( i = 0 ; i < KabeNum ; i ++ ) { // i番目の壁ポリゴンのアドレスを壁ポリゴンポインタ配列から取得 Poly = Kabe[ i ] ; // キャラクターと当たっているかを判定 if( HitCheck_Capsule_Triangle( NowPos, VAdd( NowPos, VGet( 0.0f, CHARA_HIT_HEIGHT, 0.0f ) ), CHARA_HIT_WIDTH, Poly->Position[ 0 ], Poly->Position[ 1 ], Poly->Position[ 2 ] ) == FALSE ) continue ; // 当たっていたら規定距離分キャラクターを壁の法線方向に移動させる NowPos = VAdd( NowPos, VScale( Poly->Normal, CHARA_HIT_SLIDE_LENGTH ) ) ; // 移動した上で壁ポリゴンと接触しているかどうかを判定 for( j = 0 ; j < KabeNum ; j ++ ) { // 当たっていたらループを抜ける Poly = Kabe[ j ] ; if( HitCheck_Capsule_Triangle( NowPos, VAdd( NowPos, VGet( 0.0f, CHARA_HIT_HEIGHT, 0.0f ) ), CHARA_HIT_WIDTH, Poly->Position[ 0 ], Poly->Position[ 1 ], Poly->Position[ 2 ] ) == TRUE ) break ; } // 全てのポリゴンと当たっていなかったらここでループ終了 if( j == KabeNum ) break ; } // i が KabeNum ではない場合は全部のポリゴンで押し出しを試みる前に全ての壁ポリゴンと接触しなくなったということなのでループから抜ける if( i != KabeNum ) break ; } } } // 床ポリゴンとの当たり判定 if( YukaNum != 0 ) { // ジャンプ中且つ上昇中の場合は処理を分岐 if( ch->State == 2 && ch->JumpPower > 0.0f ) { float MinY ; // 天井に頭をぶつける処理を行う // 一番低い天井にぶつける為の判定用変数を初期化 MinY = 0.0f ; // 当たったかどうかのフラグを当たっていないを意味する0にしておく HitFlag = 0 ; // 床ポリゴンの数だけ繰り返し for( i = 0 ; i < YukaNum ; i ++ ) { // i番目の床ポリゴンのアドレスを床ポリゴンポインタ配列から取得 Poly = Yuka[ i ] ; // 足先から頭の高さまでの間でポリゴンと接触しているかどうかを判定 LineRes = HitCheck_Line_Triangle( NowPos, VAdd( NowPos, VGet( 0.0f, CHARA_HIT_HEIGHT, 0.0f ) ), Poly->Position[ 0 ], Poly->Position[ 1 ], Poly->Position[ 2 ] ) ; // 接触していなかったら何もしない if( LineRes.HitFlag == FALSE ) continue ; // 既にポリゴンに当たっていて、且つ今まで検出した天井ポリゴンより高い場合は何もしない if( HitFlag == 1 && MinY < LineRes.Position.y ) continue ; // ポリゴンに当たったフラグを立てる HitFlag = 1 ; // 接触したY座標を保存する MinY = LineRes.Position.y ; } // 接触したポリゴンがあったかどうかで処理を分岐 if( HitFlag == 1 ) { // 接触した場合はキャラクターのY座標を接触座標を元に更新 NowPos.y = MinY - CHARA_HIT_HEIGHT ; // Y軸方向の速度は反転 ch->JumpPower = -ch->JumpPower ; } } else { float MaxY ; // 下降中かジャンプ中ではない場合の処理 // 床ポリゴンに当たったかどうかのフラグを倒しておく HitFlag = 0 ; // 一番高い床ポリゴンにぶつける為の判定用変数を初期化 MaxY = 0.0f ; // 床ポリゴンの数だけ繰り返し for( i = 0 ; i < YukaNum ; i ++ ) { // i番目の床ポリゴンのアドレスを床ポリゴンポインタ配列から取得 Poly = Yuka[ i ] ; // ジャンプ中かどうかで処理を分岐 if( ch->State == 2 ) { // ジャンプ中の場合は頭の先から足先より少し低い位置の間で当たっているかを判定 LineRes = HitCheck_Line_Triangle( VAdd( NowPos, VGet( 0.0f, CHARA_HIT_HEIGHT, 0.0f ) ), VAdd( NowPos, VGet( 0.0f, -1.0f, 0.0f ) ), Poly->Position[ 0 ], Poly->Position[ 1 ], Poly->Position[ 2 ] ) ; } else { // 走っている場合は頭の先からそこそこ低い位置の間で当たっているかを判定( 傾斜で落下状態に移行してしまわない為 ) LineRes = HitCheck_Line_Triangle( VAdd( NowPos, VGet( 0.0f, CHARA_HIT_HEIGHT, 0.0f ) ), VAdd( NowPos, VGet( 0.0f, -40.0f, 0.0f ) ), Poly->Position[ 0 ], Poly->Position[ 1 ], Poly->Position[ 2 ] ) ; } // 当たっていなかったら何もしない if( LineRes.HitFlag == FALSE ) continue ; // 既に当たったポリゴンがあり、且つ今まで検出した床ポリゴンより低い場合は何もしない if( HitFlag == 1 && MaxY > LineRes.Position.y ) continue ; // ポリゴンに当たったフラグを立てる HitFlag = 1 ; // 接触したY座標を保存する MaxY = LineRes.Position.y ; } // 床ポリゴンに当たったかどうかで処理を分岐 if( HitFlag == 1 ) { // 当たった場合 // 接触したポリゴンで一番高いY座標をキャラクターのY座標にする NowPos.y = MaxY ; // Y軸方向の移動速度は0に ch->JumpPower = 0.0f ; // もしジャンプ中だった場合は着地状態にする if( ch->State == 2 ) { // 移動していたかどうかで着地後の状態と再生するアニメーションを分岐する if( MoveFlag ) { // 移動している場合は走り状態に Chara_PlayAnim( ch, 1 ) ; ch->State = 1 ; } else { // 移動していない場合は立ち止り状態に Chara_PlayAnim( ch, 4 ) ; ch->State = 0 ; } // 着地時はアニメーションのブレンドは行わない ch->AnimBlendRate = 1.0f ; } } else { // 床コリジョンに当たっていなくて且つジャンプ状態ではなかった場合は if( ch->State != 2 ) { // ジャンプ中にする ch->State = 2 ; // ちょっとだけジャンプする ch->JumpPower = CHARA_FALL_UP_POWER ; // アニメーションは落下中のものにする Chara_PlayAnim( ch, 3 ) ; } } } } // 新しい座標を保存する ch->Position = NowPos ; // キャラクターのモデルの座標を更新する MV1SetPosition( ch->ModelHandle, ch->Position ) ; // 検出したキャラクターの周囲のポリゴン情報を開放する MV1CollResultPolyDimTerminate( HitDim ) ; }
static FeatureData Combine_Line_Line_Constraints(FeaturePtr c1, FeaturePtr c2) { Vector cross; double param1; Vector temp_v1, temp_v2, temp_v3, temp_v4; Vector point1; FeatureData result; /* The result is inconsistent if the lines don't intersect, a point ** otherwise (their point of intersection. */ VCross(c1->f_vector, c2->f_vector, cross); if ( VZero(cross) ) { /* The lines are parallel. */ if ( Point_On_Line( c1->f_vector, c1->f_point, c2->f_point) ) return *c1; else { result.f_type = inconsistent_feature; return result; } } /* They still may or may not intersect. */ VSub(c1->f_point, c2->f_point, temp_v1); VCross(c2->f_vector, temp_v1, temp_v2); VCross(c1->f_vector, temp_v1, temp_v3); /* temp_v3 and temp_v2 are both perp to temp_v1. */ /* If temp_v2 is 0, then the lines intersect at c1->f_point1. */ /* If temp_v3 is 0, then the lines intersect at c1->f_point2. */ /* If temp_v2 and temp_v3 are parallel, the lines intersect somewhere. */ /* Otherwise they don't. */ if ( VZero(temp_v2) ) { result.f_type = point_feature; result.f_point = c1->f_point; return result; } else if ( VZero(temp_v2) ) { result.f_type = point_feature; result.f_point = c2->f_point; return result; } VCross(temp_v2, temp_v3, temp_v4); if ( ! VZero(temp_v4) ) { result.f_type = inconsistent_feature; return result; } /* Get the parameter for the point of intersection. */ if ( ! IsZero(cross.z) ) param1 = temp_v2.z / cross.z; else if ( ! IsZero(cross.y) ) param1 = temp_v2.y / cross.y; else param1 = temp_v2.x / cross.x; VScalarMul(c1->f_vector, param1, temp_v1); VAdd(temp_v1, c1->f_point, point1); result.f_type = point_feature; result.f_point = point1; return result; }
void bump_map(VECTOR EPoint, TNORMAL *Tnormal, VECTOR normal) { DBL xcoor = 0.0, ycoor = 0.0; int index, index2, index3; COLOUR colour1, colour2, colour3; VECTOR p1, p2, p3; VECTOR bump_normal; VECTOR xprime, yprime, zprime, Temp; DBL Length; DBL Amount = Tnormal->Amount; IMAGE *Image = Tnormal->Vals.Image; Make_ColourA(colour1, 0.0, 0.0, 0.0, 0.0, 0.0); Make_ColourA(colour2, 0.0, 0.0, 0.0, 0.0, 0.0); Make_ColourA(colour3, 0.0, 0.0, 0.0, 0.0, 0.0); /* going to have to change this */ /* need to know if bump point is off of image for all 3 points */ if (map(EPoint, (TPATTERN *) Tnormal, &xcoor, &ycoor)) { return; } else { image_colour_at(Image, xcoor, ycoor, colour1, &index); } xcoor--; ycoor++; if (xcoor < 0.0) { xcoor += (DBL)Image->iwidth; } else { if (xcoor >= Image->iwidth) { xcoor -= (DBL)Image->iwidth; } } if (ycoor < 0.0) { ycoor += (DBL)Image->iheight; } else { if (ycoor >= (DBL)Image->iheight) { ycoor -= (DBL)Image->iheight; } } image_colour_at(Image, xcoor, ycoor, colour2, &index2); xcoor += 2.0; if (xcoor < 0.0) { xcoor += (DBL)Image->iwidth; } else { if (xcoor >= Image->iwidth) { xcoor -= (DBL)Image->iwidth; } } image_colour_at(Image, xcoor, ycoor, colour3, &index3); if (Image->Colour_Map == NULL || Image->Use_Colour_Flag) { p1[X] = 0; p1[Y] = Amount * (GREY_SCALE( colour1 )); p1[Z] = 0; p2[X] = -1; p2[Y] = Amount * (GREY_SCALE( colour2 )); p2[Z] = 1; p3[X] = 1; p3[Y] = Amount * (GREY_SCALE( colour3 )); p3[Z] = 1; } else { p1[X] = 0; p1[Y] = Amount * index; p1[Z] = 0; p2[X] = -1; p2[Y] = Amount * index2; p2[Z] = 1; p3[X] = 1; p3[Y] = Amount * index3; p3[Z] = 1; } /* we have points 1,2,3 for a triangle now we need the surface normal for it */ VSub(xprime, p1, p2); VSub(yprime, p3, p2); VCross(bump_normal, yprime, xprime); VNormalize(bump_normal, bump_normal); Assign_Vector(yprime, normal); Make_Vector(Temp, 0.0, 1.0, 0.0); VCross(xprime, yprime, Temp); VLength(Length, xprime); if (Length < EPSILON) { if (fabs(normal[Y] - 1.0) < Small_Tolerance) { Make_Vector(yprime, 0.0, 1.0, 0.0); Make_Vector(xprime, 1.0, 0.0, 0.0); Length = 1.0; } else { Make_Vector(yprime, 0.0, -1.0, 0.0); Make_Vector(xprime, 1.0, 0.0, 0.0); Length = 1.0; } } VScaleEq(xprime, 1.0 / Length); VCross(zprime, xprime, yprime); VNormalizeEq(zprime); VScaleEq(xprime, bump_normal[X]); VScaleEq(yprime, bump_normal[Y]); VScaleEq(zprime, bump_normal[Z]); VAdd(Temp, xprime, yprime); VScaleEq(zprime, -1); VAdd(normal, Temp, zprime); }
static void facets (const VECTOR EPoint, const TNORMAL *Tnormal, VECTOR normal, TraceThreadData *Thread) { int i; int thisseed; DBL sum, minsum; VECTOR sv, tv, dv, t1, add, newnormal, pert; DBL scale; int UseSquare; int UseUnity; DBL Metric; VECTOR *cv = Thread->Facets_Cube; Metric = Tnormal->Vals.Facets.Metric; UseSquare = (Metric == 2 ); UseUnity = (Metric == 1 ); VNormalize( normal, normal ); if ( Tnormal->Vals.Facets.UseCoords ) { Assign_Vector(tv,EPoint); } else { Assign_Vector(tv,normal); } if ( Tnormal->Vals.Facets.Size < 1e-6 ) { scale = 1e6; } else { scale = 1. / Tnormal->Vals.Facets.Size; } VScaleEq( tv, scale ); /* * Check to see if the input point is in the same unit cube as the last * call to this function, to use cache of cubelets for speed. */ thisseed = PickInCube(tv, t1); if (thisseed != Thread->Facets_Last_Seed) { /* * No, not same unit cube. Calculate the random points for this new * cube and its 80 neighbours which differ in any axis by 1 or 2. * Why distance of 2? If there is 1 point in each cube, located * randomly, it is possible for the closest random point to be in the * cube 2 over, or the one two over and one up. It is NOT possible * for it to be two over and two up. Picture a 3x3x3 cube with 9 more * cubes glued onto each face. */ /* Now store a points for this cube and each of the 80 neighbour cubes. */ int cvc = 0; for (add[X] = -2.0; add[X] < 2.5; add[X] +=1.0) { for (add[Y] = -2.0; add[Y] < 2.5; add[Y] += 1.0) { for (add[Z] = -2.0; add[Z] < 2.5; add[Z] += 1.0) { /* For each cubelet in a 5x5 cube. */ if ((fabs(add[X])>1.5)+(fabs(add[Y])>1.5)+(fabs(add[Z])>1.5) <= 1.0) { /* Yes, it's within a 3d knight move away. */ VAdd(sv, tv, add); PickInCube(sv, t1); cv[cvc][X] = t1[X]; cv[cvc][Y] = t1[Y]; cv[cvc][Z] = t1[Z]; cvc++; } } } } Thread->Facets_Last_Seed = thisseed; Thread->Facets_CVC = cvc; } /* * Find the point with the shortest distance from the input point. */ VSub(dv, cv[0], tv); if ( UseSquare ) { minsum = VSumSqr(dv); } else if ( UseUnity ) { minsum = dv[X]+dv[Y]+dv[Z]; } else { minsum = pow(fabs(dv[X]), Metric)+ pow(fabs(dv[Y]), Metric)+ pow(fabs(dv[Z]), Metric); } Assign_Vector( newnormal, cv[0] ); /* Loop for the 81 cubelets to find closest. */ for (i = 1; i < Thread->Facets_CVC; i++) { VSub(dv, cv[i], tv); if ( UseSquare ) { sum = VSumSqr(dv); } else { if ( UseUnity ) { sum = dv[X]+dv[Y]+dv[Z]; } else { sum = pow(fabs(dv[X]), Metric)+ pow(fabs(dv[Y]), Metric)+ pow(fabs(dv[Z]), Metric); } } if (sum < minsum) { minsum = sum; Assign_Vector( newnormal, cv[i] ); } } if ( Tnormal->Vals.Facets.UseCoords ) { DNoise( pert, newnormal ); VDot( sum, pert, normal ); VScale( newnormal, normal, sum ); VSubEq( pert, newnormal ); VAddScaledEq( normal, Tnormal->Vals.Facets.UseCoords, pert ); } else { Assign_Vector( normal, newnormal ); } }
inline VECTOR operator +(const VECTOR& lhs, const VECTOR& rhs) { return VAdd(lhs, rhs); }