int CameraComponent::DoTick(U32 delta) { float EASE = 0.2f; switch (mode) { case PAN: { Vector3F d = (dest - camera->PosWC()); Vector3F c = camera->PosWC(); if (d.Length() < 0.01f) { camera->SetPosWC(dest.x, dest.y, dest.z); mode = DONE; } else { camera->SetPosWC(c.x + EASE*d.x, c.y + EASE*d.y, c.z + EASE*d.z); } } break; case TRACK: { Chit* chit = Context()->chitBag->GetChit(targetChitID); if (chit) { Vector3F pos = chit->Position(); pos.y = 0; // Scoot the camera to always focus on the target. Removes // errors that occur from rotation, drift, etc. const Vector3F* eye3 = camera->EyeDir3(); Vector3F at; int result = IntersectRayPlane(camera->PosWC(), eye3[0], 1, 0.0f, &at); if (result == INTERSECT) { Vector3F t = (camera->PosWC() - at); //camera->SetPosWC( pos + t ); Vector3F c = camera->PosWC(); Vector3F d = (pos + t) - c; // If grid moving, the EASE contributes to jitter. if (GET_SUB_COMPONENT(chit, MoveComponent, GridMoveComponent)) { EASE = 1.0f; } camera->SetPosWC(c.x + EASE*d.x, pos.y + t.y, c.z + EASE*d.z); } } } break; case DONE: break; default: GLASSERT(0); } return 0; }
/*static*/ void Plane::CreatePlane( const Vector3F& normal, const Vector3F& point, Plane* plane ) { // n * p + d = 0 // so: d = -n*p GLASSERT( Equal( normal.Length(), 1.0f, 0.001f ) ); plane->n = normal; plane->d = -DotProduct( normal, point ); }
void SphericalXZ::FromCartesion( const Vector3F& in ) { theta = rho = 0.0f; r = in.Length(); if ( r != 0.0f ) { rho = acosf( in.y / r ); } if ( in.z != 0.0f ) { theta = atanf( -in.x / in.z ); } }
/// <summary> /// Sets up a quaternion & position from vector camera components /// and oriented the camera up /// </summary> /// <param name="eye">The camera position</param> /// <param name="lookAt">The camera's look-at point</param> /// <param name="up"></param> void ArcBallCameraController::SetCamera(Vector3F position, Vector3F target, Vector3F up) { m_bRecomputeViewMatrix = true; //Create a look at matrix, to simplify matters a bit Matrix4 temp; temp.LookAt(position, target, up); //invert the matrix, since we're determining the //orientation from the rotation matrix in RH coords temp.Invert(); //set the position m_Target = target; //set distance m_fDistance = (target - position).Length(); //create the new aspect from the look-at matrix m_ArcBallOrientation.FromMatrix(temp); //When setting a new eye-view direction //in one of the gamble-locked modes, the yaw and //pitch gimble must be calculated. //first, get the direction projected on the x/z plne Vector3F dir = Direction(); dir.y = 0.0f; if (dir.Length() == 0.0f) { dir = Vector3F::Forward(); } dir.Normalize(); //find the yaw of the direction on the x/z plane //and use the sign of the x-component since we have 360 degrees //of freedom m_fArcBallYaw = (acosf(-dir.z) * Sign(dir.x)); //Get the pitch from the angle formed by the Up vector and the //the forward direction, then subtracting Pi / 2, since //we pitch is zero at Forward, not Up. m_fArcBallPitch = -(acosf(Vector3F::Dot(Vector3F::Up(), Direction())) - MATH_PI_DIV_2); }
Bolt* LumosChitBag::NewBolt( const Vector3F& pos, const Vector3F& _dir, int effectFlags, int chitID, float damage, float speed, bool trail ) { GLASSERT(pos.y > 0); GLASSERT(pos.y < 4); Bolt* bolt = ChitBag::NewBolt(); Vector3F dir = _dir; dir.Normalize(); GLASSERT(Equal(dir.Length(), 1.0f)); bolt->head = pos + dir * 0.5f; bolt->len = 0.5f; bolt->dir = dir; const Game::Palette* palette = Game::GetMainPalette(); switch( effectFlags & (GameItem::EFFECT_FIRE | GameItem::EFFECT_SHOCK) ) { case 0: bolt->color = palette->Get4F( 1, PAL_GREEN ); break; case GameItem::EFFECT_FIRE: bolt->color = palette->Get4F( 1, PAL_RED ); break; case GameItem::EFFECT_SHOCK: bolt->color = palette->Get4F( 1, PAL_BLUE ); break; case GameItem::EFFECT_FIRE | GameItem::EFFECT_SHOCK: bolt->color = palette->Get4F( 1, PAL_PURPLE ); break; default: GLASSERT( 0 ); break; } bolt->chitID = chitID; bolt->damage = damage; bolt->effect = effectFlags; bolt->particle = trail; bolt->speed = speed; bolt->frameCount = 0; return bolt; }
void XenoAudio::SetChannelPos(int i) { if (!audioOn) return; if (sounds[i].pos.IsZero()) { Mix_SetPosition(i, 0, 0); } else { Vector3F delta = sounds[i].pos - listenerPos; float len = delta.Length(); float df = len / MAX_DISTANCE; int d = LRintf(df*255.0f); d = Clamp(d, 0, 255); if (delta.LengthSquared() > 0.001f) { delta.Normalize(); } else { delta.Set(0, 0, -1); } static const Vector3F UP = { 0, 1, 0 }; Vector3F listenerRight = CrossProduct(listenerDir, UP); float dotFront = DotProduct(delta, listenerDir); float dotRight = DotProduct(delta, listenerRight); // 0 is north, 90 is east, etc. WTF. float rad = atan2(dotRight, dotFront); float deg = rad * 180.0f / PI; int degi = int(deg); if (degi < 0) degi += 360; int result = Mix_SetPosition(i, degi, d); GLASSERT(result != 0); (void)result; } }
void FireWidget::Place( BattleScene* battle, const Unit* shooterUnit, const Unit* targetUnit, const grinliz::Vector2I& targetPos ) { GLASSERT( targetUnit || targetPos.x >= 0 ); const Model* targetModel = 0; const Model* targetWeapon = 0; Vector3F target; BulletTarget bulletTarget; if ( targetPos.x >= 0 ) { target.Set( (float)targetPos.x+0.5f, 1.0f, (float)targetPos.y+0.5f ); } else { targetModel = battle->GetModel( targetUnit ); targetWeapon = battle->GetWeaponModel( targetUnit ); GLASSERT( targetModel ); targetModel->CalcTarget( &target ); targetModel->CalcTargetSize( &bulletTarget.width, &bulletTarget.height ); } Vector3F distVector = target - shooterUnit->Pos(); bulletTarget.distance = distVector.Length(); const Inventory* inventory = shooterUnit->GetInventory(); const WeaponItemDef* wid = shooterUnit->GetWeaponDef(); float snapTU=0, autoTU=0, altTU=0; if ( wid ) { shooterUnit->AllFireTimeUnits( &snapTU, &autoTU, &altTU ); } int numButtons = 0; if ( wid ) { for( int i=0; i<WeaponItemDef::MAX_MODE && wid->HasWeapon(i); ++i ) { float fraction, anyFraction, dptu, tu; shooterUnit->FireStatistics( i, bulletTarget, &fraction, &anyFraction, &tu, &dptu ); int nRounds = inventory->CalcClipRoundsTotal( wid->GetClipItemDef( i) ); anyFraction = Clamp( anyFraction, 0.0f, 0.95f ); char buffer0[32]; char buffer1[32]; SNPrintf( buffer0, 32, "%s %d%%", wid->weapon[i]->desc, (int)LRintf( anyFraction*100.0f ) ); SNPrintf( buffer1, 32, "%d/%d", wid->RoundsNeeded( i ), nRounds ); fireButton[i].SetEnabled( true ); fireButton[i].SetVisible( true ); fireButton[i].SetText( buffer0 ); fireButton[i].SetText2( buffer1 ); if ( shooterUnit->CanFire( i )) { // Reflect the TU left. float tuAfter = shooterUnit->TU() - tu; int tuIndicator = ICON_ORANGE_WALK_MARK; if ( tuAfter >= autoTU ) { tuIndicator = ICON_GREEN_WALK_MARK; } else if ( tuAfter >= snapTU ) { tuIndicator = ICON_YELLOW_WALK_MARK; } else if ( tuAfter < snapTU ) { tuIndicator = ICON_ORANGE_WALK_MARK; } fireButton[i].SetDeco( Game::CalcIconAtom( tuIndicator, true ), Game::CalcIconAtom( tuIndicator, false ) ); } else { fireButton[i].SetEnabled( false ); RenderAtom nullAtom; fireButton[i].SetDeco( nullAtom, nullAtom ); } numButtons = i+1; } } else { fireButton[0].SetVisible( true ); fireButton[0].SetEnabled( false ); fireButton[0].SetText( "[none]" ); fireButton[0].SetText2( "" ); RenderAtom nullAtom; fireButton[0].SetDeco( nullAtom, nullAtom ); numButtons = 1; } for( int i=numButtons; i<WeaponItemDef::MAX_MODE; ++i ) { fireButton[i].SetVisible( false ); } Vector2F view, ui; const Screenport& port = battle->GetEngine()->GetScreenport(); port.WorldToView( target, &view ); port.ViewToUI( view, &ui ); const int DX = 10; // Make sure it fits on the screen. UIRenderer::LayoutListOnScreen( fireButton, numButtons, sizeof(fireButton[0]), ui.x+DX, ui.y, FIRE_BUTTON_SPACING, port ); ParticleSystem* ps = ParticleSystem::Instance(); Game* game = battle->GetGame(); Color4F color0 = Convert_4U8_4F( game->MainPaletteColor( 0, 5 )); Color4F color1 = Convert_4U8_4F( game->MainPaletteColor( 0, 4 )); const Model* model = battle->GetModel( shooterUnit ); if ( model ) { Vector3F trigger; Vector2I t2 = { (int)target.x, (int)target.z }; float fireRotation = shooterUnit->AngleBetween( t2, false ); model->CalcTrigger( &trigger, &fireRotation ); Ray ray = { trigger, target-trigger }; const Model* ignore[] = { model, battle->GetWeaponModel( shooterUnit ), 0 }; Vector3F intersection; Model* m = battle->GetEngine()->IntersectModel( ray, TEST_TRI, 0, 0, ignore, &intersection ); if ( !m || m == targetModel || m == targetWeapon ) { ps->EmitBeam( trigger, target, color0 ); } else { ps->EmitBeam( trigger, intersection, color0 ); ps->EmitBeam( intersection, target, color1 ); } } }
void ProcessAC3D( ACObject* ob, ModelBuilder* builder, const Matrix4& parent, const char* groupFilter ) { Matrix4 m, matrix; m.SetTranslation( ob->loc.x, ob->loc.y, ob->loc.z ); MultMatrix4( parent, m, &matrix ); builder->SetMatrix( matrix ); const char* texname = ob->textureName; if ( texname ) { // Textures just use names, not paths. if ( strrchr( texname, '/' )) { texname = strrchr( texname, '/' )+1; } } builder->SetTexture( texname ? texname : "" ); builder->PushObjectName( ob->name ); Vertex vertex[16]; memset(vertex, 0, sizeof(Vertex)* 16); for( int i = 0; i < ob->num_surf; ++i ) { ACSurface *surf = &ob->surfaces[i]; Vector3F normal = { surf->normal.x, surf->normal.y, surf->normal.z }; if ( normal.Length() == 0.f ) { GLASSERT( 0 ); normal.Set( 0.0f, 1.0f, 0.0f ); } int st = surf->flags & 0xf; if ( st == SURFACE_TYPE_POLYGON && surf->num_vertref<16 ) // hopefully convex and simple { for( int j=0; j<surf->num_vertref; ++j ) { ACVertex *v = &ob->vertices[surf->vertref[j]]; float tx = 0, ty = 0; if (ob->texture ) { float tu = surf->uvs[j].u; float tv = surf->uvs[j].v; tx = ob->texture_offset_x + tu * ob->texture_repeat_x; ty = ob->texture_offset_y + tv * ob->texture_repeat_y; } GLASSERT( j<16 ); vertex[j].pos.Set( v->x, v->y, v->z ); vertex[j].normal = normal; vertex[j].tex.Set( tx, ty ); } int numTri = surf->num_vertref-2; for( int j=0; j<numTri; ++j ) { builder->AddTri( vertex[0], vertex[j+1], vertex[j+2] ); } } else { GLOUTPUT(( "Input polygon or type not supported.\n" )); GLASSERT( 0 ); } } for ( int n = 0; n < ob->num_kids; n++) { if ( groupFilter ) { // Sleazy trick to only look at the top node. Set to node // after we find the top. if ( StrEqual( ob->kids[n]->name, groupFilter ) ) ProcessAC3D(ob->kids[n], builder, matrix, 0 ); } else { ProcessAC3D(ob->kids[n], builder, matrix, 0 ); } } builder->PopObjectName(); }