void COverheadController::MouseWheelMove(float move)
{
	if (move == 0.0f)
		return;

	camHandler->CameraTransition(0.05f);

	const float shiftSpeed = (KeyInput::GetKeyModState(KMOD_SHIFT) ? 3.0f : 1.0f);
	const float altZoomDist = height * move * 0.007f * shiftSpeed;
	
	// tilt the camera if LCTRL is pressed
	//
	// otherwise holding down LALT uses 'instant-zoom'
	// from here to the end of the function (smoothed)
	if (KeyInput::GetKeyModState(KMOD_CTRL)) {
		angle += (move * tiltSpeed * shiftSpeed * 0.025f) * angleStep;
		angle = Clamp(angle, 0.01f, fastmath::HALFPI);
	} else {
		if (move < 0.0f) {
			// ZOOM IN to mouse cursor instead of mid screen
			float3 cpos = pos - dir * height;
			float dif = -altZoomDist;

			if ((height - dif) < 60.0f) {
				dif = height - 60.0f;
			}
			if (KeyInput::GetKeyModState(KMOD_ALT)) {
				// instazoom in to standard view
				dif = (height - oldAltHeight) / mouse->dir.y * dir.y;
			}

			float3 wantedPos = cpos + mouse->dir * dif;
			float newHeight = CGround::LineGroundCol(wantedPos, wantedPos + dir * 15000, false);

			if (newHeight < 0.0f) {
				newHeight = height * (1.0f + move * 0.007f * shiftSpeed);
			}
			if ((wantedPos.y + (dir.y * newHeight)) < 0.0f) {
				newHeight = -wantedPos.y / dir.y;
			}
			if (newHeight < maxHeight) {
				height = newHeight;
				pos = wantedPos + dir * height;
			}
		} else {
			// ZOOM OUT from mid screen
			if (KeyInput::GetKeyModState(KMOD_ALT)) {
				// instazoom out to maximum height
				if (height < maxHeight*0.5f && changeAltHeight) {
					oldAltHeight = height;
					changeAltHeight = false;
				}
				height = maxHeight;
				pos.x  = mapDims.mapx * SQUARE_SIZE * 0.5f;
				pos.z  = mapDims.mapy * SQUARE_SIZE * 0.55f; // somewhat longer toward bottom
			} else {
				height *= (1.0f + (altZoomDist / height));
			}
		}

		// instant-zoom: turn on the smooth transition and reset the camera tilt
		if (KeyInput::GetKeyModState(KMOD_ALT)) {
			angle = DEFAULT_ANGLE;
			camHandler->CameraTransition(1.0f);
		} else {
			changeAltHeight = true;
		}
	}

	Update();
}
Exemple #2
0
 float MathHelper::SmoothStep(float val1, float val2, float t)
 {
     t = Clamp(t, 0, 1);
     return Lerp(val1, val2, t*t*(3 - 2 * t));
 }
