object * newplane(void * tex, vector ctr, vector norm) { plane * p; p=(plane *) rt_getmem(sizeof(plane)); memset(p, 0, sizeof(plane)); p->methods = &plane_methods; p->tex = (texture *)tex; p->norm = norm; VNorm(&p->norm); p->d = -VDot(&ctr, &p->norm); return (object *) p; }
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; }
object * newring(void * tex, vector ctr, vector norm, flt inrad, flt outrad) { ring * r; r=(ring *) malloc(sizeof(ring)); memset(r, 0, sizeof(ring)); r->methods = &ring_methods; r->tex = tex; r->ctr = ctr; r->norm = norm; VNorm(&r->norm); r->inrad = inrad; r->outrad= outrad; return (object *) r; }
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 * rt_directional_light(SceneHandle voidscene, void * tex, apivector dir) { directional_light * li; scenedef * scene = (scenedef *) voidscene; list * lst; VNorm(&dir); li=newdirectionallight(tex, dir); /* add light to the scene lightlist */ lst = (list *) malloc(sizeof(list)); lst->item = (void *) li; lst->next = scene->lightlist; scene->lightlist = lst; scene->numlights++; /* don't add to the object list since it's at infinity */ /* XXX must loop over light list and deallocate these */ /* specially since they aren't in the obj list. */ return li; }
void quadric_normal(quadric * q, vector * pnt, ray * incident, vector * N) { N->x = (q->mat.a*(pnt->x - q->ctr.x) + q->mat.b*(pnt->y - q->ctr.y) + q->mat.c*(pnt->z - q->ctr.z) + q->mat.d); N->y = (q->mat.b*(pnt->x - q->ctr.x) + q->mat.e*(pnt->y - q->ctr.y) + q->mat.f*(pnt->z - q->ctr.z) + q->mat.g); N->z = (q->mat.c*(pnt->x - q->ctr.x) + q->mat.f*(pnt->y - q->ctr.y) + q->mat.h*(pnt->z - q->ctr.z) + q->mat.i); VNorm(N); if (VDot(N, &(incident->d)) > 0.0) { N->x=-N->x; N->y=-N->y; N->z=-N->z; } }
static void stri_normal(stri * trn, vector * pnt, ray * incident, vector * N) { flt U, V, W, lensqr; vector P, tmp, norm; CROSS(norm, trn->edge1, trn->edge2); lensqr = DOT(norm, norm); VSUB((*pnt), trn->v0, P); CROSS(tmp, P, trn->edge2); U = DOT(tmp, norm) / lensqr; CROSS(tmp, trn->edge1, P); V = DOT(tmp, norm) / lensqr; W = 1.0 - (U + V); N->x = W*trn->n0.x + U*trn->n1.x + V*trn->n2.x; N->y = W*trn->n0.y + U*trn->n1.y + V*trn->n2.y; N->z = W*trn->n0.z + U*trn->n1.z + V*trn->n2.z; VNorm(N); }
void * rt_spotlight(SceneHandle voidscene, void * tex, apivector ctr, flt rad, apivector dir, flt start, flt end) { flt fallstart, fallend; point_light * li; scenedef * scene = (scenedef *) voidscene; list * lst; fallstart = start * 3.1415926 / 180.0; fallend = end * 3.1415926 / 180.0; VNorm(&dir); li = newspotlight(tex, ctr, rad, dir, fallstart, fallend); /* add light to the scene lightlist */ lst = (list *) malloc(sizeof(list)); lst->item = (void *) li; lst->next = scene->lightlist; scene->lightlist = lst; scene->numlights++; /* add light as an object as well... */ add_bounded_object(scene, (object *) li); return li; }
color ext_volume_texture(vector * hit, texture * tex, ray * ry) { color col, col2; box * bx; extvol * xvol; flt a, tx1, tx2, ty1, ty2, tz1, tz2; flt tnear, tfar; flt t, tdist, dt, ddt, sum, tt; vector pnt, bln; flt scalar, transval; int i; point_light * li; color diffint; vector N, L; flt inten; col.r = 0.0; col.g = 0.0; col.b = 0.0; bx = (box *) tex->obj; xvol = (extvol *) tex->obj; tnear= -FHUGE; tfar= FHUGE; if (ry->d.x == 0.0) { if ((ry->o.x < bx->min.x) || (ry->o.x > bx->max.x)) return col; } else { tx1 = (bx->min.x - ry->o.x) / ry->d.x; tx2 = (bx->max.x - ry->o.x) / ry->d.x; if (tx1 > tx2) { a=tx1; tx1=tx2; tx2=a; } if (tx1 > tnear) tnear=tx1; if (tx2 < tfar) tfar=tx2; } if (tnear > tfar) return col; if (tfar < 0.0) return col; if (ry->d.y == 0.0) { if ((ry->o.y < bx->min.y) || (ry->o.y > bx->max.y)) return col; } else { ty1 = (bx->min.y - ry->o.y) / ry->d.y; ty2 = (bx->max.y - ry->o.y) / ry->d.y; if (ty1 > ty2) { a=ty1; ty1=ty2; ty2=a; } if (ty1 > tnear) tnear=ty1; if (ty2 < tfar) tfar=ty2; } if (tnear > tfar) return col; if (tfar < 0.0) return col; if (ry->d.z == 0.0) { if ((ry->o.z < bx->min.z) || (ry->o.z > bx->max.z)) return col; } else { tz1 = (bx->min.z - ry->o.z) / ry->d.z; tz2 = (bx->max.z - ry->o.z) / ry->d.z; if (tz1 > tz2) { a=tz1; tz1=tz2; tz2=a; } if (tz1 > tnear) tnear=tz1; if (tz2 < tfar) tfar=tz2; } if (tnear > tfar) return col; if (tfar < 0.0) return col; if (tnear < 0.0) tnear=0.0; tdist = xvol->samples; tt = (xvol->opacity / tdist); bln.x=fabs(bx->min.x - bx->max.x); bln.y=fabs(bx->min.y - bx->max.y); bln.z=fabs(bx->min.z - bx->max.z); dt = 1.0 / tdist; sum = 0.0; /* Accumulate color as the ray passes through the voxels */ for (t=tnear; t<=tfar; t+=dt) { if (sum < 1.0) { pnt.x=((ry->o.x + (ry->d.x * t)) - bx->min.x) / bln.x; pnt.y=((ry->o.y + (ry->d.y * t)) - bx->min.y) / bln.y; pnt.z=((ry->o.z + (ry->d.z * t)) - bx->min.z) / bln.z; /* call external evaluator assume 0.0 -> 1.0 range.. */ scalar = xvol->evaluator(pnt.x, pnt.y, pnt.z); transval = tt * scalar; sum += transval; col2 = ExtVoxelColor(scalar); col.r += transval * col2.r * xvol->ambient; col.g += transval * col2.g * xvol->ambient; col.b += transval * col2.b * xvol->ambient; ddt = dt; /* Add in diffuse shaded light sources (no shadows) */ if (xvol->diffuse > 0.0) { /* Calculate the Volume gradient at the voxel */ N.x = (xvol->evaluator(pnt.x - ddt, pnt.y, pnt.z) - xvol->evaluator(pnt.x + ddt, pnt.y, pnt.z)) * 8.0 * tt; N.y = (xvol->evaluator(pnt.x, pnt.y - ddt, pnt.z) - xvol->evaluator(pnt.x, pnt.y + ddt, pnt.z)) * 8.0 * tt; N.z = (xvol->evaluator(pnt.x, pnt.y, pnt.z - ddt) - xvol->evaluator(pnt.x, pnt.y, pnt.z + ddt)) * 8.0 * tt; /* only light surfaces with enough of a normal.. */ if ((N.x*N.x + N.y*N.y + N.z*N.z) > 0.0) { diffint.r = 0.0; diffint.g = 0.0; diffint.b = 0.0; /* add the contribution of each of the lights.. */ for (i=0; i<numlights; i++) { li=lightlist[i]; VSUB(li->ctr, (*hit), L) VNorm(&L); VDOT(inten, N, L) /* only add light if its from the front of the surface */ /* could add back-lighting if we wanted to later.. */ if (inten > 0.0) { diffint.r += inten*li->tex->col.r; diffint.g += inten*li->tex->col.g; diffint.b += inten*li->tex->col.b; } } col.r += col2.r * diffint.r * xvol->diffuse; col.g += col2.g * diffint.g * xvol->diffuse; col.b += col2.b * diffint.b * xvol->diffuse; } }
// プレイヤーの処理 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_Process( CHARA *ch, VECTOR MoveVec, int JumpFlag ) { int MoveFlag ; // 移動したかどうかのフラグ( 1:移動した 0:移動していない ) // ルートフレームのZ軸方向の移動パラメータを無効にする { MATRIX LocalMatrix ; // ユーザー行列を解除する MV1ResetFrameUserLocalMatrix( ch->ModelHandle, 2 ) ; // 現在のルートフレームの行列を取得する LocalMatrix = MV1GetFrameLocalMatrix( ch->ModelHandle, 2 ) ; // Z軸方向の平行移動成分を無効にする LocalMatrix.m[ 3 ][ 2 ] = 0.0f ; // ユーザー行列として平行移動成分を無効にした行列をルートフレームにセットする MV1SetFrameUserLocalMatrix( ch->ModelHandle, 2, LocalMatrix ) ; } // 移動したかどうかのフラグをセット、少しでも移動していたら「移動している」を表す1にする MoveFlag = 0 ; if( MoveVec.x < -0.001f || MoveVec.x > 0.001f || MoveVec.y < -0.001f || MoveVec.y > 0.001f || MoveVec.z < -0.001f || MoveVec.z > 0.001f ) { MoveFlag = 1 ; } // キャラクターの状態が「ジャンプ」ではなく、且つジャンプフラグが立っていたらジャンプする if( ch->State != 2 && JumpFlag == 1 ) { // 状態を「ジャンプ」にする ch->State = 2 ; // Y軸方向の速度をセット ch->JumpPower = CHARA_JUMP_POWER ; // ジャンプアニメーションの再生 Chara_PlayAnim( ch, 2 ) ; } // 移動ボタンが押されたかどうかで処理を分岐 if( MoveFlag ) { // 移動ベクトルを正規化したものをキャラクターが向くべき方向として保存 ch->TargetMoveDirection = VNorm( MoveVec ) ; // もし今まで「立ち止まり」状態だったら if( ch->State == 0 ) { // 走りアニメーションを再生する Chara_PlayAnim( ch, 1 ) ; // 状態を「走り」にする ch->State = 1 ; } } else { // このフレームで移動していなくて、且つ状態が「走り」だったら if( ch->State == 1 ) { // 立ち止りアニメーションを再生する Chara_PlayAnim( ch, 4 ) ; // 状態を「立ち止り」にする ch->State = 0 ; } } // 状態が「ジャンプ」の場合は if( ch->State == 2 ) { // Y軸方向の速度を重力分減算する ch->JumpPower -= CHARA_GRAVITY ; // もし落下していて且つ再生されているアニメーションが上昇中用のものだった場合は if( ch->JumpPower < 0.0f && MV1GetAttachAnim( ch->ModelHandle, ch->PlayAnim1 ) == 2 ) { // 落下中ようのアニメーションを再生する Chara_PlayAnim( ch, 3 ) ; } // 移動ベクトルのY成分をY軸方向の速度にする MoveVec.y = ch->JumpPower ; } // キャラクターの移動方向にモデルの方向を近づける Chara_AngleProcess( ch ) ; // 移動ベクトルを元にコリジョンを考慮しつつキャラクターを移動 Chara_Move( ch, MoveVec ) ; // アニメーション処理 Chara_AnimProcess( ch ) ; }
static void fcylinder_intersect(const cylinder * cyl, ray * ry) { vector rc, n, O, hit, tmp2, ctmp4; flt t, s, tin, tout, ln, d, tmp, tmp3; rc.x = ry->o.x - cyl->ctr.x; rc.y = ry->o.y - cyl->ctr.y; rc.z = ry->o.z - cyl->ctr.z; VCross(&ry->d, &cyl->axis, &n); ln=SQRT(n.x*n.x + n.y*n.y + n.z*n.z); /* finish length calculation */ if (ln == 0.0) { /* ray is parallel to the cylinder.. */ return; /* in this case, we want to miss or go through the "hole" */ } n.x /= ln; n.y /= ln; n.z /= ln; VDOT(d, rc, n); d = FABS(d); if (d <= cyl->rad) { /* ray intersects cylinder.. */ VCross(&rc, &cyl->axis, &O); VDOT(t, O, n); t = - t / ln; VCross(&n, &cyl->axis, &O); ln = SQRT(O.x*O.x + O.y*O.y + O.z*O.z); O.x /= ln; O.y /= ln; O.z /= ln; VDOT(s, ry->d, O); s = FABS(SQRT(cyl->rad*cyl->rad - d*d) / s); tin = t - s; RAYPNT(hit, (*ry), tin); ctmp4=cyl->axis; VNorm(&ctmp4); tmp2.x = hit.x - cyl->ctr.x; tmp2.y = hit.y - cyl->ctr.y; tmp2.z = hit.z - cyl->ctr.z; VDOT(tmp, tmp2, ctmp4); VDOT(tmp3, cyl->axis, cyl->axis); if ((tmp > 0.0) && (tmp < SQRT(tmp3))) ry->add_intersection(tin, (object *) cyl, ry); tout = t + s; RAYPNT(hit, (*ry), tout); tmp2.x = hit.x - cyl->ctr.x; tmp2.y = hit.y - cyl->ctr.y; tmp2.z = hit.z - cyl->ctr.z; VDOT(tmp, tmp2, ctmp4); VDOT(tmp3, cyl->axis, cyl->axis); if ((tmp > 0.0) && (tmp < SQRT(tmp3))) ry->add_intersection(tout, (object *) cyl, ry); } }