Ejemplo n.º 1
0
void GameUnit< UnitType >::Draw( const Transformation &parent, const Matrix &parentMatrix )
{
    //Quick shortcut for camera setup phase
    bool myparent = ( this == _Universe->AccessCockpit()->GetParent() );


    Matrix         *ctm;
    Matrix invview;
    Transformation *ct;

    this->cumulative_transformation = linear_interpolate( this->prev_physical_state,
                                                          this->curr_physical_state,
                                                          interpolation_blend_factor );
    this->cumulative_transformation.Compose( parent, parentMatrix );
    this->cumulative_transformation.to_matrix( this->cumulative_transformation_matrix );

    ctm = &this->cumulative_transformation_matrix;
    ct  = &this->cumulative_transformation;
    if (this->graphicOptions.FaceCamera == 1) {
        Vector  p, q, r;
        QVector pos( ctm->p );
        float   wid, hei;
        float   magr = parentMatrix.getR().Magnitude();
        float   magp = parentMatrix.getP().Magnitude();
        float   magq = parentMatrix.getQ().Magnitude();
        CalculateOrientation( pos, p, q, r, wid, hei, 0, false, ctm );
        VectorAndPositionToMatrix( invview, p*magp, q*magq, r*magr, ctm->p );
        ctm = &invview;
    }

#ifdef PERFRAMESOUND
    AUDAdjustSound( sound.engine, cumulative_transformation.position, GetVelocity() );
#endif

    unsigned int i;
    if ( (this->hull < 0) && (!cam_setup_phase) )
        Explode( true, GetElapsedTime() );
    
    float damagelevel = 1.0f;
    unsigned char chardamage = 0;
    
    // We might need to scale rSize, this "average scale" takes the transform matrix into account
    float avgscale = 1.0f;
    
    bool On_Screen = false;
    float Apparent_Size = 0.0f;
    int cloak = this->cloaking;
    Matrix wmat;

    if (!cam_setup_phase) {
        // Following stuff is only needed in actual drawing phase
        if (this->cloaking > this->cloakmin) {
            cloak = (int) (this->cloaking-interpolation_blend_factor*this->pImage->cloakrate*SIMULATION_ATOM);
            cloak = cloakVal( cloak, this->cloakmin, this->pImage->cloakrate, this->pImage->cloakglass );
        }
        if (this->hull < this->maxhull) {
            damagelevel = this->hull/this->maxhull;
            chardamage  = ( 255-(unsigned char) (damagelevel*255) );
        }
        avgscale = sqrt((ctm->getP().MagnitudeSquared() + ctm->getR().MagnitudeSquared()) * 0.5);
        wmat = this->WarpMatrix( *ctm );
    }
    
    if ( ( !(this->invisible&UnitType::INVISUNIT) ) && ( ( !(this->invisible&UnitType::INVISCAMERA) ) || (!myparent) ) ) {
        if (!cam_setup_phase) {
            Camera *camera = _Universe->AccessCamera();
            QVector camerapos = camera->GetPosition();
            
            float minmeshradius =
                ( camera->GetVelocity().Magnitude()+this->Velocity.Magnitude() )*SIMULATION_ATOM;
            
            unsigned int numKeyFrames = this->graphicOptions.NumAnimationPoints;
            for (i = 0; i <= this->nummesh(); i++) {
                //NOTE LESS THAN OR EQUALS...to cover shield mesh
                if (this->meshdata[i] == NULL)
                    continue;
                if (  i == this->nummesh() && (this->meshdata[i]->numFX() == 0 || this->hull < 0) )
                    continue;
                if (this->meshdata[i]->getBlendDst() == ONE) {
                    if ( (this->invisible & UnitType::INVISGLOW) != 0 )
                        continue;
                    if (damagelevel < .9)
                        if ( flickerDamage( this, damagelevel ) )
                            continue;
                }
                QVector TransformedPosition = Transform( *ctm, this->meshdata[i]->Position().Cast() );

                //d can be used for level of detail shit
                float mSize = this->meshdata[i]->rSize() * avgscale;
                double d = ( TransformedPosition-camerapos ).Magnitude();
                double rd  = d-mSize;
                float pixradius = Apparent_Size = mSize*perspectiveFactor(
                    (rd < g_game.znear) ? g_game.znear : rd );
                float lod = pixradius*g_game.detaillevel;
                if (this->meshdata[i]->getBlendDst() == ZERO) {
                    if (UnitType::isUnit() == PLANETPTR && pixradius > 10) {
                        Occlusion::addOccluder(TransformedPosition, mSize, true);
                    } else if (pixradius >= 10.0) {
                        Occlusion::addOccluder(TransformedPosition, mSize, false);
                    }
                }
                if (lod >= 0.5 && pixradius >= 2.5) {
                    double frustd = GFXSphereInFrustum( 
                        TransformedPosition,
                        minmeshradius+mSize );
                    if (frustd) {
                        //if the radius is at least half a pixel at detail 1 (equivalent to pixradius >= 0.5 / detail)
                        float currentFrame = this->meshdata[i]->getCurrentFrame();
                        this->meshdata[i]->Draw( lod, wmat, d, 
                                                 i == this->meshdata.size()-1 ? -1 : cloak,
                                                 (camera->GetNebula() == this->nebula && this->nebula != NULL) ? -1 : 0, 
                                                 chardamage );                                                                                                                                                            //cloakign and nebula
                        On_Screen = true;
                        unsigned int numAnimFrames = 0;
                        static const string default_animation;
                        if ( this->meshdata[i]->getFramesPerSecond()
                            && ( numAnimFrames = this->meshdata[i]->getNumAnimationFrames( default_animation ) ) ) {
                            float currentprogress = floor(
                                this->meshdata[i]->getCurrentFrame()*numKeyFrames/(float) numAnimFrames );
                            if (numKeyFrames
                                && floor( currentFrame*numKeyFrames/(float) numAnimFrames ) != currentprogress) 
                            {
                                this->graphicOptions.Animating = 0;
                                this->meshdata[i]->setCurrentFrame( .1+currentprogress*numAnimFrames/(float) numKeyFrames );
                            } else if (!this->graphicOptions.Animating) {
                                this->meshdata[i]->setCurrentFrame( currentFrame );                                 //dont' budge
                            }
                        }
                    }
                }
            }
        }
        {
            Unit  *un;
            double backup = interpolation_blend_factor;
            int    cur_sim_frame = _Universe->activeStarSystem()->getCurrentSimFrame();
            for (un_iter iter = this->getSubUnits(); (un = *iter); ++iter) {
                float backup = SIMULATION_ATOM;
                if (this->sim_atom_multiplier && un->sim_atom_multiplier)
                    SIMULATION_ATOM = SIMULATION_ATOM*un->sim_atom_multiplier/this->sim_atom_multiplier;
                interpolation_blend_factor = calc_blend_factor( saved_interpolation_blend_factor,
                                                                un->sim_atom_multiplier,
                                                                un->cur_sim_queue_slot,
                                                                cur_sim_frame );
                (un)->Draw( *ct, *ctm );

                SIMULATION_ATOM = backup;
            }
            interpolation_blend_factor = backup;
        }
    } else {
        _Universe->AccessCockpit()->SetupViewPort();         ///this is the final, smoothly calculated cam
        //UpdateHudMatrix();
    }
    /***DEBUGGING cosAngleFromMountTo
     *  UnitCollection *dL = _Universe->activeStarSystem()->getUnitList();
     *  UnitCollection::UnitIterator *tmpiter = dL->createIterator();
     *  GameUnit<UnitType> * curun;
     *  while (curun = tmpiter->current()) {
     *  if (curun->selected) {
     *   float tmpdis;
     *   float tmpf = cosAngleFromMountTo (curun, tmpdis);
     *   VSFileSystem::vs_fprintf (stderr,"%s: <%f d: %f\n", curun->name.c_str(), tmpf, tmpdis);
     *
     *  }
     *  tmpiter->advance();
     *  }
     *  delete tmpiter;
     **/
    if (cam_setup_phase) return;
    int nummounts = this->GetNumMounts();
    for (i = 0; (int) i < nummounts; i++) {
        Mount *mahnt = &this->mounts[i];
        if (game_options.draw_weapons && On_Screen)
            if (mahnt->xyscale != 0 && mahnt->zscale != 0) {
                Mesh *gun = mahnt->type->gun;
                if (gun && mahnt->status != Mount::UNCHOSEN) {
                    Transformation mountLocation( mahnt->GetMountOrientation(), mahnt->GetMountLocation().Cast() );
                    mountLocation.Compose( *ct, wmat );
                    Matrix mat;
                    mountLocation.to_matrix( mat );
                    if (GFXSphereInFrustum( mountLocation.position, gun->rSize()*avgscale ) > 0) {
                        float d   = ( mountLocation.position-_Universe->AccessCamera()->GetPosition() ).Magnitude();
                        float pixradius = gun->rSize()*perspectiveFactor(
                            (d-gun->rSize() < g_game.znear) ? g_game.znear : d-gun->rSize() );
                        float lod = pixradius * g_game.detaillevel;
                        if (lod > 0.5 && pixradius > 2.5) {
                            ScaleMatrix( mat, Vector( mahnt->xyscale, mahnt->xyscale, mahnt->zscale ) );
                            gun->setCurrentFrame( this->mounts[i].ComputeAnimatedFrame( gun ) );
                            gun->Draw( lod, mat, d, cloak,
                                       (_Universe->AccessCamera()->GetNebula() == this->nebula && this->nebula != NULL) ? -1 : 0,
                                       chardamage,
                                       true );                                                                                                                                      //cloakign and nebula
                        }
                        if (mahnt->type->gun1) {
                            pixradius = gun->rSize()*perspectiveFactor(
                                (d-gun->rSize() < g_game.znear) ? g_game.znear : d-gun->rSize() );
                            lod = pixradius * g_game.detaillevel;
                            if (lod > 0.5 && pixradius > 2.5) {
                                gun = mahnt->type->gun1;
                                gun->setCurrentFrame( this->mounts[i].ComputeAnimatedFrame( gun ) );
                                gun->Draw( lod, mat, d, cloak,
                                           (_Universe->AccessCamera()->GetNebula() == this->nebula && this->nebula
                                            != NULL) ? -1 : 0,
                                           chardamage, true );                                                                                                                              //cloakign and nebula
                            }
                        }
                    }
                }
            }
        if (this->mounts[i].type->type == weapon_info::BEAM)
            if (this->mounts[i].ref.gun)
                this->mounts[i].ref.gun->Draw( *ct, wmat,
                                               ( (this->mounts[i].size&weapon_info::AUTOTRACKING)
                                                && (this->mounts[i].time_to_lock <= 0)
                                                && Unit::TargetTracked() ) ? Unit::Target() : NULL, 
                                               this->computer.radar.trackingcone );
    }
    if ( On_Screen && (phalos->NumHalos() > 0) && !( this->docked&(UnitType::DOCKED|UnitType::DOCKED_INSIDE) ) && (Apparent_Size > 5.0f) ) {
        Vector linaccel = this->GetAcceleration();
        Vector angaccel = this->GetAngularAcceleration();
        float  maxaccel = this->GetMaxAccelerationInDirectionOf( wmat.getR(), true );
        Vector velocity = this->GetVelocity();

        float  cmas = this->computer.max_ab_speed()*this->computer.max_ab_speed();
        if (cmas == 0)
            cmas = 1;
        Vector Scale( 1, 1, 1 );         //Now, HaloSystem handles that
        //WARNING: cmas is not a valid maximum speed for the upcoming multi-direction thrusters,
        //nor is maxaccel. Instead, each halo should have its own limits specified in units.csv
        float nebd = (_Universe->AccessCamera()->GetNebula() == this->nebula && this->nebula != NULL) ? -1 : 0;
        float hulld = this->GetHull() > 0 ? damagelevel : 1.0;
        phalos->Draw( wmat, Scale, cloak, nebd, hulld, velocity, linaccel, angaccel, maxaccel, cmas, this->faction );
    }
    if ( On_Screen && !UnitType::graphicOptions.NoDamageParticles
        && !( this->docked&(UnitType::DOCKED|UnitType::DOCKED_INSIDE) ) ) {
        if (damagelevel < .99 && this->nummesh() > 0 && this->GetHull() > 0) {
            unsigned int switcher    = (damagelevel > .8) ? 1
                                       : (damagelevel > .6) ? 2 : (damagelevel > .4) ? 3 : (damagelevel > .2) ? 4 : 5;
            sparkle_accum += GetElapsedTime()*game_options.sparklerate;
            int spawn = (int) (sparkle_accum);
            sparkle_accum -= spawn;
            while (spawn-- > 0) {
                switch (switcher)
                {
                case 5:
                    LaunchOneParticle( *ctm, this->GetVelocity(), ( (long) this )+165, this, damagelevel, this->faction );
                case 4:
                    LaunchOneParticle( *ctm, this->GetVelocity(), ( (long) this )+47, this, damagelevel, this->faction );
                case 3:
                    LaunchOneParticle( *ctm, this->GetVelocity(), ( (long) this )+61, this, damagelevel, this->faction );
                case 2:
                    LaunchOneParticle( *ctm, this->GetVelocity(), ( (long) this )+65537, this, damagelevel, this->faction );
                default:
                    LaunchOneParticle( *ctm, this->GetVelocity(), ( (long) this )+257, this, damagelevel, this->faction );
                }
            }
        } else {
            sparkle_accum = 0;
        }
    } else {
        sparkle_accum = 0;
    }
}
Ejemplo n.º 2
0
void GameUnit< UnitType >::DrawNow( const Matrix &mato, float lod )
{
    static const void *rootunit = NULL;
    if (rootunit == NULL) rootunit = (const void*) this;
    float damagelevel = 1.0;
    unsigned char chardamage    = 0;
    if (this->hull < this->maxhull) {
        damagelevel = this->hull/this->maxhull;
        chardamage  = ( 255-(unsigned char) (damagelevel*255) );
    }
#ifdef VARIABLE_LENGTH_PQR
    const float  vlpqrScaleFactor = SizeScaleFactor;
#else
    const float  vlpqrScaleFactor = 1.f;
#endif
    unsigned int i;
    Matrix mat( mato );
    if (this->graphicOptions.FaceCamera) {
        Vector  p, q, r;
        QVector pos( mato.p );
        float   wid, hei;
        CalculateOrientation( pos, p, q, r, wid, hei, 0, false, &mat );
        pos = mato.p;
        VectorAndPositionToMatrix( mat, p, q, r, pos );
    }
    int cloak = this->cloaking;
    if (this->cloaking > this->cloakmin)
        cloak = cloakVal( cloak, this->cloakmin, this->pImage->cloakrate, this->pImage->cloakglass );
    for (i = 0; i <= this->nummesh(); i++) {
        //NOTE LESS THAN OR EQUALS...to cover shield mesh
        if (this->meshdata[i] == NULL)
            continue;
        QVector TransformedPosition = Transform( mat,
                                                this->meshdata[i]->Position().Cast() );
        float   d = GFXSphereInFrustum( TransformedPosition, this->meshdata[i]->clipRadialSize()*vlpqrScaleFactor );
        if (d)          //d can be used for level of detail
                        //this->meshdata[i]->DrawNow(lod,false,mat,cloak);//cloakign and nebula
            this->meshdata[i]->Draw( lod, mat, d, cloak );
    }
    Unit *un;
    for (un_iter iter = this->getSubUnits(); (un = *iter); ++iter) {
        Matrix temp;
        un->curr_physical_state.to_matrix( temp );
        Matrix submat;
        MultMatrix( submat, mat, temp );
        (un)->DrawNow( submat, lod );
    }
    float  cmas = this->computer.max_ab_speed()*this->computer.max_ab_speed();
    if (cmas == 0)
        cmas = 1;
        Vector Scale( 1, 1, 1 );         //Now, HaloSystem handles that
    int    nummounts = this->GetNumMounts();
    Matrix wmat = this->WarpMatrix( mat );
    for (i = 0; (int) i < nummounts; i++) {
        Mount *mahnt = &this->mounts[i];
        if (game_options.draw_weapons)
            if (mahnt->xyscale != 0 && mahnt->zscale != 0) {
                Mesh *gun = mahnt->type->gun;
                if (gun && mahnt->status != Mount::UNCHOSEN) {
                    Transformation mountLocation( mahnt->GetMountOrientation(), mahnt->GetMountLocation().Cast() );
                    mountLocation.Compose( Transformation::from_matrix( mat ), wmat );
                    Matrix mmat;
                    mountLocation.to_matrix( mmat );
                    if (GFXSphereInFrustum( mountLocation.position, gun->rSize()*vlpqrScaleFactor ) > 0) {
                        float d   = ( mountLocation.position-_Universe->AccessCamera()->GetPosition() ).Magnitude();
                        float lod = gun->rSize()*g_game.detaillevel*perspectiveFactor(
                            (d-gun->rSize() < g_game.znear) ? g_game.znear : d-gun->rSize() );
                        ScaleMatrix( mmat, Vector( mahnt->xyscale, mahnt->xyscale, mahnt->zscale ) );
                        gun->setCurrentFrame( this->mounts[i].ComputeAnimatedFrame( gun ) );
                        gun->Draw( lod, mmat, d, cloak,
                                   (_Universe->AccessCamera()->GetNebula() == this->nebula && this->nebula != NULL) ? -1 : 0,
                                   chardamage,
                                   true );                                                                                                                                       //cloakign and nebula
                        if (mahnt->type->gun1) {
                            gun = mahnt->type->gun1;
                            gun->setCurrentFrame( this->mounts[i].ComputeAnimatedFrame( gun ) );
                            gun->Draw( lod, mmat, d, cloak,
                                       (_Universe->AccessCamera()->GetNebula() == this->nebula && this->nebula
                                        != NULL) ? -1 : 0,
                                       chardamage, true );                                                                                                                               //cloakign and nebula
                        }
                    }
                }
            }
    }
    Vector linaccel = this->GetAcceleration();
    Vector angaccel = this->GetAngularAcceleration();
    float  maxaccel = this->GetMaxAccelerationInDirectionOf( mat.getR(), true );
    Vector velocity = this->GetVelocity();
    if ( !( this->docked & (UnitType::DOCKED | UnitType::DOCKED_INSIDE) ) )
        phalos->Draw( mat, Scale, cloak, 0, this->GetHullPercent(), velocity, linaccel, angaccel, maxaccel, cmas, this->faction );
    if (rootunit == (const void*) this) {
        Mesh::ProcessZFarMeshes();
        Mesh::ProcessUndrawnMeshes();
        rootunit = NULL;
    }
}