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
// キャラクターに当たっていたら押し出す処理を行う( 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 ) ; }
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; }
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); }
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; }
void AdjustDipole () { real sFac; int n; DO_MOL { sFac = VLen (mol[n].s); VScale (mol[n].s, 1. / sFac); } }
void ComputeDipoleAccel () { real t; int n; DO_MOL { t = VDot (mol[n].sa, mol[n].s) + mInert * VLenSq (mol[n].sv); VVSAdd (mol[n].sa, - t, mol[n].s); VScale (mol[n].sa, 1. / mInert); } }
void InitAngVels () { real ang, angvFac; int n; angvFac = velMag / sqrt (1.5 * mInert); DO_MOL { ang = 2. * M_PI * RandR (); VSet (mol[n].sv, cos (ang), sin (ang), 0.); VScale (mol[n].sv, angvFac); } }
void InitVels () { int n; VZero (vSum); DO_MOL { VRand (&mol[n].rv); VScale (mol[n].rv, velMag); VVAdd (vSum, mol[n].rv); } DO_MOL VVSAdd (mol[n].rv, - 1. / nMol, vSum); }
void Compute_Rotation_Transform (TRANSFORM *transform, const VECTOR vector) { register DBL cosx, cosy, cosz, sinx, siny, sinz; MATRIX Matrix; VECTOR Radian_Vector; VScale (Radian_Vector, vector, M_PI_180); MIdentity (transform->matrix); cosx = cos (Radian_Vector[X]); sinx = sin (Radian_Vector[X]); cosy = cos (Radian_Vector[Y]); siny = sin (Radian_Vector[Y]); cosz = cos (Radian_Vector[Z]); sinz = sin (Radian_Vector[Z]); (transform->matrix) [1][1] = cosx; (transform->matrix) [2][2] = cosx; (transform->matrix) [1][2] = sinx; (transform->matrix) [2][1] = 0.0 - sinx; MTranspose (transform->inverse, transform->matrix); MIdentity (Matrix); Matrix [0][0] = cosy; Matrix [2][2] = cosy; Matrix [0][2] = 0.0 - siny; Matrix [2][0] = siny; MTimesA (transform->matrix, Matrix); MTranspose (Matrix); MTimesB (Matrix, transform->inverse); MIdentity (Matrix); Matrix [0][0] = cosz; Matrix [1][1] = cosz; Matrix [0][1] = sinz; Matrix [1][0] = 0.0 - sinz; MTimesA (transform->matrix, Matrix); MTranspose (Matrix); MTimesB (Matrix, transform->inverse); }
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 __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; }
static void wrinkles (const VECTOR EPoint, const TNORMAL *Tnormal, VECTOR normal) { register int i; register DBL scale = 1.0; VECTOR result, value, value2; Make_Vector(result, 0.0, 0.0, 0.0); for (i = 0; i < 10; scale *= 2.0, i++) { VScale(value2,EPoint,scale); DNoise(value, value2); result[X] += fabs(value[X] / scale); result[Y] += fabs(value[Y] / scale); result[Z] += fabs(value[Z] / scale); } /* Displace "normal". */ VAddScaledEq(normal, Tnormal->Amount, result); }
void Bullet::SuperShot(VECTOR start, VECTOR target, Player* player) { if (player->GetMp()>20) { if (key & PAD_INPUT_3) { if (bullet[i] == 0) { //使用されていないバレット配列のフラグをたてていく bullet[i] = 3; isGraze[i] = 0; Calculator(i, start, target); move[i] = VScale(move[i], 1.5f); isShot = -15; player->AddMp(-20); } i++; if (i == BULLET - 1) { i = 0; } } } }
void Bullet::SuperShot(VECTOR start, VECTOR target, Enemy* enemy) { if (enemy->GetMp()>20) { if (enFlag==3) { if (bullet[i] == 0) { //使用されていないバレット配列のフラグをたてていく bullet[i] = 3; isGraze[i] = 0; Calculator(i, start, target); move[i] = VScale(move[i], 1.5f); isShot = -15; enemy->AddMp(-20); } i++; if (i == BULLET - 1) { i = 0; } } } }
/* the real thing */ static void grid_intersect(grid * g, ray * ry) { flt tnear, tfar, offset; vector curpos, tmax, tdelta, pdeltaX, pdeltaY, pdeltaZ, nXp, nYp, nZp; gridindex curvox, step, out; int voxindex; objectlist * cur; if (ry->flags & RT_RAY_FINISHED) return; if (!grid_bounds_intersect(g, ry, &tnear, &tfar)) return; if (ry->maxdist < tnear) return; curpos = Raypnt(ry, tnear); pos2grid(g, &curpos, &curvox); offset = tnear; /* Setup X iterator stuff */ if (fabs(ry->d.x) < EPSILON) { tmax.x = FHUGE; tdelta.x = 0.0; step.x = 0; out.x = 0; /* never goes out of bounds on this axis */ } else if (ry->d.x < 0.0) { tmax.x = offset + ((voxel2x(g, curvox.x) - curpos.x) / ry->d.x); tdelta.x = g->voxsize.x / - ry->d.x; step.x = out.x = -1; } else { tmax.x = offset + ((voxel2x(g, curvox.x + 1) - curpos.x) / ry->d.x); tdelta.x = g->voxsize.x / ry->d.x; step.x = 1; out.x = g->xsize; } /* Setup Y iterator stuff */ if (fabs(ry->d.y) < EPSILON) { tmax.y = FHUGE; tdelta.y = 0.0; step.y = 0; out.y = 0; /* never goes out of bounds on this axis */ } else if (ry->d.y < 0.0) { tmax.y = offset + ((voxel2y(g, curvox.y) - curpos.y) / ry->d.y); tdelta.y = g->voxsize.y / - ry->d.y; step.y = out.y = -1; } else { tmax.y = offset + ((voxel2y(g, curvox.y + 1) - curpos.y) / ry->d.y); tdelta.y = g->voxsize.y / ry->d.y; step.y = 1; out.y = g->ysize; } /* Setup Z iterator stuff */ if (fabs(ry->d.z) < EPSILON) { tmax.z = FHUGE; tdelta.z = 0.0; step.z = 0; out.z = 0; /* never goes out of bounds on this axis */ } else if (ry->d.z < 0.0) { tmax.z = offset + ((voxel2z(g, curvox.z) - curpos.z) / ry->d.z); tdelta.z = g->voxsize.z / - ry->d.z; step.z = out.z = -1; } else { tmax.z = offset + ((voxel2z(g, curvox.z + 1) - curpos.z) / ry->d.z); tdelta.z = g->voxsize.z / ry->d.z; step.z = 1; out.z = g->zsize; } pdeltaX = ry->d; VScale(&pdeltaX, tdelta.x); pdeltaY = ry->d; VScale(&pdeltaY, tdelta.y); pdeltaZ = ry->d; VScale(&pdeltaZ, tdelta.z); nXp = Raypnt(ry, tmax.x); nYp = Raypnt(ry, tmax.y); nZp = Raypnt(ry, tmax.z); voxindex = curvox.z*g->xsize*g->ysize + curvox.y*g->xsize + curvox.x; while (1) { if (tmax.x < tmax.y && tmax.x < tmax.z) { cur = g->cells[voxindex]; while (cur != NULL) { if (ry->mbox[cur->obj->id] != ry->serial) { ry->mbox[cur->obj->id] = ry->serial; cur->obj->methods->intersect(cur->obj, ry); } cur = cur->next; } curvox.x += step.x; if (ry->maxdist < tmax.x || curvox.x == out.x) break; voxindex += step.x; tmax.x += tdelta.x; curpos = nXp; nXp.x += pdeltaX.x; nXp.y += pdeltaX.y; nXp.z += pdeltaX.z; } else if (tmax.z < tmax.y) { cur = g->cells[voxindex]; while (cur != NULL) { if (ry->mbox[cur->obj->id] != ry->serial) { ry->mbox[cur->obj->id] = ry->serial; cur->obj->methods->intersect(cur->obj, ry); } cur = cur->next; } curvox.z += step.z; if (ry->maxdist < tmax.z || curvox.z == out.z) break; voxindex += step.z*g->xsize*g->ysize; tmax.z += tdelta.z; curpos = nZp; nZp.x += pdeltaZ.x; nZp.y += pdeltaZ.y; nZp.z += pdeltaZ.z; } else { cur = g->cells[voxindex]; while (cur != NULL) { if (ry->mbox[cur->obj->id] != ry->serial) { ry->mbox[cur->obj->id] = ry->serial; cur->obj->methods->intersect(cur->obj, ry); } cur = cur->next; } curvox.y += step.y; if (ry->maxdist < tmax.y || curvox.y == out.y) break; voxindex += step.y*g->xsize; tmax.y += tdelta.y; curpos = nYp; nYp.x += pdeltaY.x; nYp.y += pdeltaY.y; nYp.z += pdeltaY.z; } if (ry->flags & RT_RAY_FINISHED) break; } }
void Compute_Cone_Data(OBJECT *Object) { DBL tlen, len, tmpf; VECTOR tmpv, axis, origin; CONE *Cone = (CONE *)Object; /* Process the primitive specific information */ if (fabs(Cone->apex_radius - Cone->base_radius) < EPSILON) { /* What we are dealing with here is really a cylinder */ Set_Flag(Cone, CYLINDER_FLAG); Compute_Cylinder_Data(Object); return; } if (Cone->apex_radius < Cone->base_radius) { /* Want the bigger end at the top */ Assign_Vector(tmpv,Cone->base); Assign_Vector(Cone->base,Cone->apex); Assign_Vector(Cone->apex,tmpv); tmpf = Cone->base_radius; Cone->base_radius = Cone->apex_radius; Cone->apex_radius = tmpf; } /* Find the axis and axis length */ VSub(axis, Cone->apex, Cone->base); VLength(len, axis); if (len < EPSILON) { Error("Degenerate cone/cylinder."); } else { VInverseScaleEq(axis, len); } /* Determine alignment */ tmpf = Cone->base_radius * len / (Cone->apex_radius - Cone->base_radius); VScale(origin, axis, tmpf); VSub(origin, Cone->base, origin); tlen = tmpf + len; Cone->dist = tmpf / tlen; Compute_Coordinate_Transform(Cone->Trans, origin, axis, Cone->apex_radius, tlen); /* Recalculate the bounds */ Compute_Cone_BBox(Cone); }
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 ); } }
bool Parametric::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread) { VECTOR P, D, IPoint; UV_VECT low_vect, hi_vect, uv; Ray New_Ray; DBL XRayMin, XRayMax, YRayMin, YRayMax, ZRayMin, ZRayMax, TPotRes, TLen; DBL Depth1, Depth2, temp, Len, TResult = HUGE_VAL; DBL low, hi, len; int MaxPrecompX, MaxPrecompY, MaxPrecompZ; int split, i = 0, Side1, Side2; int parX, parY; int i_flg; DBL Intervals_Low[2][32]; DBL Intervals_Hi[2][32]; int SectorNum[32]; Thread->Stats()[Ray_Par_Bound_Tests]++; if(container_shape) { if(Trans != NULL) { MInvTransPoint(New_Ray.Origin, ray.Origin, Trans); MInvTransDirection(New_Ray.Direction, ray.Direction, Trans); VLength(len, New_Ray.Direction); VInverseScaleEq(New_Ray.Direction, len); i_flg = Sphere::Intersect(New_Ray, container.sphere.center, (container.sphere.radius) * (container.sphere.radius), &Depth1, &Depth2); Depth1 = Depth1 / len; Depth2 = Depth2 / len; } else { i_flg = Sphere::Intersect(ray, container.sphere.center, (container.sphere.radius) * (container.sphere.radius), &Depth1, &Depth2); } Thread->Stats()[Ray_Sphere_Tests]--; if(i_flg) Thread->Stats()[Ray_Sphere_Tests_Succeeded]--; } else { i_flg = Box::Intersect(ray, Trans, container.box.corner1, container.box.corner2, &Depth1, &Depth2, &Side1, &Side2); } if(!i_flg) return false; Thread->Stats()[Ray_Par_Bound_Tests_Succeeded]++; Thread->Stats()[Ray_Parametric_Tests]++; if (Trans != NULL) { MInvTransPoint(P, ray.Origin, Trans); MInvTransDirection(D, ray.Direction, Trans); } else { P[X] = ray.Origin[X]; P[Y] = ray.Origin[Y]; P[Z] = ray.Origin[Z]; D[X] = ray.Direction[X]; D[Y] = ray.Direction[Y]; D[Z] = ray.Direction[Z]; } if (Depth1 == Depth2) Depth1 = 0; if ((Depth1 += 4 * accuracy) > Depth2) return false; Intervals_Low[INDEX_U][0] = umin; Intervals_Hi[INDEX_U][0] = umax; Intervals_Low[INDEX_V][0] = vmin; Intervals_Hi[INDEX_V][0] = vmax; /* Fri 09-27-1996 0. */ SectorNum[0] = 1; MaxPrecompX = MaxPrecompY = MaxPrecompZ = 0; if (PData != NULL) { if (((PData->flags) & OK_X) != 0) MaxPrecompX = 1 << (PData->depth); if (((PData->flags) & OK_Y) != 0) MaxPrecompY = 1 << (PData->depth); if (((PData->flags) & OK_Z) != 0) MaxPrecompZ = 1 << (PData->depth); } /* 0 */ while (i >= 0) { low_vect[U] = Intervals_Low[INDEX_U][i]; hi_vect[U] = Intervals_Hi[INDEX_U][i]; Len = hi_vect[U] - low_vect[U]; split = INDEX_U; low_vect[V] = Intervals_Low[INDEX_V][i]; hi_vect[V] = Intervals_Hi[INDEX_V][i]; temp = hi_vect[V] - low_vect[V]; if (temp > Len) { Len = temp; split = INDEX_V; } parX = parY = 0; TLen = 0; /* X */ if (SectorNum[i] < MaxPrecompX) { low = PData->Low[0][SectorNum[i]]; hi = PData->Hi[0][SectorNum[i]]; } else Evaluate_Function_Interval_UV(Thread->functionContext, *(Function[0]), accuracy, low_vect, hi_vect, max_gradient, low, hi); /* fabs(D[X] *(T2-T1)) is not OK with new method */ if (close(D[0], 0)) { parX = 1; if ((hi < P[0]) || (low > P[0])) { i--; continue; } } else { XRayMin = (hi - P[0]) / D[0]; XRayMax = (low - P[0]) / D[0]; if (XRayMin > XRayMax) { temp = XRayMin; XRayMin = XRayMax; XRayMax = temp; } if ((XRayMin > Depth2) || (XRayMax < Depth1)) { i--; continue; } if ((TPotRes = XRayMin) > TResult) { i--; continue; } TLen = XRayMax - XRayMin; } /* Y */ if (SectorNum[i] < MaxPrecompY) { low = PData->Low[1][SectorNum[i]]; hi = PData->Hi[1][SectorNum[i]]; } else Evaluate_Function_Interval_UV(Thread->functionContext, *(Function[1]), accuracy, low_vect, hi_vect, max_gradient, low, hi); if (close(D[1], 0)) { parY = 1; if ((hi < P[1]) || (low > P[1])) { i--; continue; } } else { YRayMin = (hi - P[1]) / D[1]; YRayMax = (low - P[1]) / D[1]; if (YRayMin > YRayMax) { temp = YRayMin; YRayMin = YRayMax; YRayMax = temp; } if ((YRayMin > Depth2) || (YRayMax < Depth1)) { i--; continue; } if ((TPotRes = YRayMin) > TResult) { i--; continue; } if (parX == 0) { if ((YRayMin > XRayMax) || (YRayMax < XRayMin)) { i--; continue; } } if ((temp = YRayMax - YRayMin) > TLen) TLen = temp; } /* Z */ if ((SectorNum[i] < MaxPrecompZ) && (0 < SectorNum[i])) { low = PData->Low[2][SectorNum[i]]; hi = PData->Hi[2][SectorNum[i]]; } else Evaluate_Function_Interval_UV(Thread->functionContext, *(Function[2]), accuracy, low_vect, hi_vect, max_gradient, low, hi); if (close(D[2], 0)) { if ((hi < P[2]) || (low > P[2])) { i--; continue; } } else { ZRayMin = (hi - P[2]) / D[2]; ZRayMax = (low - P[2]) / D[2]; if (ZRayMin > ZRayMax) { temp = ZRayMin; ZRayMin = ZRayMax; ZRayMax = temp; } if ((ZRayMin > Depth2) || (ZRayMax < Depth1)) { i--; continue; } if ((TPotRes = ZRayMin) > TResult) { i--; continue; } if (parX == 0) { if ((ZRayMin > XRayMax) || (ZRayMax < XRayMin)) { i--; continue; } } if (parY == 0) { if ((ZRayMin > YRayMax) || (ZRayMax < YRayMin)) { i--; continue; } } if ((temp = ZRayMax - ZRayMin) > TLen) TLen = temp; } if (Len > TLen) Len = TLen; if (Len < accuracy) { if ((TResult > TPotRes) && (TPotRes > Depth1)) { TResult = TPotRes; Assign_UV_Vect(uv, low_vect); } i--; } else { /* 1 copy */ if ((SectorNum[i] *= 2) >= Max_intNumber) SectorNum[i] = Max_intNumber; SectorNum[i + 1] = SectorNum[i]; SectorNum[i]++; i++; Intervals_Low[INDEX_U][i] = low_vect[U]; Intervals_Hi[INDEX_U][i] = hi_vect[U]; Intervals_Low[INDEX_V][i] = low_vect[V]; Intervals_Hi[INDEX_V][i] = hi_vect[V]; /* 2 split */ temp = (Intervals_Hi[split][i] + Intervals_Low[split][i]) / 2.0; Intervals_Hi[split][i] = temp; Intervals_Low[split][i - 1] = temp; } } if (TResult < Depth2) { Thread->Stats()[Ray_Parametric_Tests_Succeeded]++; VScale(IPoint, ray.Direction, TResult); VAddEq(IPoint, ray.Origin); if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { /* compute_param_normal( Par, UResult, VResult , &N); push_normal_entry( TResult ,IPoint, N, (ObjectPtr ) Object, Depth_Stack); */ Depth_Stack->push(Intersection(TResult, IPoint, uv, this)); return true; } } return false; }
inline VECTOR operator *(const VECTOR& lhs, float rhs) { return VScale(lhs, rhs); }
int All_Parametric_Intersections(OBJECT* Object, RAY* Ray, ISTACK* Depth_Stack) { PARAMETRIC * Par = (PARAMETRIC *)Object; PRECOMP_PAR_DATA * PData = ((PARAMETRIC *)Object)->PData; VECTOR P, D, IPoint; UV_VECT low_vect, hi_vect; RAY New_Ray; DBL XRayMin, XRayMax, YRayMin, YRayMax, ZRayMin, ZRayMax, TPotRes, TLen; DBL Depth1, Depth2, temp, Len, UResult, VResult, TResult = HUGE_VAL; DBL low, hi, len; int MaxPrecompX, MaxPrecompY, MaxPrecompZ; int split, i = 0, Side1, Side2; int parX, parY; int i_flg; Increase_Counter(stats[Ray_Par_Bound_Tests]); if(Par->container_shape) { if(Par->Trans != NULL) { MInvTransPoint(New_Ray.Initial, Ray->Initial, Par->Trans); MInvTransDirection(New_Ray.Direction, Ray->Direction, Par->Trans); VLength(len, New_Ray.Direction); VInverseScaleEq(New_Ray.Direction, len); i_flg = Intersect_Sphere(&New_Ray, Par->container.sphere.center, (Par->container.sphere.radius) * (Par->container.sphere.radius), &Depth1, &Depth2); Depth1 = Depth1 / len; Depth2 = Depth2 / len; } else { i_flg = Intersect_Sphere(Ray, Par->container.sphere.center, (Par->container.sphere.radius) * (Par->container.sphere.radius), &Depth1, &Depth2); } Decrease_Counter(stats[Ray_Sphere_Tests]); if(i_flg) Decrease_Counter(stats[Ray_Sphere_Tests_Succeeded]); } else { i_flg = Intersect_Box(Ray, Par->Trans, Par->container.box.corner1, Par->container.box.corner2, &Depth1, &Depth2, &Side1, &Side2); } if(!i_flg) return false; Increase_Counter(stats[Ray_Par_Bound_Tests_Succeeded]); Increase_Counter(stats[Ray_Parametric_Tests]); if (Par->Trans != NULL) { MInvTransPoint(P, Ray->Initial, Par->Trans); MInvTransDirection(D, Ray->Direction, Par->Trans); } else { P[X] = Ray->Initial[X]; P[Y] = Ray->Initial[Y]; P[Z] = Ray->Initial[Z]; D[X] = Ray->Direction[X]; D[Y] = Ray->Direction[Y]; D[Z] = Ray->Direction[Z]; } if (Depth1 == Depth2) Depth1 = 0; if ((Depth1 += 4 * Par->accuracy) > Depth2) return false; Intervals_Low[INDEX_U][0] = Par->umin; Intervals_Hi[INDEX_U][0] = Par->umax; Intervals_Low[INDEX_V][0] = Par->vmin; Intervals_Hi[INDEX_V][0] = Par->vmax; /* Fri 09-27-1996 0. */ SectorNum[0] = 1; MaxPrecompX = MaxPrecompY = MaxPrecompZ = 0; if (PData != NULL) { if (((PData->flags) & OK_X) != 0) MaxPrecompX = 1 << (PData->depth); if (((PData->flags) & OK_Y) != 0) MaxPrecompY = 1 << (PData->depth); if (((PData->flags) & OK_Z) != 0) MaxPrecompZ = 1 << (PData->depth); } /* 0 */ while (i >= 0) { low_vect[U] = Intervals_Low[INDEX_U][i]; hi_vect[U] = Intervals_Hi[INDEX_U][i]; Len = hi_vect[U] - low_vect[U]; split = INDEX_U; low_vect[V] = Intervals_Low[INDEX_V][i]; hi_vect[V] = Intervals_Hi[INDEX_V][i]; temp = hi_vect[V] - low_vect[V]; if (temp > Len) { Len = temp; split = INDEX_V; } parX = parY = 0; TLen = 0; /* X */ if (SectorNum[i] < MaxPrecompX) { low = PData->Low[0][SectorNum[i]]; hi = PData->Hi[0][SectorNum[i]]; } else Evaluate_Function_Interval_UV(*(Par->Function[0]), Par->accuracy, low_vect, hi_vect, Par->max_gradient, low, hi); /* fabs(D[X] *(T2-T1)) is not OK with new method */ if (close(D[0], 0)) { parX = 1; if ((hi < P[0]) || (low > P[0])) { i--; continue; } } else { XRayMin = (hi - P[0]) / D[0]; XRayMax = (low - P[0]) / D[0]; if (XRayMin > XRayMax) { temp = XRayMin; XRayMin = XRayMax; XRayMax = temp; } if ((XRayMin > Depth2) || (XRayMax < Depth1)) { i--; continue; } if ((TPotRes = XRayMin) > TResult) { i--; continue; } TLen = XRayMax - XRayMin; } /* Y */ if (SectorNum[i] < MaxPrecompY) { low = PData->Low[1][SectorNum[i]]; hi = PData->Hi[1][SectorNum[i]]; } else Evaluate_Function_Interval_UV(*(Par->Function[1]), Par->accuracy, low_vect, hi_vect, Par->max_gradient, low, hi); if (close(D[1], 0)) { parY = 1; if ((hi < P[1]) || (low > P[1])) { i--; continue; } } else { YRayMin = (hi - P[1]) / D[1]; YRayMax = (low - P[1]) / D[1]; if (YRayMin > YRayMax) { temp = YRayMin; YRayMin = YRayMax; YRayMax = temp; } if ((YRayMin > Depth2) || (YRayMax < Depth1)) { i--; continue; } if ((TPotRes = YRayMin) > TResult) { i--; continue; } if (parX == 0) { if ((YRayMin > XRayMax) || (YRayMax < XRayMin)) { i--; continue; } } if ((temp = YRayMax - YRayMin) > TLen) TLen = temp; } /* Z */ if ((SectorNum[i] < MaxPrecompZ) && (0 < SectorNum[i])) { low = PData->Low[2][SectorNum[i]]; hi = PData->Hi[2][SectorNum[i]]; } else Evaluate_Function_Interval_UV(*(Par->Function[2]), Par->accuracy, low_vect, hi_vect, Par->max_gradient, low, hi); if (close(D[2], 0)) { if ((hi < P[2]) || (low > P[2])) { i--; continue; } } else { ZRayMin = (hi - P[2]) / D[2]; ZRayMax = (low - P[2]) / D[2]; if (ZRayMin > ZRayMax) { temp = ZRayMin; ZRayMin = ZRayMax; ZRayMax = temp; } if ((ZRayMin > Depth2) || (ZRayMax < Depth1)) { i--; continue; } if ((TPotRes = ZRayMin) > TResult) { i--; continue; } if (parX == 0) { if ((ZRayMin > XRayMax) || (ZRayMax < XRayMin)) { i--; continue; } } if (parY == 0) { if ((ZRayMin > YRayMax) || (ZRayMax < YRayMin)) { i--; continue; } } if ((temp = ZRayMax - ZRayMin) > TLen) TLen = temp; } if (Len > TLen) Len = TLen; if (Len < Par->accuracy) { if ((TResult > TPotRes) && (TPotRes > Depth1)) { TResult = TPotRes; Par->last_u = UResult = low_vect[U]; Par->last_v = VResult = low_vect[V]; } i--; } else { /* 1 copy */ if ((SectorNum[i] *= 2) >= Max_intNumber) SectorNum[i] = Max_intNumber; SectorNum[i + 1] = SectorNum[i]; SectorNum[i]++; i++; Intervals_Low[INDEX_U][i] = low_vect[U]; Intervals_Hi[INDEX_U][i] = hi_vect[U]; Intervals_Low[INDEX_V][i] = low_vect[V]; Intervals_Hi[INDEX_V][i] = hi_vect[V]; /* 2 split */ temp = (Intervals_Hi[split][i] + Intervals_Low[split][i]) / 2.0; Intervals_Hi[split][i] = temp; Intervals_Low[split][i - 1] = temp; } } if (TResult < Depth2) { Increase_Counter(stats[Ray_Parametric_Tests_Succeeded]); VScale(IPoint, Ray->Direction, TResult); VAddEq(IPoint, Ray->Initial); if (Point_In_Clip(IPoint, Par->Clip)) { /* compute_param_normal( Par, UResult, VResult , &N); push_normal_entry( TResult ,IPoint, N, (OBJECT *) Object, Depth_Stack); */ // UV_VECT uv; // Make_UV_Vector(uv, UResult, VResult); // push_uv_entry(TResult, IPoint, uv, (OBJECT *)Object, Depth_Stack); push_entry(TResult, IPoint, (OBJECT *)Object, Depth_Stack); return true; } } return false; }
// キャラクターの移動処理 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 ) ; }
// 影用の深度記録画像の準備を行う void SetupDepthImage( void ) { int i ; VECTOR LightDirection ; VECTOR LightPosition ; VECTOR LightTarget ; // 描画先を影用深度記録画像にする SetDrawScreen( DepthBufferGraphHandle ) ; // 影用深度記録画像を真っ白にクリア SetBackgroundColor( 255, 255, 255 ) ; ClearDrawScreen() ; SetBackgroundColor( 0, 0, 0 ) ; // カメラのタイプを正射影タイプにセット、描画範囲も指定 SetupCamera_Ortho( 13250.0f ) ; // 描画する奥行き範囲をセット SetCameraNearFar( 10.0f, 13050.0f ) ; // カメラの向きはライトの向き LightDirection = GetLightDirection() ; // カメラの位置と注視点はステージ全体が見渡せる位置 LightTarget.x = 3620.0f ; LightTarget.y = 0.0f ; LightTarget.z = 3830.0f ; LightPosition = VAdd( LightTarget, VScale( LightDirection, -12400.0f ) ) ; SetCameraPositionAndTarget_UpVecY( LightPosition, LightTarget ) ; // 設定したカメラのビュー行列と射影行列を取得しておく LightCamera_ViewMatrix = GetCameraViewMatrix() ; LightCamera_ProjectionMatrix = GetCameraProjectionMatrix() ; // モデルの描画にオリジナルのシェーダーを使用するように設定する MV1SetUseOrigShader( TRUE ) ; // 深度記録画像への描画用のピクセルシェーダーをセット SetUsePixelShader( DepthShadow_Step1_PixelShader ) ; // 深度記録画像への剛体メッシュ描画用の頂点シェーダーをセット SetUseVertexShader( Normal_DepthShadow_Step1_VertexShader ) ; // ステージを描画 MV1DrawModel( stg.ModelHandle ) ; // 深度記録画像へのスキニングメッシュ描画用の頂点シェーダーをセット SetUseVertexShader( Skin4_DepthShadow_Step1_VertexShader ) ; // プレイヤーモデルの描画 MV1DrawModel( pl.CharaInfo.ModelHandle ) ; // プレイヤー以外キャラモデルの描画 for( i = 0 ; i < NOTPLAYER_NUM ; i ++ ) { MV1DrawModel( npl[ i ].CharaInfo.ModelHandle ) ; } // モデルの描画にオリジナルのシェーダーを使用するようにした設定を解除 MV1SetUseOrigShader( FALSE ) ; // 描画先を裏画面に戻す SetDrawScreen( DX_SCREEN_BACK ) ; }
// プレイヤーの処理 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 ) ; }
static int intersect_subpatch(BICUBIC_PATCH *Shape, RAY *ray, VECTOR V1[3], DBL uu[3], DBL vv[3], DBL *Depth, VECTOR P, VECTOR N, DBL *u, DBL *v) { DBL squared_b0, squared_b1; DBL d, n, a, b, r; VECTOR Q, T1; VECTOR B[3], IB[3], NN[3]; VSub(B[0], V1[1], V1[0]); VSub(B[1], V1[2], V1[0]); VCross(B[2], B[0], B[1]); VDot(d, B[2], B[2]); squared_b0 = VSumSqr(B[0]); squared_b1 = VSumSqr(B[1]); if (d <= (BEZIER_EPSILON * squared_b1 * squared_b0)) { return (0); } d = 1.0 / sqrt(d); VScaleEq(B[2], d); /* Degenerate triangle. */ if (!MInvers3(B, IB)) { return (0); } VDot(d, ray->Direction, IB[2]); if (fabs(d) < BEZIER_EPSILON) { return (0); } VSub(Q, V1[0], ray->Initial); VDot(n, Q, IB[2]); *Depth = n / d; if (*Depth < BEZIER_TOLERANCE) { return (0); } VScale(T1, ray->Direction, *Depth); VAdd(P, ray->Initial, T1); VSub(Q, P, V1[0]); VDot(a, Q, IB[0]); VDot(b, Q, IB[1]); if ((a < 0.0) || (b < 0.0) || (a + b > 1.0)) { return (0); } r = 1.0 - a - b; Make_Vector(N, 0.0, 0.0, 0.0); bezier_value((VECTOR(*)[4][4])&Shape->Control_Points, uu[0], vv[0], T1, NN[0]); bezier_value((VECTOR(*)[4][4])&Shape->Control_Points, uu[1], vv[1], T1, NN[1]); bezier_value((VECTOR(*)[4][4])&Shape->Control_Points, uu[2], vv[2], T1, NN[2]); VScale(T1, NN[0], r); VAddEq(N, T1); VScale(T1, NN[1], a); VAddEq(N, T1); VScale(T1, NN[2], b); VAddEq(N, T1); *u = r * uu[0] + a * uu[1] + b * uu[2]; *v = r * vv[0] + a * vv[1] + b * vv[2]; VDot(d, N, N); if (d > BEZIER_EPSILON) { d = 1.0 / sqrt(d); VScaleEq(N, d); } else { Make_Vector(N, 1, 0, 0); } return (1); }