Exemple #3
0
void UpdateOptions()
{
    if(optionsInit)
    {
        mouse.x = mouse_x;mouse.y = mouse_y;
        mouseBPrev = mouseB;
        mouseB = mouse_b;

        if(ABB(mouse,backButt) && mouseB == 1)
        {
            hFile = HeroF->str;
            zFile = ZombieF->str;
            SaveConfig("config.cfg");

            GameState = MAINMENU;
        }
        if(ABB(mouse,fxPlus) && mouseB == 1)
        {
            fxVol = Clamp(0,fxVol+1,255);
            fxAm.w = fxVol;
        }
        if(ABB(mouse,fxMinus) && mouseB == 1)
        {
            fxVol = Clamp(0,fxVol-1,255);
            fxAm.w = fxVol;
        }
        if(ABB(mouse,musPlus) && mouseB == 1)
        {
            musicVol = Clamp(0,musicVol+1,255);
            adjust_sample(bgMusic,musicVol,127,1000,1);
            musAm.w = musicVol;
        }
        if(ABB(mouse,musMinus) && mouseB == 1)
        {
            musicVol = Clamp(0,musicVol-1,255);
            adjust_sample(bgMusic,musicVol,127,1000,1);
            musAm.w = musicVol;
        }

        if(ABB(mouse,zombieNext) && mouseB == 0 && mouseBPrev == 1)
        {
            if(ZombieF->next) ZombieF = ZombieF->next;
        }
        if(ABB(mouse,zombiePrev) && mouseB == 0 && mouseBPrev == 1)
        {
            if(ZombieF->prev) ZombieF = ZombieF->prev;
        }
        if(ABB(mouse,heroNext) && mouseB == 0 && mouseBPrev == 1)
        {
            if(HeroF->next) HeroF = HeroF->next;
        }
        if(ABB(mouse,heroPrev) && mouseB == 0 && mouseBPrev == 1)
        {
            if(HeroF->prev) HeroF = HeroF->prev;
        }
    }
    else
    {
        InitOptions();
    }
}
Exemple #4
0
void SoundSource3D::SetOuterAngle(float angle)
{
    outerAngle_ = Clamp(angle, 0.0f, DEFAULT_ANGLE);
    MarkNetworkUpdate();
}
Exemple #5
0
void Batch::Prepare(View* view, bool setModelTransform) const
{
    if (!vertexShader_ || !pixelShader_)
        return;
    
    Graphics* graphics = view->GetGraphics();
    Renderer* renderer = view->GetRenderer();
    Node* cameraNode = camera_ ? camera_->GetNode() : 0;
    Light* light = lightQueue_ ? lightQueue_->light_ : 0;
    Texture2D* shadowMap = lightQueue_ ? lightQueue_->shadowMap_ : 0;

    // Set pass / material-specific renderstates
    if (pass_ && material_)
    {
        bool isShadowPass = pass_->GetType() == PASS_SHADOW;
        
        BlendMode blend = pass_->GetBlendMode();
        // Turn additive blending into subtract if the light is negative
        if (light && light->IsNegative())
        {
            if (blend == BLEND_ADD)
                blend = BLEND_SUBTRACT;
            else if (blend == BLEND_ADDALPHA)
                blend = BLEND_SUBTRACTALPHA;
        }
        
        graphics->SetBlendMode(blend);
        renderer->SetCullMode(isShadowPass ? material_->GetShadowCullMode() : material_->GetCullMode(), camera_);
        if (!isShadowPass)
        {
            const BiasParameters& depthBias = material_->GetDepthBias();
            graphics->SetDepthBias(depthBias.constantBias_, depthBias.slopeScaledBias_);
        }
        graphics->SetDepthTest(pass_->GetDepthTestMode());
        graphics->SetDepthWrite(pass_->GetDepthWrite());
    }
    
    // Set shaders first. The available shader parameters and their register/uniform positions depend on the currently set shaders
    graphics->SetShaders(vertexShader_, pixelShader_);
    
    // Set global (per-frame) shader parameters
    if (graphics->NeedParameterUpdate(SP_FRAME, (void*)0))
        view->SetGlobalShaderParameters();
    
    // Set camera shader parameters
    unsigned cameraHash = overrideView_ ? (unsigned)(size_t)camera_ + 4 : (unsigned)(size_t)camera_;
    if (graphics->NeedParameterUpdate(SP_CAMERA, reinterpret_cast<void*>(cameraHash)))
        view->SetCameraShaderParameters(camera_, true, overrideView_);
    
    // Set viewport shader parameters
    IntRect viewport = graphics->GetViewport();
    IntVector2 viewSize = IntVector2(viewport.Width(), viewport.Height());
    unsigned viewportHash = viewSize.x_ | (viewSize.y_ << 16);
    
    if (graphics->NeedParameterUpdate(SP_VIEWPORT, reinterpret_cast<void*>(viewportHash)))
    {
        // During renderpath commands the G-Buffer or viewport texture is assumed to always be viewport-sized
        view->SetGBufferShaderParameters(viewSize, IntRect(0, 0, viewSize.x_, viewSize.y_));
    }
    
    // Set model or skinning transforms
    if (setModelTransform && graphics->NeedParameterUpdate(SP_OBJECTTRANSFORM, worldTransform_))
    {
        if (geometryType_ == GEOM_SKINNED)
        {
            graphics->SetShaderParameter(VSP_SKINMATRICES, reinterpret_cast<const float*>(worldTransform_), 
                12 * numWorldTransforms_);
        }
        else
            graphics->SetShaderParameter(VSP_MODEL, *worldTransform_);
        
        // Set the orientation for billboards, either from the object itself or from the camera
        if (geometryType_ == GEOM_BILLBOARD)
        {
            if (numWorldTransforms_ > 1)
                graphics->SetShaderParameter(VSP_BILLBOARDROT, worldTransform_[1].RotationMatrix());
            else
                graphics->SetShaderParameter(VSP_BILLBOARDROT, cameraNode->GetWorldRotation().RotationMatrix());
        }
    }
    
    // Set zone-related shader parameters
    BlendMode blend = graphics->GetBlendMode();
    // If the pass is additive, override fog color to black so that shaders do not need a separate additive path
    bool overrideFogColorToBlack = blend == BLEND_ADD || blend == BLEND_ADDALPHA;
    unsigned zoneHash = (unsigned)(size_t)zone_;
    if (overrideFogColorToBlack)
        zoneHash += 0x80000000;
    if (zone_ && graphics->NeedParameterUpdate(SP_ZONE, reinterpret_cast<void*>(zoneHash)))
    {
        graphics->SetShaderParameter(VSP_AMBIENTSTARTCOLOR, zone_->GetAmbientStartColor());
        graphics->SetShaderParameter(VSP_AMBIENTENDCOLOR, zone_->GetAmbientEndColor().ToVector4() - zone_->GetAmbientStartColor().ToVector4());
        
        const BoundingBox& box = zone_->GetBoundingBox();
        Vector3 boxSize = box.Size();
        Matrix3x4 adjust(Matrix3x4::IDENTITY);
        adjust.SetScale(Vector3(1.0f / boxSize.x_, 1.0f / boxSize.y_, 1.0f / boxSize.z_));
        adjust.SetTranslation(Vector3(0.5f, 0.5f, 0.5f));
        Matrix3x4 zoneTransform = adjust * zone_->GetInverseWorldTransform();
        graphics->SetShaderParameter(VSP_ZONE, zoneTransform);
        
        graphics->SetShaderParameter(PSP_AMBIENTCOLOR, zone_->GetAmbientColor());
        graphics->SetShaderParameter(PSP_FOGCOLOR, overrideFogColorToBlack ? Color::BLACK : zone_->GetFogColor());
        
        float farClip = camera_->GetFarClip();
        float fogStart = Min(zone_->GetFogStart(), farClip);
        float fogEnd = Min(zone_->GetFogEnd(), farClip);
        if (fogStart >= fogEnd * (1.0f - M_LARGE_EPSILON))
            fogStart = fogEnd * (1.0f - M_LARGE_EPSILON);
        float fogRange = Max(fogEnd - fogStart, M_EPSILON);
        Vector4 fogParams(fogEnd / farClip, farClip / fogRange, 0.0f, 0.0f);
        
        Node* zoneNode = zone_->GetNode();
        if (zone_->GetHeightFog() && zoneNode)
        {
            Vector3 worldFogHeightVec = zoneNode->GetWorldTransform() * Vector3(0.0f, zone_->GetFogHeight(), 0.0f);
            fogParams.z_ = worldFogHeightVec.y_;
            fogParams.w_ = zone_->GetFogHeightScale() / Max(zoneNode->GetWorldScale().y_, M_EPSILON);
        }
        
        graphics->SetShaderParameter(PSP_FOGPARAMS, fogParams);
    }
    
    // Set light-related shader parameters
    if (lightQueue_)
    {
        if (graphics->NeedParameterUpdate(SP_VERTEXLIGHTS, lightQueue_) && graphics->HasShaderParameter(VS, VSP_VERTEXLIGHTS))
        {
            Vector4 vertexLights[MAX_VERTEX_LIGHTS * 3];
            const PODVector<Light*>& lights = lightQueue_->vertexLights_;
            
            for (unsigned i = 0; i < lights.Size(); ++i)
            {
                Light* vertexLight = lights[i];
                Node* vertexLightNode = vertexLight->GetNode();
                LightType type = vertexLight->GetLightType();
                
                // Attenuation
                float invRange, cutoff, invCutoff;
                if (type == LIGHT_DIRECTIONAL)
                    invRange = 0.0f;
                else
                    invRange = 1.0f / Max(vertexLight->GetRange(), M_EPSILON);
                if (type == LIGHT_SPOT)
                {
                    cutoff = Cos(vertexLight->GetFov() * 0.5f);
                    invCutoff = 1.0f / (1.0f - cutoff);
                }
                else
                {
                    cutoff = -1.0f;
                    invCutoff = 1.0f;
                }
                
                // Color
                float fade = 1.0f;
                float fadeEnd = vertexLight->GetDrawDistance();
                float fadeStart = vertexLight->GetFadeDistance();
                
                // Do fade calculation for light if both fade & draw distance defined
                if (vertexLight->GetLightType() != LIGHT_DIRECTIONAL && fadeEnd > 0.0f && fadeStart > 0.0f && fadeStart < fadeEnd)
                    fade = Min(1.0f - (vertexLight->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 1.0f);
                
                Color color = vertexLight->GetEffectiveColor() * fade;
                vertexLights[i * 3] = Vector4(color.r_, color.g_, color.b_, invRange);
                
                // Direction
                vertexLights[i * 3 + 1] = Vector4(-(vertexLightNode->GetWorldDirection()), cutoff);
                
                // Position
                vertexLights[i * 3 + 2] = Vector4(vertexLightNode->GetWorldPosition(), invCutoff);
            }
            
            if (lights.Size())
                graphics->SetShaderParameter(VSP_VERTEXLIGHTS, vertexLights[0].Data(), lights.Size() * 3 * 4);
        }
    }
    
    if (light && graphics->NeedParameterUpdate(SP_LIGHT, light))
    {
        // Deferred light volume batches operate in a camera-centered space. Detect from material, zone & pass all being null
        bool isLightVolume = !material_ && !pass_ && !zone_;
        
        Matrix3x4 cameraEffectiveTransform = camera_->GetEffectiveWorldTransform();
        Vector3 cameraEffectivePos = cameraEffectiveTransform.Translation();

        Node* lightNode = light->GetNode();
        Matrix3 lightWorldRotation = lightNode->GetWorldRotation().RotationMatrix();
        
        graphics->SetShaderParameter(VSP_LIGHTDIR, lightWorldRotation * Vector3::BACK);
        
        float atten = 1.0f / Max(light->GetRange(), M_EPSILON);
        graphics->SetShaderParameter(VSP_LIGHTPOS, Vector4(lightNode->GetWorldPosition(), atten));
        
        if (graphics->HasShaderParameter(VS, VSP_LIGHTMATRICES))
        {
            switch (light->GetLightType())
            {
            case LIGHT_DIRECTIONAL:
                {
                    Matrix4 shadowMatrices[MAX_CASCADE_SPLITS];
                    unsigned numSplits = lightQueue_->shadowSplits_.Size();
                    for (unsigned i = 0; i < numSplits; ++i)
                        CalculateShadowMatrix(shadowMatrices[i], lightQueue_, i, renderer, Vector3::ZERO);
                    
                    graphics->SetShaderParameter(VSP_LIGHTMATRICES, shadowMatrices[0].Data(), 16 * numSplits);
                }
                break;
                
            case LIGHT_SPOT:
                {
                    Matrix4 shadowMatrices[2];
                    
                    CalculateSpotMatrix(shadowMatrices[0], light, Vector3::ZERO);
                    bool isShadowed = shadowMap && graphics->HasTextureUnit(TU_SHADOWMAP);
                    if (isShadowed)
                        CalculateShadowMatrix(shadowMatrices[1], lightQueue_, 0, renderer, Vector3::ZERO);
                    
                    graphics->SetShaderParameter(VSP_LIGHTMATRICES, shadowMatrices[0].Data(), isShadowed ? 32 : 16);
                }
                break;
                
            case LIGHT_POINT:
                {
                    Matrix4 lightVecRot(lightNode->GetWorldRotation().RotationMatrix());
                    // HLSL compiler will pack the parameters as if the matrix is only 3x4, so must be careful to not overwrite
                    // the next parameter
                    #ifdef URHO3D_OPENGL
                    graphics->SetShaderParameter(VSP_LIGHTMATRICES, lightVecRot.Data(), 16);
                    #else
                    graphics->SetShaderParameter(VSP_LIGHTMATRICES, lightVecRot.Data(), 12);
                    #endif
                }
                break;
            }
        }
        
        float fade = 1.0f;
        float fadeEnd = light->GetDrawDistance();
        float fadeStart = light->GetFadeDistance();
        
        // Do fade calculation for light if both fade & draw distance defined
        if (light->GetLightType() != LIGHT_DIRECTIONAL && fadeEnd > 0.0f && fadeStart > 0.0f && fadeStart < fadeEnd)
            fade = Min(1.0f - (light->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 1.0f);
        
        // Negative lights will use subtract blending, so write absolute RGB values to the shader parameter
        graphics->SetShaderParameter(PSP_LIGHTCOLOR, Color(light->GetEffectiveColor().Abs(),
            light->GetEffectiveSpecularIntensity()) * fade);
        graphics->SetShaderParameter(PSP_LIGHTDIR, lightWorldRotation * Vector3::BACK);
        graphics->SetShaderParameter(PSP_LIGHTPOS, Vector4((isLightVolume ? (lightNode->GetWorldPosition() -
            cameraEffectivePos) : lightNode->GetWorldPosition()), atten));
        
        if (graphics->HasShaderParameter(PS, PSP_LIGHTMATRICES))
        {
            switch (light->GetLightType())
            {
            case LIGHT_DIRECTIONAL:
                {
                    Matrix4 shadowMatrices[MAX_CASCADE_SPLITS];
                    unsigned numSplits = lightQueue_->shadowSplits_.Size();
                    for (unsigned i = 0; i < numSplits; ++i)
                    {
                        CalculateShadowMatrix(shadowMatrices[i], lightQueue_, i, renderer, isLightVolume ? cameraEffectivePos :
                            Vector3::ZERO);
                    }
                    graphics->SetShaderParameter(PSP_LIGHTMATRICES, shadowMatrices[0].Data(), 16 * numSplits);
                }
                break;
                
            case LIGHT_SPOT:
                {
                    Matrix4 shadowMatrices[2];
                    
                    CalculateSpotMatrix(shadowMatrices[0], light, cameraEffectivePos);
                    bool isShadowed = lightQueue_->shadowMap_ != 0;
                    if (isShadowed)
                    {
                        CalculateShadowMatrix(shadowMatrices[1], lightQueue_, 0, renderer, isLightVolume ? cameraEffectivePos :
                            Vector3::ZERO);
                    }
                    
                    graphics->SetShaderParameter(PSP_LIGHTMATRICES, shadowMatrices[0].Data(), isShadowed ? 32 : 16);
                }
                break;
                
            case LIGHT_POINT:
                {
                    Matrix4 lightVecRot(lightNode->GetWorldRotation().RotationMatrix());
                    // HLSL compiler will pack the parameters as if the matrix is only 3x4, so must be careful to not overwrite
                    // the next parameter
                    #ifdef URHO3D_OPENGL
                    graphics->SetShaderParameter(PSP_LIGHTMATRICES, lightVecRot.Data(), 16);
                    #else
                    graphics->SetShaderParameter(PSP_LIGHTMATRICES, lightVecRot.Data(), 12);
                    #endif
                }
                break;
            }
        }
        
        // Set shadow mapping shader parameters
        if (shadowMap)
        {
            {
                // Calculate point light shadow sampling offsets (unrolled cube map)
                unsigned faceWidth = shadowMap->GetWidth() / 2;
                unsigned faceHeight = shadowMap->GetHeight() / 3;
                float width = (float)shadowMap->GetWidth();
                float height = (float)shadowMap->GetHeight();
                #ifdef URHO3D_OPENGL
                    float mulX = (float)(faceWidth - 3) / width;
                    float mulY = (float)(faceHeight - 3) / height;
                    float addX = 1.5f / width;
                    float addY = 1.5f / height;
                #else
                    float mulX = (float)(faceWidth - 4) / width;
                    float mulY = (float)(faceHeight - 4) / height;
                    float addX = 2.5f / width;
                    float addY = 2.5f / height;
                #endif
                // If using 4 shadow samples, offset the position diagonally by half pixel
                if (renderer->GetShadowQuality() & SHADOWQUALITY_HIGH_16BIT)
                {
                    addX -= 0.5f / width;
                    addY -= 0.5f / height;
                }
                graphics->SetShaderParameter(PSP_SHADOWCUBEADJUST, Vector4(mulX, mulY, addX, addY));
            }
            
            {
                // Calculate shadow camera depth parameters for point light shadows and shadow fade parameters for
                //  directional light shadows, stored in the same uniform
                Camera* shadowCamera = lightQueue_->shadowSplits_[0].shadowCamera_;
                float nearClip = shadowCamera->GetNearClip();
                float farClip = shadowCamera->GetFarClip();
                float q = farClip / (farClip - nearClip);
                float r = -q * nearClip;
                
                const CascadeParameters& parameters = light->GetShadowCascade();
                float viewFarClip = camera_->GetFarClip();
                float shadowRange = parameters.GetShadowRange();
                float fadeStart = parameters.fadeStart_ * shadowRange / viewFarClip;
                float fadeEnd = shadowRange / viewFarClip;
                float fadeRange = fadeEnd - fadeStart;
                
                graphics->SetShaderParameter(PSP_SHADOWDEPTHFADE, Vector4(q, r, fadeStart, 1.0f / fadeRange));
            }
            
            {
                float intensity = light->GetShadowIntensity();
                float fadeStart = light->GetShadowFadeDistance();
                float fadeEnd = light->GetShadowDistance();
                if (fadeStart > 0.0f && fadeEnd > 0.0f && fadeEnd > fadeStart)
                    intensity = Lerp(intensity, 1.0f, Clamp((light->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 0.0f, 1.0f));
                float pcfValues = (1.0f - intensity);
                float samples = renderer->GetShadowQuality() >= SHADOWQUALITY_HIGH_16BIT ? 4.0f : 1.0f;

                graphics->SetShaderParameter(PSP_SHADOWINTENSITY, Vector4(pcfValues / samples, intensity, 0.0f, 0.0f));
            }
            
            float sizeX = 1.0f / (float)shadowMap->GetWidth();
            float sizeY = 1.0f / (float)shadowMap->GetHeight();
            graphics->SetShaderParameter(PSP_SHADOWMAPINVSIZE, Vector4(sizeX, sizeY, 0.0f, 0.0f));
            
            Vector4 lightSplits(M_LARGE_VALUE, M_LARGE_VALUE, M_LARGE_VALUE, M_LARGE_VALUE);
            if (lightQueue_->shadowSplits_.Size() > 1)
                lightSplits.x_ = lightQueue_->shadowSplits_[0].farSplit_ / camera_->GetFarClip();
            if (lightQueue_->shadowSplits_.Size() > 2)
                lightSplits.y_ = lightQueue_->shadowSplits_[1].farSplit_ / camera_->GetFarClip();
            if (lightQueue_->shadowSplits_.Size() > 3)
                lightSplits.z_ = lightQueue_->shadowSplits_[2].farSplit_ / camera_->GetFarClip();
            
            graphics->SetShaderParameter(PSP_SHADOWSPLITS, lightSplits);
        }
    }
    
    // Set material-specific shader parameters and textures
    if (material_)
    {
        if (graphics->NeedParameterUpdate(SP_MATERIAL, material_))
        {
            // Update shader parameter animations
            material_->UpdateShaderParameterAnimations();

            const HashMap<StringHash, MaterialShaderParameter>& parameters = material_->GetShaderParameters();
            for (HashMap<StringHash, MaterialShaderParameter>::ConstIterator i = parameters.Begin(); i != parameters.End(); ++i)
                graphics->SetShaderParameter(i->first_, i->second_.value_);
        }
        
        const SharedPtr<Texture>* textures = material_->GetTextures();
        for (unsigned i = 0; i < MAX_MATERIAL_TEXTURE_UNITS; ++i)
        {
            TextureUnit unit = (TextureUnit)i;
            if (textures[i] && graphics->HasTextureUnit(unit))
                graphics->SetTexture(i, textures[i]);
        }
    }
    
    // Set light-related textures
    if (light)
    {
        if (shadowMap && graphics->HasTextureUnit(TU_SHADOWMAP))
            graphics->SetTexture(TU_SHADOWMAP, shadowMap);
        if (graphics->HasTextureUnit(TU_LIGHTRAMP))
        {
            Texture* rampTexture = light->GetRampTexture();
            if (!rampTexture)
                rampTexture = renderer->GetDefaultLightRamp();
            graphics->SetTexture(TU_LIGHTRAMP, rampTexture);
        }
        if (graphics->HasTextureUnit(TU_LIGHTSHAPE))
        {
            Texture* shapeTexture = light->GetShapeTexture();
            if (!shapeTexture && light->GetLightType() == LIGHT_SPOT)
                shapeTexture = renderer->GetDefaultLightSpot();
            graphics->SetTexture(TU_LIGHTSHAPE, shapeTexture);
        }
    }
    
    // Set zone texture if necessary
    if (zone_ && graphics->HasTextureUnit(TU_ZONE))
        graphics->SetTexture(TU_ZONE, zone_->GetZoneTexture());
}
Exemple #6
0
int _define_ship(lua_State *L, ShipType::Tag tag, std::vector<ShipType::Id> *list)
{
	if (s_currentShipFile.empty())
		return luaL_error(L, "ship file contains multiple ship definitions");

	ShipType s;
	s.tag = tag;
	s.id = s_currentShipFile;

	LUA_DEBUG_START(L);
	LuaTable t(L, -1);

	s.name = t.Get("name", "");
	s.modelName = t.Get("model", "");
	s.linThrust[ShipType::THRUSTER_REVERSE] = t.Get("reverse_thrust", 0.0f);
	s.linThrust[ShipType::THRUSTER_FORWARD] = t.Get("forward_thrust", 0.0f);
	s.linThrust[ShipType::THRUSTER_UP] = t.Get("up_thrust", 0.0f);
	s.linThrust[ShipType::THRUSTER_DOWN] = t.Get("down_thrust", 0.0f);
	s.linThrust[ShipType::THRUSTER_LEFT] = t.Get("left_thrust", 0.0f);
	s.linThrust[ShipType::THRUSTER_RIGHT] = t.Get("right_thrust", 0.0f);
	s.angThrust = t.Get("angular_thrust", 0.0f);
	// invert values where necessary
	s.linThrust[ShipType::THRUSTER_FORWARD] *= -1.f;
	s.linThrust[ShipType::THRUSTER_LEFT] *= -1.f;
	s.linThrust[ShipType::THRUSTER_DOWN] *= -1.f;
	// angthrust fudge (XXX: why?)
	s.angThrust = s.angThrust / 2;

	lua_pushstring(L, "camera_offset");
	lua_gettable(L, -2);
	if (!lua_isnil(L, -1))
		fprintf(stderr, "ship definition for '%s' has deprecated 'camera_offset' field\n", s.id.c_str());
	lua_pop(L, 1);
	s.cameraOffset = t.Get("camera_offset", vector3d(0.0));

	for (int i=0; i<Equip::SLOT_MAX; i++) s.equipSlotCapacity[i] = 0;
	s.equipSlotCapacity[Equip::SLOT_CARGO] = t.Get("max_cargo", 0);
	s.equipSlotCapacity[Equip::SLOT_ENGINE] = t.Get("max_engine", 1);
	s.equipSlotCapacity[Equip::SLOT_LASER] = t.Get("max_laser", 1);
	s.equipSlotCapacity[Equip::SLOT_MISSILE] = t.Get("max_missile", 0);
	s.equipSlotCapacity[Equip::SLOT_ECM] = t.Get("max_ecm", 1);
	s.equipSlotCapacity[Equip::SLOT_SCANNER] = t.Get("max_scanner", 1);
	s.equipSlotCapacity[Equip::SLOT_RADARMAPPER] = t.Get("max_radarmapper", 1);
	s.equipSlotCapacity[Equip::SLOT_HYPERCLOUD] = t.Get("max_hypercloud", 1);
	s.equipSlotCapacity[Equip::SLOT_HULLAUTOREPAIR] = t.Get("max_hullautorepair", 1);
	s.equipSlotCapacity[Equip::SLOT_ENERGYBOOSTER] = t.Get("max_energybooster", 1);
	s.equipSlotCapacity[Equip::SLOT_ATMOSHIELD] = t.Get("max_atmoshield", 1);
	s.equipSlotCapacity[Equip::SLOT_CABIN] = t.Get("max_cabin", 50);
	s.equipSlotCapacity[Equip::SLOT_SHIELD] = t.Get("max_shield", 9999);
	s.equipSlotCapacity[Equip::SLOT_FUELSCOOP] = t.Get("max_fuelscoop", 1);
	s.equipSlotCapacity[Equip::SLOT_CARGOSCOOP] = t.Get("max_cargoscoop", 1);
	s.equipSlotCapacity[Equip::SLOT_LASERCOOLER] = t.Get("max_lasercooler", 1);
	s.equipSlotCapacity[Equip::SLOT_CARGOLIFESUPPORT] = t.Get("max_cargolifesupport", 1);
	s.equipSlotCapacity[Equip::SLOT_AUTOPILOT] = t.Get("max_autopilot", 1);

	s.capacity = t.Get("capacity", 0);
	s.hullMass = t.Get("hull_mass", 100);
	s.fuelTankMass = t.Get("fuel_tank_mass", 5);

	// fuel_use_rate can be given in two ways
	float thruster_fuel_use = 0;
	s.effectiveExhaustVelocity = t.Get("effective_exhaust_velocity", -1.0f);
	thruster_fuel_use = t.Get("thruster_fuel_use", -1.0f);
	if(s.effectiveExhaustVelocity < 0 && thruster_fuel_use < 0) {
		// default value of v_c is used
		s.effectiveExhaustVelocity = 55000000;
	} else if(s.effectiveExhaustVelocity < 0 && thruster_fuel_use >= 0) {
		// v_c undefined and thruster fuel use defined -- use it!
		s.effectiveExhaustVelocity = GetEffectiveExhaustVelocity(s.fuelTankMass, thruster_fuel_use, s.linThrust[ShipType::THRUSTER_FORWARD]);
	} else {
		if(thruster_fuel_use >= 0)
			printf("Warning: Both thruster_fuel_use and effective_exhaust_velocity defined for %s, using effective_exhaust_velocity.\n", s.modelName.c_str());
	}

	s.baseprice = t.Get("price", 0);
	s.baseprice *= 100; // in hundredths of credits

	s.minCrew = t.Get("min_crew", 1);
	s.maxCrew = t.Get("max_crew", 1);

	s.equipSlotCapacity[Equip::SLOT_ENGINE] = Clamp(s.equipSlotCapacity[Equip::SLOT_ENGINE], 0, 1);

	{
		int hyperclass;
		hyperclass = t.Get("hyperdrive_class", 1);
		if (!hyperclass) {
			s.hyperdrive = Equip::NONE;
		} else {
			s.hyperdrive = Equip::Type(Equip::DRIVE_CLASS1+hyperclass-1);
		}
	}

	for (int i = 0; i < ShipType::GUNMOUNT_MAX; i++) {
		s.gunMount[i].pos = vector3f(0,0,0);
		s.gunMount[i].dir = vector3f(0,0,1);
		s.gunMount[i].sep = 5;
		s.gunMount[i].orient = ShipType::DUAL_LASERS_HORIZONTAL;
	}

	lua_pushstring(L, "gun_mounts");
	lua_gettable(L, -2);
	if (lua_istable(L, -1)) {
		fprintf(stderr, "ship definition for '%s' has deprecated 'gun_mounts' field\n", s.id.c_str());
		for (unsigned int i=0; i<lua_rawlen(L,-1); i++) {
			lua_pushinteger(L, i+1);
			lua_gettable(L, -2);
			if (lua_istable(L, -1) && lua_rawlen(L,-1) == 4)	{
				lua_pushinteger(L, 1);
				lua_gettable(L, -2);
				s.gunMount[i].pos = LuaVector::CheckFromLuaF(L, -1);
				lua_pop(L, 1);
				lua_pushinteger(L, 2);
				lua_gettable(L, -2);
				s.gunMount[i].dir = LuaVector::CheckFromLuaF(L, -1);
				lua_pop(L, 1);
				lua_pushinteger(L, 3);
				lua_gettable(L, -2);
				s.gunMount[i].sep = lua_tonumber(L,-1);
				lua_pop(L, 1);
				lua_pushinteger(L, 4);
				lua_gettable(L, -2);
				s.gunMount[i].orient = static_cast<ShipType::DualLaserOrientation>(
						LuaConstants::GetConstantFromArg(L, "DualLaserOrientation", -1));
				lua_pop(L, 1);
			}
			lua_pop(L, 1);
		}
	}
	lua_pop(L, 1);
	LUA_DEBUG_END(L, 0);

	//sanity check
	if (s.name.empty())
		return luaL_error(L, "Ship has no name");

	if (s.modelName.empty())
		return luaL_error(L, "Missing model name in ship");

	if (s.minCrew < 1 || s.maxCrew < 1 || s.minCrew > s.maxCrew)
		return luaL_error(L, "Invalid values for min_crew and max_crew");

	const std::string& id = s_currentShipFile;
	typedef std::map<ShipType::Id, ShipType>::iterator iter;
	std::pair<iter, bool> result = ShipType::types.insert(std::make_pair(id, s));
	if (result.second)
		list->push_back(s_currentShipFile);
	else
		return luaL_error(L, "Ship '%s' was already defined by a different file", id.c_str());
	s_currentShipFile.clear();

	return 0;
}
Exemple #7
0
/**
 * @return whether setting the video mode was successful
 *
 * Sets SDL video mode options/settings
 */
bool SpringApp::SetSDLVideoMode()
{
	int sdlflags = SDL_OPENGL | SDL_RESIZABLE;

	//! w/o SDL_NOFRAME, kde's windowmanager still creates a border (in fullscreen!) and forces a `window`-resize causing a lot of trouble (in the ::SaveWindowPosition)
	sdlflags |= globalRendering->fullScreen ? SDL_FULLSCREEN | SDL_NOFRAME : 0;

	const bool winBorderless = configHandler->GetBool("WindowBorderless");
	sdlflags |= winBorderless ? SDL_NOFRAME : 0;

	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); //! enable alpha channel ???

	globalRendering->depthBufferBits = configHandler->GetInt("DepthBufferBits");
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, globalRendering->depthBufferBits);
	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, configHandler->GetInt("StencilBufferBits"));
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

	//! FullScreen AntiAliasing
	globalRendering->FSAA = Clamp(configHandler->GetInt("FSAALevel"), 0, 8);
	if (globalRendering->FSAA > 0) {
		make_even_number(globalRendering->FSAA);
		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, globalRendering->FSAA);
	}

	//! use desktop resolution?
	if ((globalRendering->viewSizeX<=0) || (globalRendering->viewSizeY<=0)) {
		const SDL_VideoInfo* screenInfo = SDL_GetVideoInfo(); //! it's a read-only struct (we don't need to free it!)
		globalRendering->viewSizeX = screenInfo->current_w;
		globalRendering->viewSizeY = screenInfo->current_h;
	}
	//! fallback if resolution couldn't be detected
	if ((globalRendering->viewSizeX<=0) || (globalRendering->viewSizeY<=0)) {
		globalRendering->viewSizeX = 1024;
		globalRendering->viewSizeY = 768;
	}

	//! screen will be freed by SDL_Quit()
	//! from: http://sdl.beuc.net/sdl.wiki/SDL_SetVideoMode
	//! Note 3: This function should be called in the main thread of your application.
	//! User note 1: Some have found that enabling OpenGL attributes like SDL_GL_STENCIL_SIZE (the stencil buffer size) before the video mode has been set causes the application to simply ignore those attributes, while enabling attributes after the video mode has been set works fine.
	//! User note 2: Also note that, in Windows, setting the video mode resets the current OpenGL context. You must execute again the OpenGL initialization code (set the clear color or the shade model, or reload textures, for example) after calling SDL_SetVideoMode. In Linux, however, it works fine, and the initialization code only needs to be executed after the first call to SDL_SetVideoMode (although there is no harm in executing the initialization code after each call to SDL_SetVideoMode, for example for a multiplatform application).
	SDL_Surface* screen = SDL_SetVideoMode(globalRendering->viewSizeX, globalRendering->viewSizeY, 32, sdlflags);
	if (!screen) {
		char buf[1024];
		SNPRINTF(buf, sizeof(buf), "Could not set video mode:\n%s", SDL_GetError());
		handleerror(NULL, buf, "ERROR", MBF_OK|MBF_EXCL);
		return false;
	}

