Esempio n. 1
0
void Body::UpdateFrame()
{
	if (!(GetFlags() & Body::FLAG_CAN_MOVE_FRAME)) return;

	// falling out of frames
	if (!GetFrame()->IsLocalPosInFrame(GetPosition())) {
		printf("%s leaves frame %s\n", GetLabel().c_str(), GetFrame()->GetLabel().c_str());

		Frame *new_frame = GetFrame()->m_parent;
		if (new_frame) { // don't let fall out of root frame
			matrix4x4d m = matrix4x4d::Identity();
			GetFrame()->ApplyLeavingTransform(m);

			vector3d new_pos = m * GetPosition();

			matrix4x4d rot;
			GetRotMatrix(rot);
			SetRotMatrix(m * rot);
			
			m.ClearToRotOnly();
			SetVelocity(GetFrame()->GetVelocity() + m*(GetVelocity() - 
				GetFrame()->GetStasisVelocityAtPosition(GetPosition())));

			SetFrame(new_frame);
			SetPosition(new_pos);

			Pi::luaOnFrameChanged->Queue(this);
			
			return;
		}
	}

	// entering into frames
	for (std::list<Frame*>::iterator j = GetFrame()->m_children.begin(); j != GetFrame()->m_children.end(); ++j) {
		Frame *kid = *j;
		matrix4x4d m;
		Frame::GetFrameTransform(GetFrame(), kid, m);
		vector3d pos = m * GetPosition();
		if (!kid->IsLocalPosInFrame(pos)) continue;
		
		printf("%s enters frame %s\n", GetLabel().c_str(), kid->GetLabel().c_str());

		SetPosition(pos);
		SetFrame(kid);

		matrix4x4d rot;
		GetRotMatrix(rot);
		SetRotMatrix(m * rot);
				
		// get rid of transforms
		m.ClearToRotOnly();
		SetVelocity(m*(GetVelocity() - kid->GetVelocity())
			+ kid->GetStasisVelocityAtPosition(pos));

		Pi::luaOnFrameChanged->Queue(this);

		break;
	}
}
Esempio n. 2
0
// just forces the orientation
void Ship::AIFaceDirectionImmediate(const vector3d &dir)
{
	vector3d zaxis = -dir;
	vector3d xaxis = vector3d(0.0,1.0,0.0).Cross(zaxis).Normalized();
	vector3d yaxis = zaxis.Cross(xaxis).Normalized();
	matrix4x4d wantOrient = matrix4x4d::MakeRotMatrix(xaxis, yaxis, zaxis).InverseOf();
	SetRotMatrix(wantOrient);
}
Esempio n. 3
0
void Body::OrientOnSurface(double radius, double latitude, double longitude)
{
	vector3d up = vector3d(cos(latitude)*cos(longitude), sin(latitude)*cos(longitude), sin(longitude));
	vector3d pos = radius * up;
	SetPosition(pos);

	vector3d forward = vector3d(0,0,1);
	vector3d other = up.Cross(forward).Normalized();
	forward = other.Cross(up);

	matrix4x4d rot = matrix4x4d::MakeRotMatrix(other, up, forward);
	rot = rot.InverseOf();
	SetRotMatrix(rot);
}
Esempio n. 4
0
void Ship::TestLanded()
{
	m_testLanded = false;
	if (m_launchLockTimeout > 0.0f) return;
	if (m_wheelState < 1.0f) return;
	if (GetFrame()->GetBodyFor()->IsType(Object::PLANET)) {
		double speed = GetVelocity().Length();
		vector3d up = GetPosition().Normalized();
		const double planetRadius = static_cast<Planet*>(GetFrame()->GetBodyFor())->GetTerrainHeight(up);

		if (speed < MAX_LANDING_SPEED) {
			// orient the damn thing right
			// Q: i'm totally lost. why is the inverse of the body rot matrix being used?
			// A: NFI. it just works this way
			matrix4x4d rot;
			GetRotMatrix(rot);
			matrix4x4d invRot = rot.InverseOf();

			// check player is sortof sensibly oriented for landing
			const double dot = vector3d(invRot[1], invRot[5], invRot[9]).Normalized().Dot(up);
			if (dot > 0.99) {

				Aabb aabb;
				GetAabb(aabb);

				// position at zero altitude
				SetPosition(up * (planetRadius - aabb.min.y));

				vector3d forward = rot * vector3d(0,0,1);
				vector3d other = up.Cross(forward).Normalized();
				forward = other.Cross(up);

				rot = matrix4x4d::MakeRotMatrix(other, up, forward);
				rot = rot.InverseOf();
				SetRotMatrix(rot);

				SetVelocity(vector3d(0, 0, 0));
				SetAngVelocity(vector3d(0, 0, 0));
				SetForce(vector3d(0, 0, 0));
				SetTorque(vector3d(0, 0, 0));
				// we don't use DynamicBody::Disable because that also disables the geom, and that must still get collisions
				DisableBodyOnly();
				ClearThrusterState();
				m_flightState = LANDED;
				Sound::PlaySfx("Rough_Landing", 1.0f, 1.0f, 0);
				Pi::luaOnShipLanded->Queue(this, GetFrame()->GetBodyFor());
			}
		}
	}
}
Esempio n. 5
0
CTrigger::CTrigger(CLevel *pLevel, CInputBinaryStream &Stream):
    CObject(OFET_TRIGGER, pLevel), m_nWait(0)
{
    m_iColGroup = COL_TRIGGER;
    m_iColMask = COL_NONE;
    
    m_pColObj = new btCollisionObject();
    m_pColObj->setUserPointer(this);
    m_pColObj->setCollisionFlags(m_pColObj->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE);
    
    m_nUid = Stream.ReadUInt32();
    
    Stream.ReadString2(); // script name
    Stream.ignore(1); // unknown
    bool bBox = Stream.ReadUInt8() ? true : false;
    Stream.ignore(3); // unknown2
    SetResetTime((unsigned)(Stream.ReadFloat() * 1000));
    SetResetsCount(Stream.ReadUInt16()); // 0xFFFF - infinity
    Stream.ignore(2); // unknown3
    SetUseKeyRequired(Stream.ReadUInt8() ? true : false);
    Stream.ReadString2(); // key name
    bool bWeaponActivates = Stream.ReadUInt8() ? true : false;
    Stream.ignore(1); // unknown4
    bool bNpc = Stream.ReadUInt8() ? true : false;
    m_bAuto = Stream.ReadUInt8() ? true : false;
    bool bVehicleActivates = Stream.ReadUInt8() ? true : false;
    SetPos(Stream.ReadVector());
    if(bBox)
    {
        btMatrix3x3 RotMatrix;
        RotMatrix[2] = Stream.ReadVector();
        RotMatrix[0] = Stream.ReadVector();
        RotMatrix[1] = Stream.ReadVector();
        SetRotMatrix(RotMatrix);
        btVector3 Size;// = Stream.ReadVector();
        Size.setY(Stream.ReadFloat());
        Size.setX(Stream.ReadFloat());
        Size.setZ(Stream.ReadFloat());
        SetBoxShape(Size);
        bool bOneWay = Stream.ReadUInt8() ? true : false;
    }
    else
        SetSphereShape(Stream.ReadFloat());
    
    unsigned nAirlockRoomUid = Stream.ReadUInt32();
    unsigned nAttachedToUid = Stream.ReadUInt32();
    unsigned nUseClutterUid = Stream.ReadUInt32();
    m_bEnabled = Stream.ReadUInt8() ? false : true; // is disabled
    float fButtonActiveTime = Stream.ReadFloat();
    float fInsideTime = Stream.ReadFloat();
    Stream.ignore(4); // unknown5
    
    unsigned cLinks = Stream.ReadUInt32();
    if(cLinks > 128)
        CLogger::GetInst().PrintError("Warning! Trigger can be corruptted: %u links\n", cLinks);
    m_Links.reserve(cLinks);
    for(unsigned i = 0; i < cLinks; ++i)
        m_Links.push_back(Stream.ReadUInt32());
    
    AddToWorld();
}
Esempio n. 6
0
void sphere()
{    
    SetGeomScreen(1000);     
    MATRIX m;
    VECTOR trans = {0, 0, 300};
    TransMatrix(&m, &trans);
    SetTransMatrix(&m);      
    const int SPHERE_LATITUDE = 24;
    const int SPHERE_LONGITUDE = 24;
    const int SPHERE_RADIUS = 50;
    SVECTOR* sphere_vector = (SVECTOR*)MemoryManager::malloc(SPHERE_LATITUDE * SPHERE_LONGITUDE * sizeof(*sphere_vector));   
    POLY_G4* poly_sphere = (POLY_G4*)MemoryManager::malloc(SPHERE_LATITUDE * SPHERE_LONGITUDE * sizeof(*poly_sphere));
    {
        /**
         *  x <- r * sin(\alpha) * cos(\beta)
         *  y <- r * sin(\alpha) * sin(\beta)
         *  z <- r * cos(\alpha)
         * avec:
         *   \alpha \in [0, pi] : latitude
         *   \beta \in [0, 2*pi] : longitude
         */ 
        SVECTOR* v = sphere_vector;
        for ( int la = 0; la < SPHERE_LATITUDE; la++ ) {
            int alpha = (TRIGO_PI * la) / SPHERE_LATITUDE;
            int sa = sin4k[alpha];
            int ca = cos4k[alpha];
            for ( int lo = 0; lo < SPHERE_LONGITUDE; lo++, v++ ) {
                int beta = (2 * TRIGO_PI * lo) / SPHERE_LONGITUDE;
                unsigned short x = (SPHERE_RADIUS * sa * cos4k[beta]) / (TRIGO_SCALE * TRIGO_SCALE);
                unsigned short y = (SPHERE_RADIUS * sa * sin4k[beta]) / (TRIGO_SCALE *TRIGO_SCALE);
                unsigned short z = (SPHERE_RADIUS * ca) / TRIGO_SCALE;
                setVector(v, x, y, z);             
            }            
        }
        POLY_G4* p = poly_sphere;        
        for ( int la = 0; la < SPHERE_LATITUDE; la++ ) {
            for ( int lo = 0; lo < SPHERE_LONGITUDE; lo++, p++ ) {
                SetPolyG4(p);
            }
        }        
    }
    set_clear_color(0);
    static const int SPHERE_TRANSITION_STEP = 200;
    static const int SPHERE_STEP_TIME = 600;
            
    enum { SCENE_LAT_FLAT = 1, 
           SCENE_LAT_SMOOTH,
           SCENE_LIGHT_FIX_EDGE,
           SCENE_LIGHT_FIX_SQUARE,
           SCENE_LIGHT_FIX,
           SCENE_LIGHT_MOVE,
           SCENE_LIGHT_CUTOFF,
           SCENE_ZOOM,
           SCENE_LIGHT_SINUS_WAVE, };
    int current_scene = SCENE_LAT_FLAT;
    int t = 0;
    enable_auto_clear_color_buffer();    
    while ( t < SCENE_LIGHT_SINUS_WAVE * SPHERE_STEP_TIME)
    {
        SVECTOR rot = {8*t%4096, 4*t%4096, 10*t%4096};
        RotMatrix(&rot, &m);
        SetRotMatrix(&m);
        
        // update sphere    
        POLY_G4* p = poly_sphere;        
        
        // offset plasma
        static int off = 0; 
        if ( t >= 100 && t % 5 == 0 ) off++;  
                
        // light move
        static int light_move_lat = 0;
        static int light_move_long = 0;
        static int light_move_dlat = 1;
        static int light_move_dlong = 1;           
        if ( t % 1 == 0 ) {
            if ( t % 3 == 0 ) {
                light_move_lat += light_move_dlat; 
                if ( light_move_lat < 0 ) light_move_lat = 0; 
                if ( light_move_lat >= SPHERE_LATITUDE ) light_move_lat = SPHERE_LATITUDE-1;
                if ( light_move_lat == 0 || light_move_lat == SPHERE_LATITUDE-1 ) light_move_dlat *= -1;
            }
            if ( t % 1 == 0 ) {
                light_move_long += light_move_dlong; 
                if ( light_move_long < 0 ) light_move_long = 0; 
                if ( light_move_long >= SPHERE_LONGITUDE ) light_move_long = SPHERE_LONGITUDE-1;
                if ( light_move_long == 0 || light_move_long == SPHERE_LONGITUDE-1 ) light_move_long *= -1;
            }
        }     

        // dynamic cutoff
        static int light_dynamic_distance_max = 50;        
        if ( current_scene == SCENE_LIGHT_CUTOFF && t % 1 == 0 ) {            
            static const int LIGHT_DYNAMIC_DISTANCE_MIN = 20;
            static const int LIGHT_DYNAMIC_DISTANCE_MAX = 60;
            static int light_dynamic_ddist = -1;
            light_dynamic_distance_max += light_dynamic_ddist;
            if ( light_dynamic_distance_max <= LIGHT_DYNAMIC_DISTANCE_MIN || light_dynamic_distance_max >= LIGHT_DYNAMIC_DISTANCE_MAX ) light_dynamic_ddist *= -1;
        }
        int light_dynamic_distance_max2 = light_dynamic_distance_max * light_dynamic_distance_max;   
        
        // dynamic radius         
        if ( current_scene >= SCENE_ZOOM && t % 1 == 0 ) {                        
            static const int ZOOM_MIN = 150;
            static const int ZOOM_MAX = 900;
            static int zoom_stride = 15;
            static int zoom = 300;            
            SetGeomScreen(zoom);            
            zoom += zoom_stride;
            if ( zoom <= ZOOM_MIN || zoom >= ZOOM_MAX ) zoom_stride *= -1;
        }        
                
        int dt = 1;
        for ( int la = 0; la < SPHERE_LATITUDE; la++ ) {
            for ( int lo = 0; lo < SPHERE_LONGITUDE; lo++, p++ ) {                
                int lo_next = (lo+1)%SPHERE_LONGITUDE;
                int la_next = SignalProcessing::min(la+1, SPHERE_LATITUDE-1);                
                SVECTOR* v0 = &sphere_vector[la*SPHERE_LONGITUDE+lo];
                SVECTOR* v1 = &sphere_vector[la*SPHERE_LONGITUDE+lo_next];
                SVECTOR* v2 = &sphere_vector[la_next*SPHERE_LONGITUDE+lo];
                SVECTOR* v3 = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next];
                
                long dmy, flag;
                int otz = 0;
                otz += RotTransPers(v0, (long*)&p->x0, &dmy, &flag);                 
                otz += RotTransPers(v1, (long*)&p->x1, &dmy, &flag);                 
                otz += RotTransPers(v2, (long*)&p->x2, &dmy, &flag);                
                otz += RotTransPers(v3, (long*)&p->x3, &dmy, &flag);
                otz /= 4;
                limitRange(otz, 0, OT_LENGTH-1);
                AddPrim(ot + OT_LENGTH - 1 - otz, p);                
                if ( t < SCENE_LAT_FLAT*SPHERE_STEP_TIME ) { // latitude same flat color
                    current_scene = SCENE_LAT_FLAT;
                    unsigned char b = 255 * la / SPHERE_LATITUDE;                     
                    setRGB0(p, b, b, b);
                    setRGB1(p, b, b, b);
                    setRGB2(p, b, b, b);
                    setRGB3(p, b, b, b);
                } else if ( t < SCENE_LAT_SMOOTH*SPHERE_STEP_TIME ) { // latitude same smooth color
                    current_scene = SCENE_LAT_SMOOTH;
                    unsigned char b = 255 * la / SPHERE_LATITUDE;  
                    unsigned char bb = 255 * ((la+1)%SPHERE_LATITUDE) / SPHERE_LATITUDE;
                    if ( t < (SCENE_LAT_SMOOTH-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) {
                        int d= (t%SPHERE_TRANSITION_STEP);
                        b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                    } 
                    setRGB0(p, b, b, b);
                    setRGB1(p, b, b, b);
                    setRGB2(p, bb, bb, bb);
                    setRGB3(p, bb, bb, bb);
                } else if ( t < SCENE_LIGHT_FIX_EDGE*SPHERE_STEP_TIME ) { // latitude same smooth color + lighting fix
                    dt = 3;
                    current_scene = SCENE_LIGHT_FIX_EDGE;
                    unsigned char b = 255;
                    unsigned char bb = 255;
                    const int LIGHT_LAT = 3*SPHERE_LATITUDE/4;
                    const int LIGHT_LONG = SPHERE_LONGITUDE/4;
                    const int LIGHT_DISTANCE_MAX = 50;
                    const int LIGHT_DISTANCE_MAX2 = LIGHT_DISTANCE_MAX * LIGHT_DISTANCE_MAX;
                    SVECTOR* l = &sphere_vector[LIGHT_LAT*SPHERE_LONGITUDE+LIGHT_LONG];
                    SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo];
                    SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo];
                    int d = SignalProcessing::dist2(l, v);
                    int dd = SignalProcessing::dist2(l, vv);
                    b = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - d) * b) / LIGHT_DISTANCE_MAX2;
                    bb = (SignalProcessing::max(0,  LIGHT_DISTANCE_MAX2 - dd) * bb) / LIGHT_DISTANCE_MAX2;
                    // smooth
                    if ( t < (SCENE_LIGHT_FIX-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) {
                        int d= (t%SPHERE_TRANSITION_STEP);
                        b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                    } 
                    setRGB0(p, b, b, b);
                    setRGB1(p, b, b, b);
                    setRGB2(p, bb, bb, bb);
                    setRGB3(p, bb, bb, bb);
                } else if ( t < SCENE_LIGHT_FIX_SQUARE*SPHERE_STEP_TIME ) { // latitude same smooth color + lighting fix
                    dt = 3;
                    current_scene = SCENE_LIGHT_FIX_SQUARE;
                    unsigned char b = 255;
                    unsigned char bb = 255;
                    unsigned char bbb = 255;
                    unsigned char bbbb = 255;
                    const int LIGHT_LAT = 3*SPHERE_LATITUDE/4;
                    const int LIGHT_LONG = SPHERE_LONGITUDE/4;
                    const int LIGHT_DISTANCE_MAX = 50;
                    const int LIGHT_DISTANCE_MAX2 = LIGHT_DISTANCE_MAX * LIGHT_DISTANCE_MAX;
                    SVECTOR* l = &sphere_vector[LIGHT_LAT*SPHERE_LONGITUDE+LIGHT_LONG];
                    SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo];                    
                    SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo];                    
                    SVECTOR* vvv = &sphere_vector[la*SPHERE_LONGITUDE+lo_next];
                    SVECTOR* vvvv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next];
                    int d = SignalProcessing::dist2(l, v);
                    int dd = SignalProcessing::dist2(l, vv);
                    int ddd = SignalProcessing::dist2(l, vvv);
                    int dddd = SignalProcessing::dist2(l, vvvv);
                    b = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - d) * b) / LIGHT_DISTANCE_MAX2;
                    bb = (SignalProcessing::max(0,  LIGHT_DISTANCE_MAX2 - dd) * bb) / LIGHT_DISTANCE_MAX2;
                    bbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - ddd) * bbb) / LIGHT_DISTANCE_MAX2;
                    bbbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - dddd) * bbbb) / LIGHT_DISTANCE_MAX2;                    
                    // smooth
                    if ( t < (SCENE_LIGHT_FIX-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) {
                        int d= (t%SPHERE_TRANSITION_STEP);
                        b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbb = (bbb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbbb = (bbbb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                    } 
                    setRGB0(p, b, b, b);
                    setRGB1(p, bb, bb, bb);
                    setRGB2(p, bbb, bbb, bbb);
                    setRGB3(p, bbbb, bbbb, bbbb);                     
                } else if ( t < SCENE_LIGHT_FIX*SPHERE_STEP_TIME ) { // latitude same smooth color + lighting fix
                    dt = 1;
                    current_scene = SCENE_LIGHT_FIX;
                    unsigned char b = 255;
                    unsigned char bb = 255;
                    unsigned char bbb = 255;
                    unsigned char bbbb = 255;
                    const int LIGHT_LAT = 3*SPHERE_LATITUDE/4;
                    const int LIGHT_LONG = SPHERE_LONGITUDE/4;
                    const int LIGHT_DISTANCE_MAX = 50;
                    const int LIGHT_DISTANCE_MAX2 = LIGHT_DISTANCE_MAX * LIGHT_DISTANCE_MAX;
                    SVECTOR* l = &sphere_vector[LIGHT_LAT*SPHERE_LONGITUDE+LIGHT_LONG];
                    SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo];                    
                    SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo];                    
                    SVECTOR* vvv = &sphere_vector[la*SPHERE_LONGITUDE+lo_next];
                    SVECTOR* vvvv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next];
                    int d = SignalProcessing::dist2(l, v);
                    int dd = SignalProcessing::dist2(l, vv);
                    int ddd = SignalProcessing::dist2(l, vvv);
                    int dddd = SignalProcessing::dist2(l, vvvv);
                    b = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - d) * b) / LIGHT_DISTANCE_MAX2;
                    bb = (SignalProcessing::max(0,  LIGHT_DISTANCE_MAX2 - dd) * bb) / LIGHT_DISTANCE_MAX2;
                    bbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - ddd) * bbb) / LIGHT_DISTANCE_MAX2;
                    bbbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - dddd) * bbbb) / LIGHT_DISTANCE_MAX2;                    
                    // smooth
                    if ( t < (SCENE_LIGHT_FIX-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) {
                        int d= (t%SPHERE_TRANSITION_STEP);
                        b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbb = (bbb * d + p->r1 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbbb = (bbbb * d + p->r3 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                    } 
                    setRGB0(p, b, b, b);
                    setRGB2(p, bb, bb, bb);
                    setRGB1(p, bbb, bbb, bbb);
                    setRGB3(p, bbbb, bbbb, bbbb);                    
                } else if ( t < SCENE_LIGHT_MOVE*SPHERE_STEP_TIME ) { // latitude same smooth color + lighting move
                    current_scene = SCENE_LIGHT_MOVE;
                    unsigned char b = 255;
                    unsigned char bb = 255;                    
                    unsigned char bbb = 255;                    
                    unsigned char bbbb = 255;                    
                    const int LIGHT_DISTANCE_MAX = 50;
                    const int LIGHT_DISTANCE_MAX2 = LIGHT_DISTANCE_MAX * LIGHT_DISTANCE_MAX;
                    // light
                    {
                        SVECTOR* l = &sphere_vector[light_move_lat*SPHERE_LONGITUDE+light_move_long];
                        SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo];                    
                        SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo];                    
                        SVECTOR* vvv = &sphere_vector[la*SPHERE_LONGITUDE+lo_next];
                        SVECTOR* vvvv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next];
                        int d = SignalProcessing::dist2(l, v);
                        int dd = SignalProcessing::dist2(l, vv);
                        int ddd = SignalProcessing::dist2(l, vvv);
                        int dddd = SignalProcessing::dist2(l, vvvv);
                        b = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - d) * b) / LIGHT_DISTANCE_MAX2;
                        bb = (SignalProcessing::max(0,  LIGHT_DISTANCE_MAX2 - dd) * bb) / LIGHT_DISTANCE_MAX2;
                        bbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - ddd) * bbb) / LIGHT_DISTANCE_MAX2;
                        bbbb = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - dddd) * bbbb) / LIGHT_DISTANCE_MAX2;                       
                    }
                    // smooth
                    if ( t < (SCENE_LIGHT_MOVE-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) {
                        int d= (t%SPHERE_TRANSITION_STEP);
                        b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbb = (bbb * d + p->r1 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbbb = (bbbb * d + p->r3 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                    } 
                    setRGB0(p, b, b, b);
                    setRGB2(p, bb, bb, bb);
                    setRGB1(p, bbb, bbb, bbb);
                    setRGB3(p, bbbb, bbbb, bbbb);      
                } else if ( t < SCENE_LIGHT_CUTOFF*SPHERE_STEP_TIME ) { // latitude same smooth color + lighting move + dynamic cutoff 
                    current_scene = SCENE_LIGHT_CUTOFF;
                    unsigned char b = 255;
                    unsigned char bb = 255;
                    unsigned char bbb = 255;
                    unsigned char bbbb = 255;
                    // light
                    {
                        SVECTOR* l = &sphere_vector[light_move_lat*SPHERE_LONGITUDE+light_move_long];
                        SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo];                    
                        SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo];                    
                        SVECTOR* vvv = &sphere_vector[la*SPHERE_LONGITUDE+lo_next];
                        SVECTOR* vvvv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next];
                        int d = SignalProcessing::dist2(l, v);
                        int dd = SignalProcessing::dist2(l, vv);
                        int ddd = SignalProcessing::dist2(l, vvv);
                        int dddd = SignalProcessing::dist2(l, vvvv);
                        b = (SignalProcessing::max(0, light_dynamic_distance_max2 - d) * b) / light_dynamic_distance_max2;
                        bb = (SignalProcessing::max(0,  light_dynamic_distance_max2 - dd) * bb) / light_dynamic_distance_max2;                    
                        bbb = (SignalProcessing::max(0, light_dynamic_distance_max2 - ddd) * bbb) / light_dynamic_distance_max2;
                        bbbb = (SignalProcessing::max(0, light_dynamic_distance_max2 - dddd) * bbbb) / light_dynamic_distance_max2;
                    }
                    // smooth
                    if ( t < (SCENE_LIGHT_CUTOFF-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) {
                        int d= (t%SPHERE_TRANSITION_STEP);
                        b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbb = (bbb * d + p->r1 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbbb = (bbbb * d + p->r3 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                    } 
                    setRGB0(p, b, b, b);
                    setRGB2(p, bb, bb, bb);
                    setRGB1(p, bbb, bbb, bbb);
                    setRGB3(p, bbbb, bbbb, bbbb);     
                } else if ( t < SCENE_ZOOM*SPHERE_STEP_TIME ) { // latitude same smooth color + lighting move + dynamic cutoff + zoom
                    current_scene = SCENE_ZOOM;
                    unsigned char b = 255;
                    unsigned char bb = 255;
                    unsigned char bbb = 255;
                    unsigned char bbbb = 255;
                    // light
                    {
                        SVECTOR* l = &sphere_vector[light_move_lat*SPHERE_LONGITUDE+light_move_long];
                        SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo];                    
                        SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo];                    
                        SVECTOR* vvv = &sphere_vector[la*SPHERE_LONGITUDE+lo_next];
                        SVECTOR* vvvv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next];
                        int d = SignalProcessing::dist2(l, v);
                        int dd = SignalProcessing::dist2(l, vv);
                        int ddd = SignalProcessing::dist2(l, vvv);
                        int dddd = SignalProcessing::dist2(l, vvvv);
                        b = (SignalProcessing::max(0, light_dynamic_distance_max2 - d) * b) / light_dynamic_distance_max2;
                        bb = (SignalProcessing::max(0,  light_dynamic_distance_max2 - dd) * bb) / light_dynamic_distance_max2;                    
                        bbb = (SignalProcessing::max(0, light_dynamic_distance_max2 - ddd) * bbb) / light_dynamic_distance_max2;
                        bbbb = (SignalProcessing::max(0, light_dynamic_distance_max2 - dddd) * bbbb) / light_dynamic_distance_max2;                   
                    }
                    // smooth
                    if ( t < (SCENE_ZOOM-1)*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) {
                        int d= (t%SPHERE_TRANSITION_STEP);
                        b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbb = (bbb * d + p->r1 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbbb = (bbbb * d + p->r3 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                    } 
                    setRGB0(p, b, b, b);
                    setRGB2(p, bb, bb, bb);
                    setRGB1(p, bbb, bbb, bbb);
                    setRGB3(p, bbbb, bbbb, bbbb);
                }                 
                else { // smooth bande move + lighting move
                    current_scene = SCENE_LIGHT_SINUS_WAVE;
                    const int LIGHT_DISTANCE_MAX = 50;
                    const int LIGHT_DISTANCE_MAX2 = LIGHT_DISTANCE_MAX * LIGHT_DISTANCE_MAX;
                    const int NB_COLOR = 5;                    
                    unsigned char b = (255 * (((la+off)%SPHERE_LATITUDE)%NB_COLOR)) / (NB_COLOR-1);
                    unsigned char bb = (255 * (((la+1+off)%SPHERE_LATITUDE)%NB_COLOR)) / (NB_COLOR-1);
                    unsigned char bbb = (255 * (((la+off)%SPHERE_LATITUDE)%NB_COLOR)) / (NB_COLOR-1);
                    unsigned char bbbb = (255 * (((la+1+off)%SPHERE_LATITUDE)%NB_COLOR)) / (NB_COLOR-1);
                    // light
                    {
                        SVECTOR* l = &sphere_vector[light_move_lat*SPHERE_LONGITUDE+light_move_long];
                        SVECTOR* v = &sphere_vector[la*SPHERE_LONGITUDE+lo];                    
                        SVECTOR* vv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo];                    
                        SVECTOR* vvv = &sphere_vector[la*SPHERE_LONGITUDE+lo_next];
                        SVECTOR* vvvv = &sphere_vector[la_next*SPHERE_LONGITUDE+lo_next];
                        int d = SignalProcessing::dist2(l, v);
                        int dd = SignalProcessing::dist2(l, vv);
                        int ddd = SignalProcessing::dist2(l, vvv);
                        int dddd = SignalProcessing::dist2(l, vvvv);
                        b = (SignalProcessing::max(0, LIGHT_DISTANCE_MAX2 - d) * b) / LIGHT_DISTANCE_MAX2;
                        bb = (SignalProcessing::max(0,  LIGHT_DISTANCE_MAX2 - dd) * bb) / LIGHT_DISTANCE_MAX2; 
                        bbb = (SignalProcessing::max(0,  LIGHT_DISTANCE_MAX2 - ddd) * bbb) / LIGHT_DISTANCE_MAX2; 
                        bbbb = (SignalProcessing::max(0,  LIGHT_DISTANCE_MAX2 - dddd) * bbbb) / LIGHT_DISTANCE_MAX2; 
                    }
                    // smooth
                    if ( t < 5*SPHERE_STEP_TIME + SPHERE_TRANSITION_STEP ) {
                        int d= (t%SPHERE_TRANSITION_STEP);
                        b = (b * d + p->r0 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bb = (bb * d + p->r2 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbb = (bbb * d + p->r1 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                        bbbb = (bbbb * d + p->r3 * (SPHERE_TRANSITION_STEP - d)) / SPHERE_TRANSITION_STEP;
                    } 
                    setRGB0(p, b, b, b);
                    setRGB2(p, bb, bb, bb);
                    setRGB1(p, bbb, bbb, bbb);
                    setRGB3(p, bbbb, bbbb, bbbb);
                }                
            }
        }        
        display();
        t += dt;
    }    
    MemoryManager::free(sphere_vector);    
    MemoryManager::free(poly_sphere);    
}