#ifdef STREFLOP_H
	//! Something in SDL_SetVideoMode (OpenGL drivers?) messes with the FPU control word.
	//! Set single precision floating point math.
	streflop_init<streflop::Simple>();
#endif

	//! setup GL smoothing
	const int lineSmoothing = configHandler->GetInt("SmoothLines");
	if (lineSmoothing > 0) {
		GLenum hint = GL_FASTEST;
		if (lineSmoothing >= 3) {
			hint = GL_NICEST;
		} else if (lineSmoothing >= 2) {
			hint = GL_DONT_CARE;
		}
		glEnable(GL_LINE_SMOOTH);
		glHint(GL_LINE_SMOOTH_HINT, hint);
	}
	const int pointSmoothing = configHandler->GetInt("SmoothPoints");
	if (pointSmoothing > 0) {
		GLenum hint = GL_FASTEST;
		if (pointSmoothing >= 3) {
			hint = GL_NICEST;
		} else if (pointSmoothing >= 2) {
			hint = GL_DONT_CARE;
		}
		glEnable(GL_POINT_SMOOTH);
		glHint(GL_POINT_SMOOTH_HINT, hint);
	}

	//! setup LOD bias factor
	const float lodBias = Clamp(configHandler->GetFloat("TextureLODBias"), -4.f, 4.f);
	if (fabs(lodBias)>0.01f) {
		glTexEnvf(GL_TEXTURE_FILTER_CONTROL,GL_TEXTURE_LOD_BIAS, lodBias );
	}

	//! there must be a way to see if this is necessary, compare old/new context pointers?
	if (configHandler->GetBool("FixAltTab")) {
		//! free GL resources
		GLContext::Free();

		//! initialize any GL resources that were lost
		GLContext::Init();
	}

	VSync.Init();

	int bits;
	SDL_GL_GetAttribute(SDL_GL_BUFFER_SIZE, &bits);
	SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE,  &globalRendering->depthBufferBits);
	if (globalRendering->fullScreen) {
		LOG("Video mode set to %ix%i/%ibit", globalRendering->viewSizeX, globalRendering->viewSizeY, bits);
	} else {
		LOG("Video mode set to %ix%i/%ibit (windowed)", globalRendering->viewSizeX, globalRendering->viewSizeY, bits);
	}

	return true;
}
Exemple #8
0
void Light::SetFov(float fov)
{
    fov_ = Clamp(fov, 0.0f, M_MAX_FOV);
    OnMarkedDirty(node_);
    MarkNetworkUpdate();
}
Exemple #9
0
void Light::SetShadowNearFarRatio(float nearFarRatio)
{
    shadowNearFarRatio_ = Clamp(nearFarRatio, 0.0f, 0.5f);
    MarkNetworkUpdate();
}
Exemple #10
0
void cCuboid::ClampY(int a_MinY, int a_MaxY)
{
	p1.y = Clamp(p1.y, a_MinY, a_MaxY);
	p2.y = Clamp(p2.y, a_MinY, a_MaxY);
}
Exemple #11
0
void cCuboid::ClampZ(int a_MinZ, int a_MaxZ)
{
	p1.z = Clamp(p1.z, a_MinZ, a_MaxZ);
	p2.z = Clamp(p2.z, a_MinZ, a_MaxZ);
}
Exemple #12
0
void cCuboid::ClampX(int a_MinX, int a_MaxX)
{
	p1.x = Clamp(p1.x, a_MinX, a_MaxX);
	p2.x = Clamp(p2.x, a_MinX, a_MaxX);
}
void SpaceStation::DockingUpdate(const double timeStep)
{
	vector3d p1, p2, zaxis;
	for (Uint32 i=0; i<m_shipDocking.size(); i++) {
		shipDocking_t &dt = m_shipDocking[i];
		if (!dt.ship) continue;
		// docked stage is m_type->NumDockingPorts() + 1 => ship docked
		if (dt.stage > m_type->NumDockingStages()) continue;

		double stageDuration = (dt.stage > 0 ?
				m_type->GetDockAnimStageDuration(dt.stage-1) :
				m_type->GetUndockAnimStageDuration(abs(dt.stage)-1));
		dt.stagePos += timeStep / stageDuration;

		if (dt.stage == 1) {
			// SPECIAL stage! Docking granted but waiting for ship to dock

			m_doorAnimationStep = 0.3; // open door

			if (dt.stagePos >= 1.0) {
				if (dt.ship == Pi::player)
					Pi::game->log->Add(GetLabel(), Lang::DOCKING_CLEARANCE_EXPIRED);
				dt.ship = 0;
				dt.stage = 0;
				m_doorAnimationStep = -0.3; // close door
			}
			continue;
		}

		if (dt.stagePos > 1.0) {
			// use end position of last segment for start position of new segment
			SpaceStationType::positionOrient_t dport;
			PiVerify(m_type->GetDockAnimPositionOrient(i, dt.stage, 1.0f, dt.fromPos, dport, dt.ship));
			matrix3x3d fromRot = matrix3x3d::FromVectors(dport.xaxis, dport.yaxis, dport.zaxis);
			dt.fromRot = Quaterniond::FromMatrix3x3(fromRot);
			dt.fromPos = dport.pos;

			// transition between docking stages
			dt.stagePos = 0;
			if (dt.stage >= 0) dt.stage++;
			else dt.stage--;
		}

		if (dt.stage < -m_type->ShipLaunchStage() && dt.ship->GetFlightState() != Ship::FLYING) {
			// launch ship
			dt.ship->SetFlightState(Ship::FLYING);
			dt.ship->SetAngVelocity(GetAngVelocity());
			if (m_type->IsSurfaceStation()) {
				dt.ship->SetThrusterState(1, 1.0);	// up
			} else {
				dt.ship->SetThrusterState(2, -1.0);	// forward
			}
			LuaEvent::Queue("onShipUndocked", dt.ship, this);
		}
		if (dt.stage < -m_type->NumUndockStages()) {
			// undock animation finished, clear port
			dt.stage = 0;
			dt.ship = 0;
			LockPort(i, false);
			m_doorAnimationStep = -0.3; // close door
		}
		else if (dt.stage > m_type->NumDockingStages()) {
			// set docked
			dt.ship->SetDockedWith(this, i);
			LuaEvent::Queue("onShipDocked", dt.ship, this);
			LockPort(i, false);
			m_doorAnimationStep = -0.3; // close door
		}
	}

	m_doorAnimationState = Clamp(m_doorAnimationState + m_doorAnimationStep*timeStep, 0.0, 1.0);
	if (m_doorAnimation)
		m_doorAnimation->SetProgress(m_doorAnimationState);
}
Exemple #14
0
void AmbientSounds::Update()
{
	float v_env = (Pi::worldView->GetActiveCamera()->IsExternal() ? 1.0f : 0.5f) * Sound::GetSfxVolume();

	if (Pi::player->GetFlightState() == Ship::DOCKED) {
		if (starNoise.IsPlaying()) {
			float target[2] = {0.0f,0.0f};
			float dv_dt[2] = {1.0f,1.0f};
			starNoise.VolumeAnimate(target, dv_dt);
			starNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
		}
		if (atmosphereNoise.IsPlaying()) {
			float target[2] = {0.0f,0.0f};
			float dv_dt[2] = {1.0f,1.0f};
			atmosphereNoise.VolumeAnimate(target, dv_dt);
			atmosphereNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
		}
		if (planetSurfaceNoise.IsPlaying()) {
			float target[2] = {0.0f,0.0f};
			float dv_dt[2] = {1.0f,1.0f};
			planetSurfaceNoise.VolumeAnimate(target, dv_dt);
			planetSurfaceNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
		}

		if (!stationNoise.IsPlaying()) {
			const char *sounds[] = {
				"Large_Station_ambient",
				"Medium_Station_ambient",
				"Small_Station_ambient"
			};
			// just use a random station noise until we have a
			// concept of 'station size'
			stationNoise.Play(sounds[Pi::player->GetDockedWith()->GetSystemBody()->seed % 3],
					0.3f*v_env, 0.3f*v_env, Sound::OP_REPEAT);
		}
	} else if (Pi::player->GetFlightState() == Ship::LANDED) {
		/* Planet surface noise on rough-landing */
		if (starNoise.IsPlaying()) {
			float target[2] = {0.0f,0.0f};
			float dv_dt[2] = {1.0f,1.0f};
			starNoise.VolumeAnimate(target, dv_dt);
			starNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
		}
		if (atmosphereNoise.IsPlaying()) {
			float target[2] = {0.0f,0.0f};
			float dv_dt[2] = {1.0f,1.0f};
			atmosphereNoise.VolumeAnimate(target, dv_dt);
			atmosphereNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
		}
		if (stationNoise.IsPlaying()) {
			float target[2] = {0.0f,0.0f};
			float dv_dt[2] = {1.0f,1.0f};
			stationNoise.VolumeAnimate(target, dv_dt);
			stationNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
		}

		// lets try something random for the time being
		if (!planetSurfaceNoise.IsPlaying()) {
			SystemBody *sbody = Pi::player->GetFrame()->GetSystemBody();
			assert(sbody);
			const char *sample = NULL;

			if (sbody->m_life > fixed(1,5)) {
				const char *s[] = {
					"Wind", "Thunder_1", "Thunder_2", "Thunder_3",
					"Thunder_4", "Storm", "Rain_Light", "River",
					"RainForestIntroducedNight", "RainForestIntroduced",
					"NormalForestIntroduced"
				};
				sample = s[sbody->seed % 11];
			}
			else if (sbody->m_volatileGas > fixed(1,2)) {
				const char *s[] = {
					"Wind", "Thunder_1", "Thunder_2", "Thunder_3",
					"Thunder_4", "Storm"
				};
				sample = s[sbody->seed % 6];
			}
			else if (sbody->m_volatileGas > fixed(1,10)) {
				sample = "Wind";
			}

			if (sample) {
				planetSurfaceNoise.Play(sample, 0.3f*v_env, 0.3f*v_env, Sound::OP_REPEAT);
			}
		}
    } else if (planetSurfaceNoise.IsPlaying()) {
        // planetSurfaceNoise.IsPlaying() - if we are out of the atmosphere then stop playing
        if (Pi::player->GetFrame()->IsRotFrame()) {
            Body *astro = Pi::player->GetFrame()->GetBody();
            if (astro->IsType(Object::PLANET)) {
                double dist = Pi::player->GetPosition().Length();
                double pressure, density;
                static_cast<Planet*>(astro)->GetAtmosphericState(dist, &pressure, &density);
                if (pressure < 0.001) {
                    // Stop playing surface noise once out of the atmosphere
                    planetSurfaceNoise.Stop();
                }
            }
        }
    } else {
		if (stationNoise.IsPlaying()) {
			float target[2] = {0.0f,0.0f};
			float dv_dt[2] = {1.0f,1.0f};
			stationNoise.VolumeAnimate(target, dv_dt);
			stationNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
		}
		{
			if (Pi::game->IsNormalSpace()) {
				StarSystem *s = Pi::game->GetSpace()->GetStarSystem().Get();
				if (astroNoiseSeed != s->GetSeed()) {
					// change sound!
					astroNoiseSeed = s->GetSeed();
					float target[2] = {0.0f,0.0f};
					float dv_dt[2] = {0.1f,0.1f};
					starNoise.VolumeAnimate(target, dv_dt);
					starNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
					// XXX the way Sound::Event works isn't totally obvious.
					// to destroy the object doesn't stop the sound. it is
					// really just a sound event reference
					starNoise = Sound::Event();
				}
			}
		}
		// when all the sounds are in we can use the body we are in frame of reference to
		if (!starNoise.IsPlaying()) {
			Frame *f = Pi::player->GetFrame();
			if (!f) return; // When player has no frame (game abort) then get outta here!!
			const SystemBody *sbody = f->GetSystemBody();
			const char *sample = 0;
			for (; sbody && !sample; sbody = f->GetSystemBody()) {
				switch (sbody->type) {
					case SystemBody::TYPE_BROWN_DWARF: sample = "Brown_Dwarf_Substellar_Object"; break;
					case SystemBody::TYPE_STAR_M: sample = "M_Red_Star"; break;
					case SystemBody::TYPE_STAR_K: sample = "K_Star"; break;
					case SystemBody::TYPE_WHITE_DWARF: sample = "White_Dwarf_Star"; break;
					case SystemBody::TYPE_STAR_G: sample = "G_Star"; break;
					case SystemBody::TYPE_STAR_F: sample = "F_Star"; break;
					case SystemBody::TYPE_STAR_A: sample = "A_Star"; break;
					case SystemBody::TYPE_STAR_B: sample = "B_Hot_Blue_STAR"; break;
					case SystemBody::TYPE_STAR_O: sample = "Blue_Super_Giant"; break;
					case SystemBody::TYPE_PLANET_GAS_GIANT: {
							if (sbody->mass > fixed(400,1)) {
								sample = "Very_Large_Gas_Giant";
							} else if (sbody->mass > fixed(80,1)) {
								sample = "Large_Gas_Giant";
							} else if (sbody->mass > fixed(20,1)) {
								sample = "Medium_Gas_Giant";
							} else {
								sample = "Small_Gas_Giant";
							}
						}
						break;
					default: sample = 0; break;
				}
				if (sample) {
					starNoise.Play(sample, 0.0f, 0.0f, Sound::OP_REPEAT);
					starNoise.VolumeAnimate(.3f*v_env, .3f*v_env, .05f, .05f);
				} else {
					// go up orbital hierarchy tree to see if we can find a sound
					f = f->GetParent();
					if (f == 0) break;
				}
			}
		}

		Body *astro;
		if ((astro = Pi::player->GetFrame()->GetBody())
			&& Pi::player->GetFrame()->IsRotFrame() && (astro->IsType(Object::PLANET))) {
			double dist = Pi::player->GetPosition().Length();
			double pressure, density;
			static_cast<Planet*>(astro)->GetAtmosphericState(dist, &pressure, &density);
			// maximum volume at around 2km/sec at earth density, pressure
			float volume = float(density * Pi::player->GetVelocity().Length() * 0.0005);
			volume = Clamp(volume, 0.0f, 1.0f) * v_env;
			if (atmosphereNoise.IsPlaying()) {
				float target[2] = {volume, volume};
				float dv_dt[2] = {1.0f,1.0f};
				atmosphereNoise.VolumeAnimate(target, dv_dt);
			} else {
				atmosphereNoise.Play("Atmosphere_Flying", volume, volume, Sound::OP_REPEAT);
			}
		} else {
			float target[2] = {0.0f,0.0f};
			float dv_dt[2] = {1.0f,1.0f};
			atmosphereNoise.VolumeAnimate(target, dv_dt);
			atmosphereNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
		}
	}
}
Exemple #15
0
// Calculates the ambiently and directly lit portions of the lighting model taking into account the atmosphere and sun positions at a given location
// 1. Calculates the amount of direct illumination available taking into account
//    * multiple suns
//    * sun positions relative to up direction i.e. light is dimmed as suns set
//    * Thickness of the atmosphere overhead i.e. as atmospheres get thicker light starts dimming earlier as sun sets, without atmosphere the light switches off at point of sunset
// 2. Calculates the split between ambient and directly lit portions taking into account
//    * Atmosphere density (optical thickness) of the sky dome overhead
//        as optical thickness increases the fraction of ambient light increases
//        this takes altitude into account automatically
//    * As suns set the split is biased towards ambient
void ModelBody::CalcLighting(double &ambient, double &direct, const Camera *camera)
{
	const double minAmbient = 0.05;
	ambient = minAmbient;
	direct = 1.0;
	Body *astro = GetFrame()->GetBody();
	if ( ! (astro && astro->IsType(Object::PLANET)) )
		return;

	Planet *planet = static_cast<Planet*>(astro);

	// position relative to the rotating frame of the planet
	vector3d upDir = GetInterpPositionRelTo(planet->GetFrame());
	const double planetRadius = planet->GetSystemBody()->GetRadius();
	const double dist = std::max(planetRadius, upDir.Length());
	upDir = upDir.Normalized();

	double pressure, density;
	planet->GetAtmosphericState(dist, &pressure, &density);
	double surfaceDensity;
	Color cl;
	planet->GetSystemBody()->GetAtmosphereFlavor(&cl, &surfaceDensity);

	// approximate optical thickness fraction as fraction of density remaining relative to earths
	double opticalThicknessFraction = density/EARTH_ATMOSPHERE_SURFACE_DENSITY;

	// tweak optical thickness curve - lower exponent ==> higher altitude before ambient level drops
	// Commenting this out, since it leads to a sharp transition at
	// atmosphereRadius, where density is suddenly 0
	//opticalThicknessFraction = pow(std::max(0.00001,opticalThicknessFraction),0.15); //max needed to avoid 0^power

	if (opticalThicknessFraction < 0.0001)
		return;

	//step through all the lights and calculate contributions taking into account sun position
	double light = 0.0;
	double light_clamped = 0.0;

	const std::vector<Camera::LightSource> &lightSources = camera->GetLightSources();
	for(std::vector<Camera::LightSource>::const_iterator l = lightSources.begin();
			l != lightSources.end(); ++l) {
		double sunAngle;
		// calculate the extent the sun is towards zenith
		if (l->GetBody()){
			// relative to the rotating frame of the planet
			const vector3d lightDir = (l->GetBody()->GetInterpPositionRelTo(planet->GetFrame()).Normalized());
			sunAngle = lightDir.Dot(upDir);
		} else {
			// light is the default light for systems without lights
			sunAngle = 1.0;
		}

		const double critAngle = -sqrt(dist*dist-planetRadius*planetRadius)/dist;

		//0 to 1 as sunangle goes from critAngle to 1.0
		double sunAngle2 = (Clamp(sunAngle, critAngle, 1.0)-critAngle)/(1.0-critAngle);

		// angle at which light begins to fade on Earth
		const double surfaceStartAngle = 0.3;
		// angle at which sun set completes, which should be after sun has dipped below the horizon on Earth
		const double surfaceEndAngle = -0.18;

		const double start = std::min((surfaceStartAngle*opticalThicknessFraction),1.0);
		const double end = std::max((surfaceEndAngle*opticalThicknessFraction),-0.2);

		sunAngle = (Clamp(sunAngle-critAngle, end, start)-end)/(start-end);

		light += sunAngle;
		light_clamped += sunAngle2;
	}

	light_clamped /= lightSources.size();
	light /= lightSources.size();

	// brightness depends on optical depth and intensity of light from all the stars
	direct = 1.0 -  Clamp((1.0 - light),0.0,1.0) * Clamp(opticalThicknessFraction,0.0,1.0);

	// ambient light fraction
	// alter ratio between directly and ambiently lit portions towards ambiently lit as sun sets
	const double fraction = ( 0.2 + 0.8 * (1.0-light_clamped) ) * Clamp(opticalThicknessFraction,0.0,1.0);

	// fraction of light left over to be lit directly
	direct = (1.0-fraction)*direct;

	// scale ambient by amount of light
	ambient = fraction*(Clamp((light),0.0,1.0))*0.25;

	ambient = std::max(minAmbient, ambient);
}
Exemple #16
0
void Light::SetShadowIntensity(float intensity)
{
    shadowIntensity_ = Clamp(intensity, 0.0f, 1.0f);
    MarkNetworkUpdate();
}
Exemple #17
0
// GridAccel Method Definitions
GridAccel::GridAccel(const vector<Reference<Primitive> > &p,
                     bool forRefined, bool refineImmediately)
    : gridForRefined(forRefined) {
    PBRT_GRID_STARTED_CONSTRUCTION(this, p.size());
    // Create reader-writeer mutex for grid
    rwMutex = RWMutex::Create();

    // Initialize _primitives_ with primitives for grid
    if (refineImmediately)
        for (u_int i = 0; i < p.size(); ++i)
            p[i]->FullyRefine(primitives);
    else
        primitives = p;

    // Compute bounds and choose grid resolution
    for (u_int i = 0; i < primitives.size(); ++i)
        bounds = Union(bounds, primitives[i]->WorldBound());
    Vector delta = bounds.pMax - bounds.pMin;

    // Find _voxelsPerUnitDist_ for grid
    int maxAxis = bounds.MaximumExtent();
    float invMaxWidth = 1.f / delta[maxAxis];
    Assert(invMaxWidth > 0.f);
    float cubeRoot = 3.f * powf(float(primitives.size()), 1.f/3.f);
    float voxelsPerUnitDist = cubeRoot * invMaxWidth;
    for (int axis = 0; axis < 3; ++axis) {
        NVoxels[axis] = Round2Int(delta[axis] * voxelsPerUnitDist);
        NVoxels[axis] = Clamp(NVoxels[axis], 1, 64);
    }
    PBRT_GRID_BOUNDS_AND_RESOLUTION(&bounds, NVoxels);

    // Compute voxel widths and allocate voxels
    for (int axis = 0; axis < 3; ++axis) {
        Width[axis] = delta[axis] / NVoxels[axis];
        InvWidth[axis] = (Width[axis] == 0.f) ? 0.f : 1.f / Width[axis];
    }
    int nVoxels = NVoxels[0] * NVoxels[1] * NVoxels[2];
    voxels = AllocAligned<Voxel *>(nVoxels);
    memset(voxels, 0, nVoxels * sizeof(Voxel *));

    // Add primitives to grid voxels
    for (u_int i = 0; i < primitives.size(); ++i) {
        // Find voxel extent of primitive
        BBox pb = primitives[i]->WorldBound();
        int vmin[3], vmax[3];
        for (int axis = 0; axis < 3; ++axis) {
            vmin[axis] = posToVoxel(pb.pMin, axis);
            vmax[axis] = posToVoxel(pb.pMax, axis);
        }

        // Add primitive to overlapping voxels
        PBRT_GRID_VOXELIZED_PRIMITIVE(vmin, vmax);
        for (int z = vmin[2]; z <= vmax[2]; ++z)
            for (int y = vmin[1]; y <= vmax[1]; ++y)
                for (int x = vmin[0]; x <= vmax[0]; ++x) {
                    int o = offset(x, y, z);
                    if (!voxels[o]) {
                        // Allocate new voxel and store primitive in it
                        voxels[o] = voxelArena.Alloc<Voxel>();
                        *voxels[o] = Voxel(primitives[i]);
                    }
                    else {
                        // Add primitive to already-allocated voxel
                        voxels[o]->AddPrimitive(primitives[i]);
                    }
                }
    }
    PBRT_GRID_FINISHED_CONSTRUCTION(this);
}
Exemple #18
0
void Light::SetShadowResolution(float resolution)
{
    shadowResolution_ = Clamp(resolution, 0.125f, 1.0f);
    MarkNetworkUpdate();
}
void CameraApplication::MoveCamera(Entity* cameraEntity, float frameTime)
{
    if (!cameraEntity)
        return;

    Placeable* placeable = cameraEntity->Component<Placeable>();
    if (!placeable)
        return;
    
    InputAPI* input = framework->Input();

    bool changed = false;

    Transform t = placeable->transform.Get();

    float3 rotDelta = float3::zero;

    if (inputContext_->IsMouseButtonDown(Urho3D::MOUSEB_RIGHT))
    {
        rotDelta.x -= input->GetMouseMoveY() * cRotateSpeed;
        rotDelta.y -= input->GetMouseMoveX() * cRotateSpeed;
    }
    else if (inputContext_->GetNumTouches() > 0)
    {
        // Find a touch point that is not on top of the movement joystick button.
        for (int ti=0, len=input->GetNumTouches(); ti<len; ++ti)
        {
            Urho3D::TouchState *touch = input->GetTouch(ti);
            if (!touch->touchedElement_.Get())
            {
                rotDelta -= (float3(static_cast<float>(touch->delta_.y_), static_cast<float>(touch->delta_.x_), 0.f) * cRotateSpeed);
                break;
            }
        }
    }

    if (!rotDelta.Equals(float3::zero))
    {
        RotateChanged.Emit(rotDelta);

        t.rot.x += rotDelta.x;
        t.rot.y += rotDelta.y;
        t.rot.x = Clamp(t.rot.x, -90.0f, 90.0f);
        changed = true;
    }

    float3 moveVector = float3::zero;
    // Note right-handed coordinate system
    if (inputContext_->IsKeyDown(Urho3D::KEY_W))
        moveVector += float3(0.0f, 0.0f, -1.0f);
    if (inputContext_->IsKeyDown(Urho3D::KEY_S))
        moveVector += float3(0.0f, 0.0f, 1.0f);
    if (inputContext_->IsKeyDown(Urho3D::KEY_A))
        moveVector += float3(-1.0f, 0.0f, 0.0f);
    if (inputContext_->IsKeyDown(Urho3D::KEY_D))
        moveVector += float3(1.0f, 0.0f, 0.0f);
    if (inputContext_->IsKeyDown(Urho3D::KEY_SPACE))
        moveVector += float3(0.0f, 1.0f, 0.0f);
    if (inputContext_->IsKeyDown(Urho3D::KEY_C))
        moveVector += float3(0.0f, -1.0f, 0.0f);

    if (!moveVector.Equals(lastMoveVector_))
    {
        lastMoveVector_ = moveVector;
        MoveChanged.Emit(moveVector);
    }

    if (inputContext_->IsKeyPressed(Urho3D::KEY_SHIFT))
        moveVector *= 2;

    if (!moveVector.Equals(float3::zero))
    {
        movementHeld_ = Clamp(movementHeld_ + (frameTime * 4.f), 0.f, 1.0f);
        t.pos += t.Orientation() * (cMoveSpeed * frameTime * moveVector * movementHeld_);
        changed = true;
    }
    else
        movementHeld_ = 0.f;

    // If some other camera (like avatar) is active, do not actually move, only transmit the move signals
    if (changed && cameraEntity == lastCamera_)
        placeable->transform.Set(t);
}
Exemple #20
0
void CascadeParameters::Validate()
{
    for (unsigned i = 0; i < MAX_CASCADE_SPLITS; ++i)
        splits_[i] = Max(splits_[i], 0.0f);
    fadeStart_ = Clamp(fadeStart_, M_EPSILON, 1.0f);
}
Exemple #21
0
void SoundSource3D::SetAngleAttenuation(float innerAngle, float outerAngle)
{
    innerAngle_ = Clamp(innerAngle, 0.0f, DEFAULT_ANGLE);
    outerAngle_ = Clamp(outerAngle, 0.0f, DEFAULT_ANGLE);
    MarkNetworkUpdate();
}
void PhysicsWorld::SetWarmStartFraction(float fraction)
{
	mParams.warmStartFraction = Clamp(fraction, 0.0f, 1.0f);
}
Exemple #23
0
void CEFX::SetAirAbsorptionFactor(ALfloat value)
{
	airAbsorptionFactor = Clamp(value, AL_MIN_AIR_ABSORPTION_FACTOR, AL_MAX_AIR_ABSORPTION_FACTOR);
}
void PhysicsWorld::SetDamping(float linear, float angular)
{
	mParams.linearDamping = Clamp(linear, 0.0f, 1.0f);
	mParams.angularDamping = Clamp(angular, 0.0f, 1.0f);
	WakeAll();
}
bool
GlueMapWindow::OnMouseUp(PixelScalar x, PixelScalar y)
{
    if (drag_mode != DRAG_NONE)
        ReleaseCapture();

    // Ignore single click event if double click detected
    if (ignore_single_click) {
        ignore_single_click = false;
        return true;
    }

    int click_time = mouse_down_clock.Elapsed();
    mouse_down_clock.Reset();

    DragMode old_drag_mode = drag_mode;
    drag_mode = DRAG_NONE;

    switch (old_drag_mode) {
    case DRAG_NONE:
        /* skip the arm_mapitem_list check below */
        return false;

#ifdef HAVE_MULTI_TOUCH
    case DRAG_MULTI_TOUCH_PAN:
        follow_mode = FOLLOW_SELF;
        ::PanTo(visible_projection.GetGeoScreenCenter());
        return true;
#endif

    case DRAG_PAN:
#ifndef ENABLE_OPENGL
        /* allow the use of the stretched last buffer for the next two
           redraws */
        scale_buffer = 2;
#endif

#ifdef ENABLE_OPENGL
        kinetic_x.MouseUp(x);
        kinetic_y.MouseUp(y);
        kinetic_timer.Schedule(30);
#endif
        break;

    case DRAG_SIMULATOR:
        if (click_time > 50 &&
                compare_squared(drag_start.x - x, drag_start.y - y,
                                Layout::Scale(36)) == 1) {
            GeoPoint location = visible_projection.ScreenToGeo(x, y);

            double distance = hypot(drag_start.x - x, drag_start.y - y);

            // This drag moves the aircraft (changes speed and direction)
            const Angle old_bearing = CommonInterface::Basic().track;
            const auto min_speed = fixed(1.1) *
                                   CommonInterface::GetComputerSettings().polar.glide_polar_task.GetVMin();
            const Angle new_bearing = drag_start_geopoint.Bearing(location);
            if (((new_bearing - old_bearing).AsDelta().AbsoluteDegrees() < fixed(30)) ||
                    (CommonInterface::Basic().ground_speed < min_speed))
                device_blackboard->SetSpeed(Clamp(fixed(distance) / Layout::FastScale(3),
                                                  min_speed, fixed(100)));

            device_blackboard->SetTrack(new_bearing);
            // change bearing without changing speed if direction change > 30
            // 20080815 JMW prevent dragging to stop glider

            return true;
        }

        break;

    case DRAG_GESTURE:
        const TCHAR* gesture = gestures.Finish();
        if (gesture && OnMouseGesture(gesture))
            return true;

        break;
    }

    if (arm_mapitem_list) {
        map_item_timer.Schedule(200);
        return true;
    }

    return false;
}
// main
void PhysicsWorld::Step(float dt, unsigned char velocityIterations, unsigned char positionIterations)
{
	const TimeStep timeStep(dt, velocityIterations, positionIterations, mParams, mStats);
	Stopwatch timer;
	mStats.Clear();

	// update rigid bodies
	const float linearDampFactor = 1.0f - Clamp(mParams.linearDamping  * timeStep.dt, 0.0f, 1.0f);
	const float angularDampFactor = 1.0f - Clamp(mParams.angularDamping * timeStep.dt, 0.0f, 1.0f);
	timer.Start();
	for (auto &body : mRigidBodies)
	{
		// TODOKai mass
		if (!body.CollidersValid())
			body.ValidateColliders();

		// update
		body.UpdateMassAndLocalCentroid();
		body.UpdateOrientation();
		body.UpdatePositionFromGlobalCentroid();
		body.UpdateGlobalInverseInertiaTensor();
		body.UpdateProxies();

		timeStep.stats.colliders += body.mColliders.size();
	}
	timeStep.stats.rigidBodies = mRigidBodies.size();
	timeStep.stats.integration += timer.Stop();

	// broadphase
	timer.Start();
	auto &pairList = mBroadphase->ComputePairs();
	timeStep.stats.broadphasePairs = pairList.size();
	timeStep.stats.broadphase += timer.Stop();

	// narrowphase
	timer.Start();
	mContactManager.PreNarrowphase();
	for (ColliderPair &pair : pairList)
	{
		Collider *colliderA = pair.mCollider1;
		Collider *colliderB = pair.mCollider2;
		RigidBody &bodyA = *colliderA->mParent;
		RigidBody &bodyB = *colliderB->mParent;
		CPhysics* cphyA = bodyA.mParent->cphy;
		CPhysics* cphyB = bodyB.mParent->cphy;

		if (!bodyA.CanCollide(bodyB) || !colliderA->CanBeCollide(*colliderB))
			continue;

		// collision table check
		if (!cphyA->gameObject->GetState()->GetCollisionTable()->GetDoesIDsCollide(cphyA->GetCOllisionID(), cphyB->GetCOllisionID()))
			continue;

		// make sure colliderA is always less than colliderB in memory address for consistency
		if (colliderA > colliderB)
		{
			std::swap(colliderA, colliderB);
			auto temp = cphyA;
			cphyA = cphyB;
			cphyB = temp;
		}


		ContactManifold *manifold = new (mManifoldAllocator.Allocate()) ContactManifold();
		manifold->colliderA = colliderA;
		manifold->colliderB = colliderB;

		//TODO
		manifold->isColliding =
			Collide(*manifold, *colliderA->mGeometry, *colliderB->mGeometry, mContactAllocator);

		if (!manifold->isColliding
			|| !mContactManager.Add(*manifold, mParams.contactPersistenceThreshold * mParams.contactPersistenceThreshold))
		{
			// manifold not colliding OR persistent manifold already exists, delete
			manifold->~ContactManifold();
			mManifoldAllocator.Free(manifold);
		}
		else
		{
			//these will be deleted by the script subsystem
			CollisionData* dataA = new CollisionData();
			CollisionData* dataB = new CollisionData();

			// send manifold to OnCollide function
			{
				dataA->isA = true;
				dataA->collidedObj = cphyB->gameObject;
				dataA->selfCPhy = cphyA;
				dataA->collidedObjCPhy = cphyB;
				dataA->numContacts = manifold->numContacts;
				for (int i = 0; i < dataA->numContacts; ++i)
				{
					dataA->normals.push_back(manifold->contacts[i]->normal);
				}
				ScriptSubsystem::getInstance()->QueueEvent<CollisionData>(cphyA->gameObject, "OnCollisionEnter", dataA);
			}
			{
				dataB->isA = false;
				dataB->collidedObj = cphyA->gameObject;
				dataB->selfCPhy = cphyB;
				dataB->collidedObjCPhy = cphyA;
				dataB->numContacts = manifold->numContacts;
				for (int i = 0; i < dataB->numContacts; ++i)
				{
					dataB->normals.push_back(manifold->contacts[i]->normal);
				}
				ScriptSubsystem::getInstance()->QueueEvent<CollisionData>(cphyB->gameObject, "OnCollisionEnter", dataB);
			}
			if (cphyA->mIsTriggered || cphyB->mIsTriggered)
			{
				manifold->~ContactManifold();
				mManifoldAllocator.Free(manifold);
			}
		}
	}
	mContactManager.PostNarrowphase();
	timeStep.stats.narrowphase += timer.Stop();

	SimulateIslands(timeStep);

	// update broadphase after position integration
	mBroadphase->Update(timeStep);

	mContactManager.Draw();

}
void EnvironmentOptions::ParseEnvironmentOptions()
{
    // get logging options
    mFpsFrequency = GetIntegerEnvironmentVariable( DALI_ENV_FPS_TRACKING, 0 );
    mUpdateStatusFrequency = GetIntegerEnvironmentVariable( DALI_ENV_UPDATE_STATUS_INTERVAL, 0 );
    mObjectProfilerInterval = GetIntegerEnvironmentVariable( DALI_ENV_OBJECT_PROFILER_INTERVAL, 0 );
    mPerformanceStatsLevel = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PERFORMANCE_STATS, 0 );
    mPerformanceStatsFrequency = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PERFORMANCE_STATS_FREQUENCY, 0 );
    mPerformanceTimeStampOutput = GetIntegerEnvironmentVariable( DALI_ENV_PERFORMANCE_TIMESTAMP_OUTPUT, 0 );
    mNetworkControl = GetIntegerEnvironmentVariable( DALI_ENV_NETWORK_CONTROL, 0 );
    mPanGestureLoggingLevel = GetIntegerEnvironmentVariable( DALI_ENV_LOG_PAN_GESTURE, 0 );

    int predictionMode;
    if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_PREDICTION_MODE, predictionMode) )
    {
        mPanGesturePredictionMode = predictionMode;
    }
    int predictionAmount(-1);
    if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_PREDICTION_AMOUNT, predictionAmount) )
    {
        if( predictionAmount < 0 )
        {
            // do not support times in the past
            predictionAmount = 0;
        }
        mPanGesturePredictionAmount = predictionAmount;
    }
    int minPredictionAmount(-1);
    if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_MIN_PREDICTION_AMOUNT, minPredictionAmount) )
    {
        if( minPredictionAmount < 0 )
        {
            // do not support times in the past
            minPredictionAmount = 0;
        }
        mPanGestureMinPredictionAmount = minPredictionAmount;
    }
    int maxPredictionAmount(-1);
    if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_MAX_PREDICTION_AMOUNT, maxPredictionAmount) )
    {
        if( minPredictionAmount > -1 && maxPredictionAmount < minPredictionAmount )
        {
            // maximum amount should not be smaller than minimum amount
            maxPredictionAmount = minPredictionAmount;
        }
        mPanGestureMaxPredictionAmount = maxPredictionAmount;
    }
    int predictionAmountAdjustment(-1);
    if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_PREDICTION_AMOUNT_ADJUSTMENT, predictionAmountAdjustment) )
    {
        if( predictionAmountAdjustment < 0 )
        {
            // negative amount doesn't make sense
            predictionAmountAdjustment = 0;
        }
        mPanGesturePredictionAmountAdjustment = predictionAmountAdjustment;
    }
    int smoothingMode;
    if( GetIntegerEnvironmentVariable(DALI_ENV_PAN_SMOOTHING_MODE, smoothingMode) )
    {
        mPanGestureSmoothingMode = smoothingMode;
    }
    float smoothingAmount = 1.0f;
    if( GetFloatEnvironmentVariable(DALI_ENV_PAN_SMOOTHING_AMOUNT, smoothingAmount) )
    {
        smoothingAmount = Clamp(smoothingAmount, 0.0f, 1.0f);
        mPanGestureSmoothingAmount = smoothingAmount;
    }

    int minimumDistance(-1);
    if ( GetIntegerEnvironmentVariable(DALI_ENV_PAN_MINIMUM_DISTANCE, minimumDistance ))
    {
        mPanMinimumDistance = minimumDistance;
    }

    int minimumEvents(-1);
    if ( GetIntegerEnvironmentVariable(DALI_ENV_PAN_MINIMUM_EVENTS, minimumEvents ))
    {
        mPanMinimumEvents = minimumEvents;
    }

    int glesCallTime(0);
    if ( GetIntegerEnvironmentVariable(DALI_GLES_CALL_TIME, glesCallTime ))
    {
        mGlesCallTime = glesCallTime;
    }

    int windowWidth(0), windowHeight(0);
    if ( GetIntegerEnvironmentVariable( DALI_WINDOW_WIDTH, windowWidth ) && GetIntegerEnvironmentVariable( DALI_WINDOW_HEIGHT, windowHeight ) )
    {
        mWindowWidth = windowWidth;
        mWindowHeight = windowHeight;
    }

    const char * windowName = GetCharEnvironmentVariable( DALI_WINDOW_NAME );
    if ( windowName )
    {
        mWindowName = windowName;
    }

    const char * windowClassName = GetCharEnvironmentVariable( DALI_WINDOW_CLASS_NAME );
    if ( windowClassName )
    {
        mWindowClassName = windowClassName;
    }
}
void PhysicsWorld::SimulateIslands(const TimeStep &timeStep)
{
	// clear & update flags
	for (RigidBody &body : mRigidBodies)
	{
		// body
		body.mFlags.Clear(PhysicsFlags::ISLAND);
		body.mFlags.Set(PhysicsFlags::CAN_SLEEP);

		// joints
		for (auto &jointEdge : body.mJointEdges)
		{
			Joint &joint = *jointEdge.joint;
			joint.mFlags.Clear(PhysicsFlags::ISLAND);

			if (!joint.mAllowSleep)
				body.mFlags.Clear(PhysicsFlags::CAN_SLEEP);
		}

		// manifolds
		for (auto &collider : body.mColliders)
		for (auto &contactEdge : collider.mContactEdges)
			contactEdge.manifold->flags.Clear(PhysicsFlags::ISLAND);
	}

	// build & solve islands
	const float linearDampFactor = 1.0f - Clamp(mParams.linearDamping  * timeStep.dt, 0.0f, 1.0f);
	const float angularDampFactor = 1.0f - Clamp(mParams.angularDamping * timeStep.dt, 0.0f, 1.0f);
	 float sleepLinearThresholdSQ = mParams.sleepLinearThreshold * mParams.sleepLinearThreshold;
	const float sleepAngularThresholdSQ = mParams.sleepAngularThreshold * mParams.sleepAngularThreshold;
	Island island(mGravity, linearDampFactor, angularDampFactor);
	IN_LIST(RigidBody, mIslandSearchLink) queue;
	for (auto &seed : mRigidBodies)
	{
		// already belongs to one island, continue
		if (seed.mFlags.Test(PhysicsFlags::ISLAND))
			continue;

		// skip sleeping bodies
		if (mParams.allowSleep && !seed.IsAwake())
			continue;

		// skip static bodies
		if (seed.mType == RigidBody::STATIC)
			continue;

		// clear island and construct a new island 
		// using current rigid body as a "seed"
		float minSleepTime = FLT_MAX;
		island.Clear();
		seed.mFlags.Set(PhysicsFlags::ISLAND);
		queue.push_back(&seed);

		// build island
		// breadth first search (BFS) on the constraint graph (using a FIFO queue)
		while (!queue.empty())
		{
			// pop top body off the queue
			RigidBody &body = *queue.pop_front(); // if we use pop_back then this becomes a depth first search (DFS)

			// skip static bodies
			if (body.mType == RigidBody::STATIC)
				continue;

			island.Add(body);

			if (!body.IsAwake())
			{
				// make sure the body stays awake
				body.SetAwake(true);
			}

			if (body.mFlags.Test(PhysicsFlags::CAN_SLEEP)
				&& body.mLinearVelocity.LengthSq() < sleepLinearThresholdSQ
				&& body.mAngularVelocity.LengthSq() < sleepAngularThresholdSQ)
				body.mSleepTimer += timeStep.dt;
			else
				body.mSleepTimer = 0.0f;

			minSleepTime = Min(minSleepTime, body.mSleepTimer);

			// add joints to island (loop through joint edges)
			for (auto &edge : body.mJointEdges)
			{
				Joint &joint = *edge.joint;
				if (!joint.mFlags.Test(PhysicsFlags::ISLAND))
				{
					// add other rigid body (if existent) to island
					if (edge.other)
					{
						RigidBody &otherBody = *edge.other;
						if (!otherBody.mFlags.Test(PhysicsFlags::ISLAND) && otherBody.mType != RigidBody::STATIC)
						{
							otherBody.mFlags.Set(PhysicsFlags::ISLAND);
							queue.push_back(&otherBody);
						}
					}

					// add joint to island
					joint.mFlags.Set(PhysicsFlags::ISLAND);
					island.Add(joint);
				}
			} // end of looping through joint edges

			// add contact manifolds to the island
			for (auto &collider : body.mColliders)
			{
				for (auto &edge : collider.mContactEdges)
				{
					ContactManifold &manifold = *edge.manifold;
					if (manifold.isColliding && !manifold.flags.Test(PhysicsFlags::ISLAND))
					{
						// add other rigid body to island
						RigidBody &otherBody = *edge.other->mParent;
						if (!otherBody.mFlags.Test(PhysicsFlags::ISLAND) && otherBody.mType != RigidBody::STATIC)
						{
							otherBody.mFlags.Set(PhysicsFlags::ISLAND);
							queue.push_back(&otherBody);
						}

						// add manifold to island
						manifold.flags.Set(PhysicsFlags::ISLAND);
						if (!manifold.colliderA->mIsSensor && !manifold.colliderB->mIsSensor) // skip sensors
							island.Add(manifold);
					} // end of looping through contact edges
				} // end of looping through contact edges

			} // end of looping through colliders
		} // end of building island

		// solve island or put island to sleep
		if (minSleepTime < mParams.sleepTimeThreshold)
		{
			island.Step(timeStep);

			// post-solve
			for (auto &body : island.mRigidBodies)
			{
				// record energy (ignores 0.5 constant factor)
				if (body.mType != RigidBody::STATIC)
				{
					const MassData &m = body.mMassData;
					mStats.energy += m.mass * body.mLinearVelocity.LengthSq();
					mStats.energy += body.mAngularVelocity.Dot(m.unitLocalInertiaTensor * body.mAngularVelocity);
				}
			} // end of post-solve
		}
		else
			island.Sleep(timeStep);

		// update island stats
		timeStep.stats.minIslandSize = Min(island.NumRigidBodies(), timeStep.stats.minIslandSize);
		timeStep.stats.maxIslandSize = Max(island.NumRigidBodies(), timeStep.stats.maxIslandSize);
		++timeStep.stats.islands;
	}
	if (!timeStep.stats.islands)
		timeStep.stats.minIslandSize = timeStep.stats.maxIslandSize = 0;
	timeStep.stats.avgIslandSize = timeStep.stats.islands ? static_cast<float>(timeStep.stats.rigidBodies) / timeStep.stats.islands : 0.0f;

}
void IRenderPipeline3D::RasterizeTriangles()
{
	for (UINT tri = 0;tri < m_pIB_HomoSpace_Clipped->size() - 2;tri += 3)
	{
		UINT idx1 = m_pIB_HomoSpace_Clipped->at(tri);
		UINT idx2 = m_pIB_HomoSpace_Clipped->at(tri + 1);
		UINT idx3 = m_pIB_HomoSpace_Clipped->at(tri + 2);

		RasterizedFragment outVertex;

		//3 vertices of triangles ( in homogeneous space , [-1,1]x[-1,1])
		const auto& v1 = m_pVB_HomoSpace_Clipped->at(idx1);
		const auto& v2 = m_pVB_HomoSpace_Clipped->at(idx2);
		const auto& v3 = m_pVB_HomoSpace_Clipped->at(idx3);


		//convert to pixel space
		auto convertToPixelSpace = [&](const VertexShaderOutput_Vertex& v, VECTOR2& outV)
		{
			outV.x = float(mBufferWidth) * (v.posH.x + 1.0f) / 2.0f;
			outV.y = float(mBufferHeight) * (-v.posH.y + 1.0f) / 2.0f;
		};

		VECTOR2 v1_pixel, v2_pixel, v3_pixel;//pixel space
		convertToPixelSpace(v1, v1_pixel);
		convertToPixelSpace(v2, v2_pixel);
		convertToPixelSpace(v3, v3_pixel);

		//Basis Vector, used to compute the bilinear interpolation coord (s,t) of current pixel
		VECTOR2 basisVector1 = v2_pixel - v1_pixel;
		VECTOR2 basisVector2 = v3_pixel - v1_pixel;

		//a determinant to solve B-Lerp Coord equation
		//refer to doc for more math detail.
		float D = basisVector1.x*basisVector2.y - basisVector2.x*basisVector1.y;

		//in such circumstances,A B C lie on the same line.
		//------well , use THE SIGN OF D can implement BACKFACE CULLING--------
		if (D == 0)return;

		//scanline rasterization , generate pixels ROW-BY-ROW
		float minY = Clamp(min(min(v1_pixel.y, v2_pixel.y), v3_pixel.y), 0, float(mBufferHeight - 1));
		float maxY = Clamp(max(max(v1_pixel.y, v2_pixel.y), v3_pixel.y), 0, float(mBufferHeight - 1));

		//------------ horizontal scan line Intersection ------------
		for (int j = int(minY);j < int(maxY) + 1;++j)
		{
			BOOL intersectSucceeded = FALSE;
			UINT x1 = 0, x2 = 0;
			intersectSucceeded =
				mFunction_HorizontalIntersect(float(j), v1_pixel, v2_pixel, v3_pixel, x1, x2);

			//x1 = Clamp(x1, 0, mBufferWidth - 1);
			//x2 = Clamp(x2, 0, mBufferWidth - 1);

			//if intersect succeed, we will get X region [x1,x2] which indicate the range of pixels to fill
			if (intersectSucceeded == TRUE)
			{
				//-----------------FOR EACH RASTERIZED FRAGMENT----------------
				for (UINT i = x1;i <= x2;++i)
				{
					if (i >= mBufferWidth || j >= mBufferHeight)
					{
						break;
					}

					//pixel coord of current processing pixel
					VECTOR2 currentPoint_pixel = VECTOR2(float(i) + 0.5f, float(j) + 0.5f);

					//v1 (A) is the orginal point of basis, calculate the relative pixel coordinate
					VECTOR2 currentPointLocal_pixel = currentPoint_pixel - v1_pixel;

					//calculate the bilinear interpolation ratio coordinate (s,t)
					// (->localP) = s (->V1) + t(->V2)
					float s = (currentPointLocal_pixel.x*basisVector2.y - currentPointLocal_pixel.y*basisVector2.x) / D;
					float t = (basisVector1.x*currentPointLocal_pixel.y - basisVector1.y*currentPointLocal_pixel.x) / D;

					//depth correct interpolation ,then perform depth test
					float depth = 1.0f / (s / v2.posH.z + t / v3.posH.z + (1 - s - t) / v1.posH.z);
					if (mFunction_DepthTest(i, j, depth) == FALSE)goto label_nextPixel;

					//I will use normal bilinear interpolation to see the result first
					outVertex.pixelX = i;
					outVertex.pixelY = j;

					//perspective correct interpolation
					outVertex.color =
						(s / v2.posH.z* v2.color +
							t / v3.posH.z *v3.color +
							(1 - s - t) / v1.posH.z *v1.color)*depth;

					outVertex.texcoord =
						(s / v2.posH.z * v2.texcoord +
							t / v3.posH.z * v3.texcoord +
							(1 - s - t) / v1.posH.z * v1.texcoord)*depth;


					m_pVB_Rasterized->push_back(outVertex);
				label_nextPixel:;
				}//for each x (column)
			}//if horizontal intersect succeed

		}//for each y (row)
	}//for each homogeneous clip space triangle
}
Exemple #30
0
void Ship::StaticUpdate(const float timeStep)
{
	// do player sounds before dead check, so they also turn off
	if (IsType(Object::PLAYER)) DoThrusterSounds();

	if (IsDead()) return;

	if (m_controller) m_controller->StaticUpdate(timeStep);

	if (GetHullTemperature() > 1.0)
		Explode();

	UpdateAlertState();

	/* FUEL SCOOPING!!!!!!!!! */
	if ((m_flightState == FLYING) && (m_equipment.Get(Equip::SLOT_FUELSCOOP) != Equip::NONE)) {
		Body *astro = GetFrame()->GetBody();
		if (astro && astro->IsType(Object::PLANET)) {
			Planet *p = static_cast<Planet*>(astro);
			if (p->GetSystemBody()->IsScoopable()) {
				double dist = GetPosition().Length();
				double pressure, density;
				p->GetAtmosphericState(dist, &pressure, &density);

				double speed = GetVelocity().Length();
				vector3d vdir = GetVelocity().Normalized();
				vector3d pdir = -GetOrient().VectorZ();
				double dot = vdir.Dot(pdir);
				if ((m_stats.free_capacity) && (dot > 0.95) && (speed > 2000.0) && (density > 1.0)) {
					double rate = speed*density*0.00001f;
					if (Pi::rng.Double() < rate) {
						m_equipment.Add(Equip::HYDROGEN);
						UpdateEquipStats();
						if (this->IsType(Object::PLAYER)) {
							Pi::Message(stringf(Lang::FUEL_SCOOP_ACTIVE_N_TONNES_H_COLLECTED,
									formatarg("quantity", m_equipment.Count(Equip::SLOT_CARGO, Equip::HYDROGEN))));
						}
					}
				}
			}
		}
	}

	// Cargo bay life support
	if (m_equipment.Get(Equip::SLOT_CARGOLIFESUPPORT) != Equip::CARGO_LIFE_SUPPORT) {
		// Hull is pressure-sealed, it just doesn't provide
		// temperature regulation and breathable atmosphere

		// kill stuff roughly every 5 seconds
		if ((!m_dockedWith) && (5.0*Pi::rng.Double() < timeStep)) {
			Equip::Type t = (Pi::rng.Int32(2) ? Equip::LIVE_ANIMALS : Equip::SLAVES);

			if (m_equipment.Remove(t, 1)) {
				m_equipment.Add(Equip::FERTILIZER);
				if (this->IsType(Object::PLAYER)) {
					Pi::Message(Lang::CARGO_BAY_LIFE_SUPPORT_LOST);
				}
			}
		}
	}

	if (m_flightState == FLYING)
		m_launchLockTimeout -= timeStep;
	if (m_launchLockTimeout < 0) m_launchLockTimeout = 0;

	// lasers
	for (int i=0; i<ShipType::GUNMOUNT_MAX; i++) {
		m_gunRecharge[i] -= timeStep;
		float rateCooling = 0.01f;
		if (m_equipment.Get(Equip::SLOT_LASERCOOLER) != Equip::NONE)  {
			rateCooling *= float(Equip::types[ m_equipment.Get(Equip::SLOT_LASERCOOLER) ].pval);
		}
		m_gunTemperature[i] -= rateCooling*timeStep;
		if (m_gunTemperature[i] < 0.0f) m_gunTemperature[i] = 0;
		if (m_gunRecharge[i] < 0.0f) m_gunRecharge[i] = 0;

		if (!m_gunState[i]) continue;
		if (m_gunRecharge[i] > 0.0f) continue;
		if (m_gunTemperature[i] > 1.0) continue;

		FireWeapon(i);
	}

	if (m_ecmRecharge > 0.0f) {
		m_ecmRecharge = std::max(0.0f, m_ecmRecharge - timeStep);
	}

	if (m_stats.shield_mass_left < m_stats.shield_mass) {
		// 250 second recharge
		float recharge_rate = 0.004f;
		if (m_equipment.Get(Equip::SLOT_ENERGYBOOSTER) != Equip::NONE) {
			recharge_rate *= float(Equip::types[ m_equipment.Get(Equip::SLOT_ENERGYBOOSTER) ].pval);
		}
		m_stats.shield_mass_left += m_stats.shield_mass * recharge_rate * timeStep;
	}
	m_stats.shield_mass_left = Clamp(m_stats.shield_mass_left, 0.0f, m_stats.shield_mass);

	if (m_wheelTransition) {
		m_wheelState += m_wheelTransition*0.3f*timeStep;
		m_wheelState = Clamp(m_wheelState, 0.0f, 1.0f);
		if (is_equal_exact(m_wheelState, 0.0f) || is_equal_exact(m_wheelState, 1.0f))
			m_wheelTransition = 0;
	}

	if (m_testLanded) TestLanded();

	if (m_equipment.Get(Equip::SLOT_HULLAUTOREPAIR) == Equip::HULL_AUTOREPAIR) {
		const ShipType &stype = GetShipType();
		m_stats.hull_mass_left = std::min(m_stats.hull_mass_left + 0.1f*timeStep, float(stype.hullMass));
	}

	// After calling StartHyperspaceTo this Ship must not spawn objects
	// holding references to it (eg missiles), as StartHyperspaceTo
	// removes the ship from Space::bodies and so the missile will not
	// have references to this cleared by NotifyRemoved()
	if (m_hyperspace.countdown > 0.0f) {
		m_hyperspace.countdown = m_hyperspace.countdown - timeStep;
		if (m_hyperspace.countdown <= 0.0f) {
			m_hyperspace.countdown = 0;
			m_hyperspace.now = true;
		}
	}

	if (m_hyperspace.now) {
		m_hyperspace.now = false;
		EnterHyperspace();
	}
}