Example #1
0
		GLColorBuffer GLDepthOfFieldFilter::UnderSample(GLColorBuffer tex) {
			SPADES_MARK_FUNCTION();
			// do gaussian blur
			GLProgram *program = passthrough;
			IGLDevice *dev = renderer->GetGLDevice();
			GLQuadRenderer qr(dev);
			int w = tex.GetWidth();
			int h = tex.GetHeight();
			
			static GLProgramAttribute blur_positionAttribute("positionAttribute");
			static GLProgramUniform blur_textureUniform("texture");
			static GLProgramUniform blur_colorUniform("colorUniform");
			static GLProgramUniform blur_texCoordRangeUniform("texCoordRange");
			program->Use();
			blur_positionAttribute(program);
			
			blur_textureUniform(program);
			blur_textureUniform.SetValue(0);
			dev->ActiveTexture(0);
			dev->BindTexture(IGLDevice::Texture2D, tex.GetTexture());
			
			blur_colorUniform(program);
			blur_colorUniform.SetValue(1.f,1.f,1.f,1.f);
			
			blur_texCoordRangeUniform(program);
			blur_texCoordRangeUniform.SetValue(0.f, 0.f, 1.f, 1.f);
			
			qr.SetCoordAttributeIndex(blur_positionAttribute());
			dev->Enable(IGLDevice::Blend, false);
			
			GLColorBuffer buf2 = renderer->GetFramebufferManager()->CreateBufferHandle(w/2, h/2, false);
			dev->Viewport(0, 0, w/2, h/2);
			dev->BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer());
			qr.Draw();
			return buf2;
		}
		void GLModelRenderer::RenderDynamicLightPass(std::vector<GLDynamicLight> lights) {
			SPADES_MARK_FUNCTION();
			
			GLProfiler profiler(device, "Model [%d model(s), %d unique model type(s)]", modelCount, (int)models.size());
			
			if(!lights.empty()){
				
				for(size_t i = 0; i < models.size(); i++){
					RenderModel& m = models[i];
					GLModel *model = m.model;
					
					model->RenderDynamicLightPass(m.params, lights);
				}
					
			}
			
			// last phase: clear scene
			for(size_t i = 0; i < models.size(); i++){
				models[i].model->renderId = -1;
			}
			models.clear();
			
			modelCount = 0;
		}
Example #3
0
		GLShader *GLProgramManager::CreateShader(const std::string &name) {
			SPADES_MARK_FUNCTION();
			
			SPLog("Loading GLSL shader '%s'", name.c_str());
			std::string text = FileManager::ReadAllBytes(name.c_str());
			GLShader::Type type;
			
			if(name.find(".fs") != std::string::npos)
				type = GLShader::FragmentShader;
			else if(name.find(".vs") != std::string::npos)
				type = GLShader::VertexShader;
			else
				SPRaise("Failed to determine the type of a shader: %s",
						name.c_str());
			
			GLShader *s = new GLShader(device, type);
			s->AddSource(text);
			
			Stopwatch sw;
			s->Compile();
			SPLog("Successfully compiled GLSL program '%s' in %.3fms", name.c_str(),
				  sw.GetTime() * 1000.);
			return s;
		}
Example #4
0
	StdStream::~StdStream() {
		SPADES_MARK_FUNCTION();

		if (autoClose)
			fclose(handle);
	}
Example #5
0
		GLColorBuffer GLBloomFilter::Filter(GLColorBuffer input) {
			SPADES_MARK_FUNCTION();
			
			
			
			std::vector<Level> levels;
			
			IGLDevice *dev = renderer->GetGLDevice();
			GLQuadRenderer qr(dev);
			
			static GLProgramAttribute thruPosition("positionAttribute");
			static GLProgramUniform thruColor("colorUniform");
			static GLProgramUniform thruTexture("texture");
			static GLProgramUniform thruTexCoordRange("texCoordRange");
			
			thruPosition(thru);
			thruColor(thru);
			thruTexture(thru);
			thruTexCoordRange(thru);
			
			GLProgram *gammaMix = renderer->RegisterProgram("Shaders/PostFilters/GammaMix.program");
			static GLProgramAttribute gammaMixPosition("positionAttribute");
			static GLProgramUniform gammaMixTexture1("texture1");
			static GLProgramUniform gammaMixTexture2("texture2");
			static GLProgramUniform gammaMixMix1("mix1");
			static GLProgramUniform gammaMixMix2("mix2");
			
			gammaMixPosition(gammaMix);
			gammaMixTexture1(gammaMix);
			gammaMixTexture2(gammaMix);
			gammaMixMix1(gammaMix);
			gammaMixMix2(gammaMix);
			
			thru->Use();
			thruColor.SetValue(1.f, 1.f, 1.f, 1.f);
			thruTexture.SetValue(0);
			dev->Enable(IGLDevice::Blend, false);
			
			// create downsample levels
			for(int i = 0; i < 6; i++){
				GLColorBuffer prevLevel;
				if(i == 0){
					prevLevel = input;
				}else{
					prevLevel = levels.back().buffer;
				}
				
				int prevW = prevLevel.GetWidth();
				int prevH = prevLevel.GetHeight();
				int newW = (prevW + 1) / 2;
				int newH = (prevH + 1) / 2;
				GLColorBuffer newLevel = input.GetManager()->CreateBufferHandle(newW, newH);
				
				thru->Use();
				qr.SetCoordAttributeIndex(thruPosition());
				dev->BindTexture(IGLDevice::Texture2D, prevLevel.GetTexture());
				dev->BindFramebuffer(IGLDevice::Framebuffer, newLevel.GetFramebuffer());
				dev->Viewport(0, 0, newLevel.GetWidth(), newLevel.GetHeight());
				thruTexCoordRange.SetValue(0.f, 0.f,
										   (float)newLevel.GetWidth() * 2.f / (float)prevW,
										   (float)newLevel.GetHeight() * 2.f / (float)prevH);
				qr.Draw();
				dev->BindTexture(IGLDevice::Texture2D, 0);
				
				Level lv;
				lv.w = newW; lv.h = newH;
				lv.buffer = newLevel;
				levels.push_back(lv);
			}
			
			dev->Enable(IGLDevice::Blend, true);
			dev->BlendFunc(IGLDevice::SrcAlpha,
						   IGLDevice::OneMinusSrcAlpha);
			
			// composite levels in the opposite direction
			thruTexCoordRange.SetValue(0.f, 0.f, 1.f, 1.f);
			for(int i = (int)levels.size() - 1; i >= 1; i--){
				int cnt = (int)levels.size() - i;
				float alpha = (float)cnt / (float)(cnt + 1);
				alpha = sqrtf(alpha);
				GLColorBuffer curLevel = levels[i].buffer;
				GLColorBuffer targLevel = levels[i - 1].buffer;
			
				thru->Use();
				qr.SetCoordAttributeIndex(thruPosition());
				dev->BindTexture(IGLDevice::Texture2D, curLevel.GetTexture());
				dev->BindFramebuffer(IGLDevice::Framebuffer, targLevel.GetFramebuffer());
				dev->Viewport(0, 0, targLevel.GetWidth(), targLevel.GetHeight());
				thruColor.SetValue(1.f, 1.f, 1.f, alpha);
				qr.Draw();
				dev->BindTexture(IGLDevice::Texture2D, 0);
			}
			
			// composite to the final image
			GLColorBuffer output = input.GetManager()->CreateBufferHandle();
			GLColorBuffer topLevel = levels[0].buffer;
			
			gammaMix->Use();
			qr.SetCoordAttributeIndex(gammaMixPosition());
			dev->ActiveTexture(0);
			dev->BindTexture(IGLDevice::Texture2D, input.GetTexture());
			dev->ActiveTexture(1);
			dev->BindTexture(IGLDevice::Texture2D, topLevel.GetTexture());
			dev->BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer());
			dev->Viewport(0, 0, output.GetWidth(), output.GetHeight());
			gammaMixTexture1.SetValue(0);
			gammaMixTexture2.SetValue(1);
			gammaMixMix1.SetValue(.8f, .8f, .8f);
			gammaMixMix2.SetValue(.2f, .2f, .2f);
			qr.Draw();
			dev->BindTexture(IGLDevice::Texture2D, 0);
			
			dev->ActiveTexture(0);
			
			return output;
		}
Example #6
0
		virtual void Save(IStream *, Bitmap *) {
			SPADES_MARK_FUNCTION();
			SPNotImplemented();
		}
Example #7
0
		GLVoxelModel::~GLVoxelModel() {
			SPADES_MARK_FUNCTION();

			device->DeleteBuffer(idxBuffer);
			device->DeleteBuffer(buffer);
		}
Example #8
0
		void GLVoxelModel::RenderSunlightPass(std::vector<client::ModelRenderParam> params) {
			SPADES_MARK_FUNCTION();

			device->ActiveTexture(0);
			aoImage->Bind(IGLDevice::Texture2D);
			device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter,
			                     IGLDevice::Linear);

			device->Enable(IGLDevice::CullFace, true);
			device->Enable(IGLDevice::DepthTest, true);

			program->Use();

			static GLShadowShader shadowShader;
			shadowShader(renderer, program, 1);

			static GLProgramUniform fogDistance("fogDistance");
			fogDistance(program);
			fogDistance.SetValue(renderer->GetFogDistance());

			static GLProgramUniform fogColor("fogColor");
			fogColor(program);
			Vector3 fogCol = renderer->GetFogColorForSolidPass();
			fogCol *= fogCol;
			fogColor.SetValue(fogCol.x, fogCol.y, fogCol.z);

			static GLProgramUniform aoUniform("ambientOcclusionTexture");
			aoUniform(program);
			aoUniform.SetValue(0);

			static GLProgramUniform modelOrigin("modelOrigin");
			modelOrigin(program);
			modelOrigin.SetValue(origin.x, origin.y, origin.z);

			static GLProgramUniform sunLightDirection("sunLightDirection");
			sunLightDirection(program);
			Vector3 sunPos = MakeVector3(0, -1, -1);
			sunPos = sunPos.Normalize();
			sunLightDirection.SetValue(sunPos.x, sunPos.y, sunPos.z);

			static GLProgramUniform viewOriginVector("viewOriginVector");
			viewOriginVector(program);
			const auto &viewOrigin = renderer->GetSceneDef().viewOrigin;
			viewOriginVector.SetValue(viewOrigin.x, viewOrigin.y, viewOrigin.z);

			// setup attributes
			static GLProgramAttribute positionAttribute("positionAttribute");
			static GLProgramAttribute textureCoordAttribute("textureCoordAttribute");
			static GLProgramAttribute colorAttribute("colorAttribute");
			static GLProgramAttribute normalAttribute("normalAttribute");

			positionAttribute(program);
			textureCoordAttribute(program);
			colorAttribute(program);
			normalAttribute(program);

			device->BindBuffer(IGLDevice::ArrayBuffer, buffer);
			device->VertexAttribPointer(positionAttribute(), 4, IGLDevice::UnsignedByte, false,
			                            sizeof(Vertex), (void *)0);
			device->VertexAttribPointer(textureCoordAttribute(), 2, IGLDevice::UnsignedShort, false,
			                            sizeof(Vertex), (void *)4);
			device->VertexAttribPointer(colorAttribute(), 4, IGLDevice::UnsignedByte, true,
			                            sizeof(Vertex), (void *)8);
			device->VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false,
			                            sizeof(Vertex), (void *)12);
			device->BindBuffer(IGLDevice::ArrayBuffer, 0);

			device->EnableVertexAttribArray(positionAttribute(), true);
			device->EnableVertexAttribArray(textureCoordAttribute(), true);
			device->EnableVertexAttribArray(colorAttribute(), true);
			device->EnableVertexAttribArray(normalAttribute(), true);

			device->BindBuffer(IGLDevice::ElementArrayBuffer, idxBuffer);

			for (size_t i = 0; i < params.size(); i++) {
				const client::ModelRenderParam &param = params[i];

				// frustrum cull
				float rad = radius;
				rad *= param.matrix.GetAxis(0).GetLength();
				if (!renderer->SphereFrustrumCull(param.matrix.GetOrigin(), rad)) {
					continue;
				}

				static GLProgramUniform customColor("customColor");
				customColor(program);
				customColor.SetValue(param.customColor.x, param.customColor.y, param.customColor.z);

				Matrix4 modelMatrix = param.matrix;
				static GLProgramUniform projectionViewModelMatrix("projectionViewModelMatrix");
				projectionViewModelMatrix(program);
				projectionViewModelMatrix.SetValue(renderer->GetProjectionViewMatrix() *
				                                   modelMatrix);

				static GLProgramUniform viewModelMatrix("viewModelMatrix");
				viewModelMatrix(program);
				viewModelMatrix.SetValue(renderer->GetViewMatrix() * modelMatrix);

				static GLProgramUniform modelMatrixU("modelMatrix");
				modelMatrixU(program);
				modelMatrixU.SetValue(modelMatrix);

				modelMatrix.m[12] = 0.f;
				modelMatrix.m[13] = 0.f;
				modelMatrix.m[14] = 0.f;
				static GLProgramUniform modelNormalMatrix("modelNormalMatrix");
				modelNormalMatrix(program);
				modelNormalMatrix.SetValue(modelMatrix);

				if (param.depthHack) {
					device->DepthRange(0.f, 0.1f);
				}

				device->DrawElements(IGLDevice::Triangles, numIndices, IGLDevice::UnsignedInt,
				                     (void *)0);
				if (param.depthHack) {
					device->DepthRange(0.f, 1.f);
				}
			}

			device->BindBuffer(IGLDevice::ElementArrayBuffer, 0);

			device->EnableVertexAttribArray(positionAttribute(), false);
			device->EnableVertexAttribArray(textureCoordAttribute(), false);
			device->EnableVertexAttribArray(colorAttribute(), false);
			device->EnableVertexAttribArray(normalAttribute(), false);

			device->ActiveTexture(0);
			device->BindTexture(IGLDevice::Texture2D, 0);
		}
Example #9
0
		void GLVoxelModel::Prerender(std::vector<client::ModelRenderParam> params) {
			SPADES_MARK_FUNCTION();

			RenderSunlightPass(params);
		}
		/** Handles movement of joined local player. */
		void Client::UpdateLocalPlayer(float dt) {
			SPADES_MARK_FUNCTION();
			
			auto *player = world->GetLocalPlayer();
			
			PlayerInput inp = playerInput;
			WeaponInput winp = weapInput;
			
			// weapon/tools are disabled while/soon after sprinting
			if(GetSprintState() > 0.001f) {
				winp.primary = false;
				winp.secondary = false;
			}
			
			// don't allow to stand up when ceilings are too low
			if(inp.crouch == false){
				if(player->GetInput().crouch){
					if(!player->TryUncrouch(false)){
						inp.crouch = true;
					}
				}
			}
			
			// don't allow jumping in the air
			if(inp.jump){
				if(!player->IsOnGroundOrWade())
					inp.jump = false;
			}
			
			// weapon/tools are disabled while changing tools
			if(clientPlayers[world->GetLocalPlayerIndex()]->IsChangingTool()) {
				winp.primary = false;
				winp.secondary = false;
			}
			
			// disable weapon while reloading (except shotgun)
			if(player->GetTool() == Player::ToolWeapon &&
			   player->IsAwaitingReloadCompletion() &&
			   !player->GetWeapon()->IsReloadSlow()) {
				winp.primary = false;
			}
			
			player->SetInput(inp);
			player->SetWeaponInput(winp);
			
			//send player input
			// FIXME: send only there are any changed?
			net->SendPlayerInput(inp);
			net->SendWeaponInput(winp);
			
			if(hasDelayedReload) {
				world->GetLocalPlayer()->Reload();
				net->SendReload();
				hasDelayedReload = false;
			}
			
			//PlayerInput actualInput = player->GetInput();
			WeaponInput actualWeapInput = player->GetWeaponInput();
			
			if(actualWeapInput.secondary &&
			   player->IsToolWeapon() &&
			   player->IsAlive()){
			}else{
				if(player->IsToolWeapon()){
					// there is a possibility that player has respawned or something.
					// stop aiming down
					weapInput.secondary = false;
				}
			}
			
			// is the selected tool no longer usable (ex. out of ammo)?
			if(!player->IsToolSelectable(player->GetTool())) {
				// release mouse button before auto-switching tools
				winp.primary = false;
				winp.secondary = false;
				weapInput = winp;
				net->SendWeaponInput(weapInput);
				actualWeapInput = winp = player->GetWeaponInput();
				
				// select another tool
				Player::ToolType t = player->GetTool();
				do{
					switch(t){
						case Player::ToolSpade:
							t = Player::ToolGrenade;
							break;
						case Player::ToolBlock:
							t = Player::ToolSpade;
							break;
						case Player::ToolWeapon:
							t = Player::ToolBlock;
							break;
						case Player::ToolGrenade:
							t = Player::ToolWeapon;
							break;
					}
				}while(!world->GetLocalPlayer()->IsToolSelectable(t));
				SetSelectedTool(t);
			}
			
			// send orientation
			Vector3 curFront = player->GetFront();
			if(curFront.x != lastFront.x ||
			   curFront.y != lastFront.y ||
			   curFront.z != lastFront.z) {
				lastFront = curFront;
				net->SendOrientation(curFront);
			}
			
			lastKills = world->GetPlayerPersistent(player->GetId()).kills;
			
			// show block count when building block lines.
			if(player->IsAlive() &&
			   player->GetTool() == Player::ToolBlock &&
			   player->GetWeaponInput().secondary &&
			   player->IsBlockCursorDragging()) {
				if(player->IsBlockCursorActive()) {
					auto blocks = std::move
					(world->CubeLine(player->GetBlockCursorDragPos(),
									 player->GetBlockCursorPos(),
									 256));
					auto msg = _TrN("Client",
									"{0} block", "{0} blocks",
									blocks.size());
					AlertType type =
					static_cast<int>(blocks.size()) > player->GetNumBlocks() ?
					AlertType::Warning : AlertType::Notice;
					ShowAlert(msg, type, 0.f, true);
				}else{
					// invalid
					auto msg = _Tr("Client", "-- blocks");
					AlertType type = AlertType::Warning;
					ShowAlert(msg, type, 0.f, true);
				}
			}
			
			if(player->IsAlive())
				lastAliveTime = time;
			
			if(player->GetHealth() < lastHealth){
				// ouch!
				lastHealth = player->GetHealth();
				lastHurtTime = world->GetTime();
				
				Handle<IAudioChunk> c;
				switch((rand() >> 3) & 3){
					case 0:
						c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/FleshLocal1.wav");
						break;
					case 1:
						c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/FleshLocal2.wav");
						break;
					case 2:
						c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/FleshLocal3.wav");
						break;
					case 3:
						c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/FleshLocal4.wav");
						break;
				}
				audioDevice->PlayLocal(c, AudioParam());
				
				float hpper = player->GetHealth() / 100.f;
				int cnt = 18 - (int)(player->GetHealth() / 100.f * 8.f);
				hurtSprites.resize(std::max(cnt, 6));
				for(size_t i = 0; i < hurtSprites.size(); i++) {
					HurtSprite& spr = hurtSprites[i];
					spr.angle = GetRandom() * (2.f * static_cast<float>(M_PI));
					spr.scale = .2f + GetRandom() * GetRandom() * .7f;
					spr.horzShift = GetRandom();
					spr.strength = .3f + GetRandom() * .7f;
					if(hpper > .5f) {
						spr.strength *= 1.5f - hpper;
					}
				}
				
			}else{
Example #11
0
		Weapon::~Weapon(){
			
			SPADES_MARK_FUNCTION();
		}
    virtual Bitmap *Load(IStream *stream) {
        SPADES_MARK_FUNCTION();

        // read all
        std::string data = stream->ReadAllBytes();

        // copy to buffer
        Fl_Image *img = LoadFltkImage(data);

        SPAssert(img);
        SPAssert(img->count() >= 1);

        const unsigned char* inPixels =
            (const unsigned char *)img->data()[0];
        int depth = img->d();
        int width = img->w();
        int height = img->h();
        int pitch = width * depth + img->ld();

        Handle<Bitmap> bmp;
        try {
            bmp = new Bitmap(width, height);
        } catch(...) {
            delete img;
            throw;
        }
        try {
            unsigned char *outPixels = (unsigned char *)bmp->GetPixels();

            if(pitch == width * 4 && depth == 4) {
                // if the format matches the requirement of Bitmap,
                // just use it
                memcpy(outPixels, inPixels, pitch * height);
            } else {
                // convert
                const unsigned char* line;
                for(int y = 0; y < height; y++) {
                    line = inPixels;
                    for(int x = 0; x < width; x++) {
                        uint8_t r, g, b, a;
                        switch(depth) {
                        case 1:
                            r = g = b = *(line++);
                            a = 255;
                            break;
                        case 2:
                            r = g = b = *(line++);
                            a = *(line++);
                            break;
                        case 3:
                            r = *(line++);
                            g = *(line++);
                            b = *(line++);
                            a = 255;
                            break;
                        case 4:
                            r = *(line++);
                            g = *(line++);
                            b = *(line++);
                            a = *(line++);
                            break;
                        default:
                            SPAssert(false);
                        }
                        *(outPixels++) = r;
                        *(outPixels++) = g;
                        *(outPixels++) = b;
                        *(outPixels++) = a;
                    }
                    inPixels += pitch;
                }
            }
            delete img;
            return bmp.Unmanage();
        } catch(...) {
            delete img;
            throw;
        }
    }
Example #13
0
		void GLSpriteRenderer::Render() {
			SPADES_MARK_FUNCTION();
			lastImage = NULL;
			program->Use();
			
			projectionViewMatrix(program);
			rightVector(program);
			upVector(program);
			texture(program);
			viewMatrix(program);
			fogDistance(program);
			fogColor(program);
			
			positionAttribute(program);
			spritePosAttribute(program);
			colorAttribute(program);
			
			projectionViewMatrix.SetValue(renderer->GetProjectionViewMatrix());
			viewMatrix.SetValue(renderer->GetViewMatrix());
			
			fogDistance.SetValue(renderer->GetFogDistance());
			
			Vector3 fogCol = renderer->GetFogColor();
			fogColor.SetValue(fogCol.x,fogCol.y,fogCol.z);
			
			const client::SceneDefinition& def = renderer->GetSceneDef();
			rightVector.SetValue(def.viewAxis[0].x,
								 def.viewAxis[0].y,
								 def.viewAxis[0].z);
			upVector.SetValue(def.viewAxis[1].x,
							  def.viewAxis[1].y,
							  def.viewAxis[1].z);
			texture.SetValue(0);
			
			device->ActiveTexture(0);
			
			device->EnableVertexAttribArray(positionAttribute(), true);
			device->EnableVertexAttribArray(spritePosAttribute(), true);
			device->EnableVertexAttribArray(colorAttribute(), true);
			
			
			for(size_t i = 0; i < sprites.size(); i++){
				Sprite& spr = sprites[i];
				if(spr.image != lastImage){
					Flush();
					lastImage = spr.image;
					SPAssert(vertices.empty());
				}
				
				Vertex v;
				v.x = spr.center.x;
				v.y = spr.center.y;
				v.z = spr.center.z;
				v.radius = spr.radius;
				v.angle = spr.angle;
				v.r = spr.color.x;
				v.g = spr.color.y;
				v.b = spr.color.z;
				v.a = spr.color.w;
				
				uint32_t idx = (uint32_t)vertices.size();
				v.sx = -1; v.sy = -1;
				vertices.push_back(v);
				v.sx = 1; v.sy = -1;
				vertices.push_back(v);
				v.sx = -1; v.sy = 1;
				vertices.push_back(v);
				v.sx = 1; v.sy = 1;
				vertices.push_back(v);
				
				indices.push_back(idx);
				indices.push_back(idx + 1);
				indices.push_back(idx + 2);
				indices.push_back(idx + 1);
				indices.push_back(idx + 3);
				indices.push_back(idx + 2);
			}
		
			Flush();
			
			device->EnableVertexAttribArray(positionAttribute(), false);
			device->EnableVertexAttribArray(spritePosAttribute(), false);
			device->EnableVertexAttribArray(colorAttribute(), false);
		}
Example #14
0
		void GLSpriteRenderer::Clear(){
			SPADES_MARK_FUNCTION();
			sprites.clear();
		}
Example #15
0
		GLSpriteRenderer::~GLSpriteRenderer(){
			SPADES_MARK_FUNCTION();
			
		}
Example #16
0
		StartupScreen::~StartupScreen() {
			SPADES_MARK_FUNCTION();
			helper->StartupScreenDestroyed();
		}
Example #17
0
		bool StartupScreen::NeedsAbsoluteMouseCoordinate() {
			SPADES_MARK_FUNCTION();
			return true;
		}
		GLColorBuffer GLColorCorrectionFilter::Filter(GLColorBuffer input, Vector3 tintVal) {
			SPADES_MARK_FUNCTION();

			IGLDevice *dev = renderer->GetGLDevice();
			GLQuadRenderer qr(dev);

			static GLProgramAttribute lensPosition("positionAttribute");
			static GLProgramUniform lensTexture("mainTexture");

			static GLProgramUniform saturation("saturation");
			static GLProgramUniform enhancement("enhancement");
			static GLProgramUniform tint("tint");

			saturation(lens);
			enhancement(lens);
			tint(lens);

			dev->Enable(IGLDevice::Blend, false);

			lensPosition(lens);
			lensTexture(lens);

			lens->Use();

			tint.SetValue(tintVal.x, tintVal.y, tintVal.z);

			const client::SceneDefinition &def = renderer->GetSceneDef();

			if (settings.r_hdr) {
				// when HDR is enabled ACES tone mapping is applied first, so
				// lower enhancement value is required
				if (settings.r_bloom) {
					saturation.SetValue(0.8f * def.saturation * settings.r_saturation);
					enhancement.SetValue(0.1f);
				} else {
					saturation.SetValue(0.9f * def.saturation * settings.r_saturation);
					enhancement.SetValue(0.0f);
				}
			} else {
				if (settings.r_bloom) {
					// make image sharper
					saturation.SetValue(.85f * def.saturation * settings.r_saturation);
					enhancement.SetValue(0.7f);
				} else {
					saturation.SetValue(1.f * def.saturation * settings.r_saturation);
					enhancement.SetValue(0.3f);
				}
			}

			lensTexture.SetValue(0);

			// composite to the final image
			GLColorBuffer output = input.GetManager()->CreateBufferHandle();

			qr.SetCoordAttributeIndex(lensPosition());
			dev->BindTexture(IGLDevice::Texture2D, input.GetTexture());
			dev->BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer());
			dev->Viewport(0, 0, output.GetWidth(), output.GetHeight());
			qr.Draw();
			dev->BindTexture(IGLDevice::Texture2D, 0);

			return output;
		}
Example #19
0
		void GLVoxelModel::RenderShadowMapPass(std::vector<client::ModelRenderParam> params) {
			SPADES_MARK_FUNCTION();

			device->Enable(IGLDevice::CullFace, true);
			device->Enable(IGLDevice::DepthTest, true);

			shadowMapProgram->Use();

			static GLShadowMapShader shadowMapShader;
			shadowMapShader(renderer, shadowMapProgram, 0);

			static GLProgramUniform modelOrigin("modelOrigin");
			modelOrigin(shadowMapProgram);
			modelOrigin.SetValue(origin.x, origin.y, origin.z);

			// setup attributes
			static GLProgramAttribute positionAttribute("positionAttribute");
			static GLProgramAttribute normalAttribute("normalAttribute");

			positionAttribute(shadowMapProgram);
			normalAttribute(shadowMapProgram);

			device->BindBuffer(IGLDevice::ArrayBuffer, buffer);
			device->VertexAttribPointer(positionAttribute(), 4, IGLDevice::UnsignedByte, false,
			                            sizeof(Vertex), (void *)0);
			if (normalAttribute() != -1) {
				device->VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false,
				                            sizeof(Vertex), (void *)12);
			}
			device->BindBuffer(IGLDevice::ArrayBuffer, 0);

			device->EnableVertexAttribArray(positionAttribute(), true);
			if (normalAttribute() != -1)
				device->EnableVertexAttribArray(normalAttribute(), true);

			device->BindBuffer(IGLDevice::ElementArrayBuffer, idxBuffer);

			for (size_t i = 0; i < params.size(); i++) {
				const client::ModelRenderParam &param = params[i];

				// frustrum cull
				float rad = radius;
				rad *= param.matrix.GetAxis(0).GetLength();

				if (param.depthHack)
					continue;

				if (!renderer->GetShadowMapRenderer()->SphereCull(param.matrix.GetOrigin(), rad)) {
					continue;
				}

				Matrix4 modelMatrix = param.matrix;

				static GLProgramUniform modelMatrixU("modelMatrix");
				modelMatrixU(shadowMapProgram);
				modelMatrixU.SetValue(modelMatrix);

				modelMatrix.m[12] = 0.f;
				modelMatrix.m[13] = 0.f;
				modelMatrix.m[14] = 0.f;
				static GLProgramUniform modelNormalMatrix("modelNormalMatrix");
				modelNormalMatrix(shadowMapProgram);
				modelNormalMatrix.SetValue(modelMatrix);

				device->DrawElements(IGLDevice::Triangles, numIndices, IGLDevice::UnsignedInt,
				                     (void *)0);
			}

			device->BindBuffer(IGLDevice::ElementArrayBuffer, 0);

			device->EnableVertexAttribArray(positionAttribute(), false);
			if (normalAttribute() != -1)
				device->EnableVertexAttribArray(normalAttribute(), false);

			device->ActiveTexture(0);
			device->BindTexture(IGLDevice::Texture2D, 0);
		}
Example #20
0
		void Player::SetVelocity(const spades::Vector3 &v) {
			SPADES_MARK_FUNCTION();
			
			velocity = v;
		}
Example #21
0
		void GLVoxelModel::RenderDynamicLightPass(std::vector<client::ModelRenderParam> params,
		                                          std::vector<GLDynamicLight> lights) {
			SPADES_MARK_FUNCTION();

			device->ActiveTexture(0);

			device->Enable(IGLDevice::CullFace, true);
			device->Enable(IGLDevice::DepthTest, true);

			dlightProgram->Use();

			static GLDynamicLightShader dlightShader;

			static GLProgramUniform fogDistance("fogDistance");
			fogDistance(dlightProgram);
			fogDistance.SetValue(renderer->GetFogDistance());

			static GLProgramUniform modelOrigin("modelOrigin");
			modelOrigin(dlightProgram);
			modelOrigin.SetValue(origin.x, origin.y, origin.z);

			static GLProgramUniform sunLightDirection("sunLightDirection");
			sunLightDirection(dlightProgram);
			Vector3 sunPos = MakeVector3(0, -1, -1);
			sunPos = sunPos.Normalize();
			sunLightDirection.SetValue(sunPos.x, sunPos.y, sunPos.z);

			static GLProgramUniform viewOriginVector("viewOriginVector");
			viewOriginVector(dlightProgram);
			const auto &viewOrigin = renderer->GetSceneDef().viewOrigin;
			viewOriginVector.SetValue(viewOrigin.x, viewOrigin.y, viewOrigin.z);

			// setup attributes
			static GLProgramAttribute positionAttribute("positionAttribute");
			static GLProgramAttribute colorAttribute("colorAttribute");
			static GLProgramAttribute normalAttribute("normalAttribute");

			positionAttribute(dlightProgram);
			colorAttribute(dlightProgram);
			normalAttribute(dlightProgram);

			device->BindBuffer(IGLDevice::ArrayBuffer, buffer);
			device->VertexAttribPointer(positionAttribute(), 4, IGLDevice::UnsignedByte, false,
			                            sizeof(Vertex), (void *)0);
			device->VertexAttribPointer(colorAttribute(), 4, IGLDevice::UnsignedByte, true,
			                            sizeof(Vertex), (void *)8);
			device->VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false,
			                            sizeof(Vertex), (void *)12);
			device->BindBuffer(IGLDevice::ArrayBuffer, 0);

			device->EnableVertexAttribArray(positionAttribute(), true);
			device->EnableVertexAttribArray(colorAttribute(), true);
			device->EnableVertexAttribArray(normalAttribute(), true);

			device->BindBuffer(IGLDevice::ElementArrayBuffer, idxBuffer);

			for (size_t i = 0; i < params.size(); i++) {
				const client::ModelRenderParam &param = params[i];

				// frustrum cull
				float rad = radius;
				rad *= param.matrix.GetAxis(0).GetLength();
				if (!renderer->SphereFrustrumCull(param.matrix.GetOrigin(), rad)) {
					continue;
				}

				static GLProgramUniform customColor("customColor");
				customColor(dlightProgram);
				customColor.SetValue(param.customColor.x, param.customColor.y, param.customColor.z);

				Matrix4 modelMatrix = param.matrix;
				static GLProgramUniform projectionViewModelMatrix("projectionViewModelMatrix");
				projectionViewModelMatrix(dlightProgram);
				projectionViewModelMatrix.SetValue(renderer->GetProjectionViewMatrix() *
				                                   modelMatrix);

				static GLProgramUniform viewModelMatrix("viewModelMatrix");
				viewModelMatrix(dlightProgram);
				viewModelMatrix.SetValue(renderer->GetViewMatrix() * modelMatrix);

				static GLProgramUniform modelMatrixU("modelMatrix");
				modelMatrixU(dlightProgram);
				modelMatrixU.SetValue(modelMatrix);

				modelMatrix.m[12] = 0.f;
				modelMatrix.m[13] = 0.f;
				modelMatrix.m[14] = 0.f;
				static GLProgramUniform modelNormalMatrix("modelNormalMatrix");
				modelNormalMatrix(dlightProgram);
				modelNormalMatrix.SetValue(modelMatrix);

				if (param.depthHack) {
					device->DepthRange(0.f, 0.1f);
				}
				for (size_t i = 0; i < lights.size(); i++) {
					if (!GLDynamicLightShader::SphereCull(lights[i], param.matrix.GetOrigin(), rad))
						continue;

					dlightShader(renderer, dlightProgram, lights[i], 0);

					device->DrawElements(IGLDevice::Triangles, numIndices, IGLDevice::UnsignedInt,
					                     (void *)0);
				}
				if (param.depthHack) {
					device->DepthRange(0.f, 1.f);
				}
			}

			device->BindBuffer(IGLDevice::ElementArrayBuffer, 0);

			device->EnableVertexAttribArray(positionAttribute(), false);
			device->EnableVertexAttribArray(colorAttribute(), false);
			device->EnableVertexAttribArray(normalAttribute(), false);

			device->ActiveTexture(0);
		}
Example #22
0
		void Player::SetOrientation(const spades::Vector3 &v) {
			SPADES_MARK_FUNCTION();
			
			orientation = v;
		}
Example #23
0
int main(int argc, char ** argv)
{
#ifdef WIN32
	SetUnhandledExceptionFilter( UnhandledExceptionProc );
#endif

	for(int i = 1; i < argc;) {
			int ret = argsHandler(argc, argv, i);
			if(!ret) {
				// ignore unknown arg
				i++;
			}
		}

		if ( cg_printVersion ) {
			printf( "%s\n", PACKAGE_STRING );
			return 0;
		}

		if ( cg_printHelp ) {
			printHelp( argv[0] );
			return 0;
		}


	std::unique_ptr<SplashWindow> splashWindow;

	try{

		// start recording backtrace
		spades::reflection::Backtrace::StartBacktrace();
		SPADES_MARK_FUNCTION();

		// show splash window
		// NOTE: splash window uses image loader, which assumes backtrace is already initialized.
		splashWindow.reset(new SplashWindow());
		auto showSplashWindowTime = SDL_GetTicks();
		auto pumpEvents = [&splashWindow] { splashWindow->PumpEvents(); };

		// initialize threads
		spades::Thread::InitThreadSystem();
		spades::DispatchQueue::GetThreadQueue()->MarkSDLVideoThread();

		SPLog("Package: " PACKAGE_STRING);
		// setup user-specific default resource directories
#ifdef WIN32
		static wchar_t buf[4096];
		GetModuleFileNameW(NULL, buf, 4096);
		std::wstring appdir = buf;
		appdir = appdir.substr(0, appdir.find_last_of(L'\\')+1);

		if(SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, buf))){
			std::wstring datadir = buf;
			datadir += L"\\OpenSpades\\Resources";
			spades::FileManager::AddFileSystem(new spades::DirectoryFileSystem(Utf8FromWString(datadir.c_str()), true));
		}
		
		spades::FileManager::AddFileSystem(new spades::DirectoryFileSystem(Utf8FromWString((appdir + L"Resources").c_str()), false));
		
		//fltk has a console window on windows (can disable while building, maybe use a builtin console for a later release?)
		HWND hCon = GetConsoleWindow();
		if( NULL != hCon ) {
			setIcon( hCon );
		}

#elif defined(__APPLE__)
		std::string home = getenv("HOME");
		spades::FileManager::AddFileSystem
		(new spades::DirectoryFileSystem("./Resources", false));

		// OS X application is made of Bundle, which contains its own Resources directory.
		{
			char *baseDir = SDL_GetBasePath();
			if(baseDir) {
				spades::FileManager::AddFileSystem
				(new spades::DirectoryFileSystem(baseDir, false));
				SDL_free(baseDir);
			}
		}

		spades::FileManager::AddFileSystem
		(new spades::DirectoryFileSystem(home+"/Library/Application Support/OpenSpades/Resources", true));
#else
		std::string home = getenv("HOME");

		spades::FileManager::AddFileSystem
		(new spades::DirectoryFileSystem("./Resources", false));

		spades::FileManager::AddFileSystem(new spades::DirectoryFileSystem(CMAKE_INSTALL_PREFIX "/" OPENSPADES_INSTALL_RESOURCES, false));

		std::string xdg_data_home = home+"/.local/share";

		if (getenv("XDG_DATA_HOME") == NULL) {
			SPLog("XDG_DATA_HOME not defined. Assuming that XDG_DATA_HOME is ~/.local/share");
		}
		else {
			std::string xdg_data_home = getenv("XDG_DATA_HOME");
			SPLog("XDG_DATA_HOME is %s", xdg_data_home.c_str());
		}

		struct stat info;

		if ( stat((xdg_data_home+"/openspades").c_str(), &info ) != 0 ) {
			if ( stat((home+"/.openspades").c_str(), &info ) != 0) { }
			else if( info.st_mode & S_IFDIR ) {
				SPLog("Openspades directory in XDG_DATA_HOME not found, though old directory exists. Trying to resolve compatibility problem.");

				if (rename( (home+"/.openspades").c_str() , (xdg_data_home+"/openspades").c_str() ) != 0) {
					SPLog("Failed to move old directory to new.");
				} else {
					SPLog("Successfully moved old directory.");

					if (mkdir((home+"/.openspades").c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0) {
						SDL_RWops *io = SDL_RWFromFile((home+"/.openspades/CONTENT_MOVED_TO_NEW_DIR").c_str(), "wb");
						if (io != NULL) {
							const char* text = ("Content of this directory moved to "+xdg_data_home+"/openspades").c_str();
							io->write(io, text, strlen(text), 1);
							io->close(io);
						}
					}
				}
			}
		}

		spades::FileManager::AddFileSystem
		(new spades::DirectoryFileSystem(xdg_data_home+"/openspades/Resources", true));

#endif

		// start log output to SystemMessages.log
		try{
			spades::StartLog();
		}catch(const std::exception& ex){
			SDL_InitSubSystem(SDL_INIT_VIDEO);
			auto msg = spades::Format("Failed to start recording log because of the following error:\n{0}\n\n"
									  "OpenSpades will continue to run, but any critical events are not logged.", ex.what());
			if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING,
										"OpenSpades Log System Failure",
										msg.c_str(), splashWindow->GetWindow())) {
				// showing dialog failed.
			}
		}
		SPLog("Log Started.");

		// load preferences.
		spades::Settings::GetInstance()->Load();
		pumpEvents();

		// dump CPU info (for debugging?)
		{
			spades::CpuID cpuid;
			SPLog("---- CPU Information ----");
			SPLog("Vendor ID: %s", cpuid.GetVendorId().c_str());
			SPLog("Brand ID: %s", cpuid.GetBrand().c_str());
			SPLog("Supports MMX: %s", cpuid.Supports(spades::CpuFeature::MMX)?"YES":"NO");
			SPLog("Supports SSE: %s", cpuid.Supports(spades::CpuFeature::SSE)?"YES":"NO");
			SPLog("Supports SSE2: %s", cpuid.Supports(spades::CpuFeature::SSE2)?"YES":"NO");
			SPLog("Supports SSE3: %s", cpuid.Supports(spades::CpuFeature::SSE3)?"YES":"NO");
			SPLog("Supports SSSE3: %s", cpuid.Supports(spades::CpuFeature::SSSE3)?"YES":"NO");
			SPLog("Supports FMA: %s", cpuid.Supports(spades::CpuFeature::FMA)?"YES":"NO");
			SPLog("Supports AVX: %s", cpuid.Supports(spades::CpuFeature::AVX)?"YES":"NO");
			SPLog("Supports AVX2: %s", cpuid.Supports(spades::CpuFeature::AVX2)?"YES":"NO");
			SPLog("Supports AVX512F: %s", cpuid.Supports(spades::CpuFeature::AVX512F)?"YES":"NO");
			SPLog("Supports AVX512CD: %s", cpuid.Supports(spades::CpuFeature::AVX512CD)?"YES":"NO");
			SPLog("Supports AVX512ER: %s", cpuid.Supports(spades::CpuFeature::AVX512ER)?"YES":"NO");
			SPLog("Supports AVX512PF: %s", cpuid.Supports(spades::CpuFeature::AVX512PF)?"YES":"NO");
			SPLog("Simultaneous Multithreading: %s", cpuid.Supports(spades::CpuFeature::SimultaneousMT)?"YES":"NO");
			SPLog("Misc:");
			SPLog("%s", cpuid.GetMiscInfo().c_str());
			SPLog("-------------------------");
		}

		// register resource directory specified by Makefile (or something)
#if defined(RESDIR_DEFINED)
		spades::FileManager::AddFileSystem(new spades::DirectoryFileSystem(RESDIR, false));
#endif

		// search current file system for .pak files
		{
			std::vector<spades::IFileSystem*> fss;
			std::vector<spades::IFileSystem*> fssImportant;

			std::vector<std::string> files = spades::FileManager::EnumFiles("");

			struct Comparator {
				static int GetPakId(const std::string& str) {
					if(str.size() >= 4 && str[0] == 'p' &&
					   str[1] == 'a' && str[2] == 'k' &&
					   (str[3] >= '0' && str[3] <= '9')){
						return atoi(str.c_str() + 3);
					}else{
						return 32767;
					}
				}
				static bool Compare(const std::string& a,
									const std::string& b) {
					int pa = GetPakId(a);
					int pb = GetPakId(b);
					if(pa == pb){
						return a < b;
					}else{
						return pa < pb;
					}
				}
			};

			std::sort(files.begin(), files.end(), Comparator::Compare);

			for(size_t i = 0; i < files.size(); i++){
				std::string name = files[i];

				// check extension
				if(name.size() < 4 ||
				   name.rfind(".pak") != name.size() - 4){
					continue;
				}

				if(spades::FileManager::FileExists(name.c_str())) {
					spades::IStream *stream = spades::FileManager::OpenForReading(name.c_str());
					spades::ZipFileSystem *fs = new spades::ZipFileSystem(stream);
					if(name[0] == '_' && false) { // last resort for #198
						SPLog("Pak Registered: %s (marked as 'important')\n", name.c_str());
						fssImportant.push_back(fs);
					}else{
						SPLog("Pak Registered: %s\n", name.c_str());
						fss.push_back(fs);
					}
				}
			}
			for(size_t i = fss.size(); i > 0; i--){
				spades::FileManager::AppendFileSystem(fss[i - 1]);
			}
			for(size_t i = 0; i < fssImportant.size(); i++){
				spades::FileManager::PrependFileSystem(fssImportant[i]);
			}
		}
		pumpEvents();

		// initialize localization system
		SPLog("Initializing localization system");
		spades::LoadCurrentLocale();
		_Tr("Main", "Localization System Loaded");
		pumpEvents();

		// parse args

		// initialize AngelScript
		SPLog("Initializing script engine");
		spades::ScriptManager::GetInstance();
		pumpEvents();

		ThreadQuantumSetter quantumSetter;
		(void)quantumSetter; // suppress "unused variable" warning

		SDL_InitSubSystem(SDL_INIT_VIDEO);

		// we want to show splash window at least for some time...
		pumpEvents();
		auto ticks = SDL_GetTicks();
		if(ticks < showSplashWindowTime + 1500) {
			SDL_Delay(showSplashWindowTime + 1500 - ticks);
		}
		pumpEvents();

		// everything is now ready!
		if( !cg_autoConnect ) {
			if(!((int)cl_showStartupWindow != 0 ||
				 splashWindow->IsStartupScreenRequested())) {
				splashWindow.reset();

				SPLog("Starting main screen");
				spades::StartMainScreen();
			}else{
				splashWindow.reset();

				SPLog("Starting startup window");
				::spades::gui::StartupScreen::Run();
			}
		} else {
			splashWindow.reset();

			spades::ServerAddress host(cg_lastQuickConnectHost.CString(), (int)cg_protocolVersion == 3 ? spades::ProtocolVersion::v075 : spades::ProtocolVersion::v076 );
			spades::StartClient(host, cg_playerName);
		}

		spades::Settings::GetInstance()->Flush();

	}catch(const ExitRequestException&){
		// user changed his mind.
	}catch(const std::exception& ex) {

		try {
			splashWindow.reset(nullptr);
		}catch(...){
		}

		std::string msg = ex.what();
		msg = _Tr("Main", "A serious error caused OpenSpades to stop working:\n\n{0}\n\nSee SystemMessages.log for more details.", msg);

		SPLog("[!] Terminating due to the fatal error: %s", ex.what());

		SDL_InitSubSystem(SDL_INIT_VIDEO);
		if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, _Tr("Main", "OpenSpades Fatal Error").c_str(), msg.c_str(), nullptr)) {
			// showing dialog failed.
			// TODO: do appropriate action
		}

	}

    return 0;
}
Example #24
0
		void Player::Update(float dt) {
			SPADES_MARK_FUNCTION();
			auto* listener = world->GetListener();
			
			MovePlayer(dt);
			
			if(!IsAlive()) {
				// do death cleanup
				blockCursorDragging = false;
			}
			
			if(tool == ToolSpade){
				if(weapInput.primary){
					if(world->GetTime() > nextSpadeTime){
						UseSpade();
						nextSpadeTime = world->GetTime() + GetToolPrimaryDelay();
					}
				}else if(weapInput.secondary){
					if(world->GetTime() > nextDigTime){
						DigWithSpade();
						nextDigTime = world->GetTime() + GetToolSecondaryDelay();
						firstDig = false;
					}
				}
			}else if(tool == ToolBlock && IsLocalPlayer()){
				GameMap::RayCastResult result;
				auto *map = GetWorld()->GetMap();
				result = map->CastRay2(GetEye(), GetFront(), 12);
				canPending = false;
				
				if(blockCursorDragging) {
					// check the starting point is not floating
					auto start = blockCursorDragPos;
					if(map->IsSolidWrapped(start.x-1, start.y, start.z) ||
					   map->IsSolidWrapped(start.x, start.y-1, start.z) ||
					   map->IsSolidWrapped(start.x, start.y, start.z-1) ||
					   map->IsSolidWrapped(start.x+1, start.y, start.z) ||
					   map->IsSolidWrapped(start.x, start.y+1, start.z) ||
					   map->IsSolidWrapped(start.x, start.y, start.z+1)) {
						// still okay
					}else{
						// cannot build; floating
						if(listener &&
						   this == world->GetLocalPlayer()) {
							listener->
							LocalPlayerBuildError(BuildFailureReason::InvalidPosition);
						}
						blockCursorDragging = false;
					}
				}
				
				if(result.hit &&
				   (result.hitBlock + result.normal).z < 62 &&
				   (!OverlapsWithOneBlock(result.hitBlock + result.normal)) &&
				   BoxDistanceToBlock(result.hitBlock + result.normal) < 3.f &&
				   !pendingPlaceBlock){
					
					// Building is possible, and there's no delayed block placement.
					blockCursorActive = true;
					blockCursorPos = result.hitBlock + result.normal;
					
				}else if(pendingPlaceBlock){
					
					// Delayed Block Placement: When player attempts to place a block while jumping and
					// placing block is currently impossible, building will be delayed until it becomes
					// possible, as long as player is airborne.
					if(airborne == false || blockStocks <= 0){
						// player is no longer airborne, or doesn't have a block to place.
						pendingPlaceBlock = false;
						lastSingleBlockBuildSeqDone = true;
						if(blockStocks > 0) {
							// cannot build; invalid position.
						}
					}else if((!OverlapsWithOneBlock(pendingPlaceBlockPos)) &&
							 BoxDistanceToBlock(pendingPlaceBlockPos) < 3.f){
						// now building became possible.
						SPAssert(this == world->GetLocalPlayer());
						
						if(GetWorld()->GetListener())
							GetWorld()->GetListener()->LocalPlayerBlockAction(pendingPlaceBlockPos, BlockActionCreate);
						
						pendingPlaceBlock = false;
						lastSingleBlockBuildSeqDone = true;
						// blockStocks--; decrease when created
						
						nextBlockTime = world->GetTime() + GetToolPrimaryDelay();
					}
					
				}else{
					// Delayed Block Placement can be activated only when the only reason making placement
					// impossible is that block to be placed overlaps with the player's hitbox.
					canPending = result.hit &&
								 (result.hitBlock + result.normal).z < 62 &&
								 BoxDistanceToBlock(result.hitBlock + result.normal) < 3.f;
					
					blockCursorActive = false;
					int dist = 11;
					for(; dist >= 1 &&
						BoxDistanceToBlock(result.hitBlock + result.normal) > 3.f ; dist--) {
						result = GetWorld()->GetMap()->CastRay2(GetEye(),
																GetFront(),
																dist);
					}
					for(; dist < 12 &&
						BoxDistanceToBlock(result.hitBlock + result.normal) < 3.f ; dist++) {
						result = GetWorld()->GetMap()->CastRay2(GetEye(),
																GetFront(),
																dist);
					}
					
					blockCursorPos = result.hitBlock + result.normal;
				}
				
			}else if(tool == ToolWeapon){
			}else if(tool == ToolGrenade){
				if(holdingGrenade){
					if(world->GetTime() - grenadeTime > 2.9f){
						ThrowGrenade();
					}
				}
			}
		
			if(tool != ToolWeapon)
				weapon->SetShooting(false);
			if(weapon->FrameNext(dt)){
				FireWeapon();
			}
			
			if(weapon->IsReloading()) {
				lastReloadingTime = world->GetTime();
			}else if(reloadingServerSide) {
				// for some reason a server didn't return
				// WeaponReload packet.
				if(world->GetTime() + lastReloadingTime + .8f) {
					reloadingServerSide = false;
					weapon->ForceReloadDone();
				}
			}
		}
Example #25
0
Bitmap::~Bitmap() {
    SPADES_MARK_FUNCTION();

    if(autoDelete)
        delete[] pixels;
}
Example #26
0
		void Player::FireWeapon() {
			SPADES_MARK_FUNCTION();
			
			Vector3 muzzle = GetEye();
			muzzle += GetFront() * 0.01f;
			
			// for hit-test debugging
			std::map<int, HitTestDebugger::PlayerHit> playerHits;
			std::vector<Vector3> bulletVectors;
			
			//Vector3 right = GetRight();
			//Vector3 up = GetUp();
			
			int pellets = weapon->GetPelletSize();
			float spread = weapon->GetSpread();
			GameMap *map = world->GetMap();
			
			// pyspades takes destroying more than one block as a
			// speed hack (shotgun does this)
			bool blockDestroyed = false;
			
			Vector3 dir2 = GetFront();
			for(int i =0 ; i < pellets; i++){
				
				// AoS 0.75's way (dir2 shouldn't be normalized!)
				dir2.x += (GetRandom() - GetRandom()) * spread;
				dir2.y += (GetRandom() - GetRandom()) * spread;
				dir2.z += (GetRandom() - GetRandom()) * spread;
				Vector3 dir = dir2.Normalize();
				
				bulletVectors.push_back(dir);
				
				// first do map raycast
				GameMap::RayCastResult mapResult;
				mapResult = map->CastRay2(muzzle,
										  dir,
										  500);
				
				Player *hitPlayer = NULL;
				float hitPlayerDistance = 0.f;
				HitBodyPart hitPart = HitBodyPart::None;
				
				for(int i = 0; i < world->GetNumPlayerSlots(); i++){
					Player *other = world->GetPlayer(i);
					if(other == this || other == NULL)
						continue;
					if(other == this || !other->IsAlive() ||
					   other->GetTeamId() >= 2)
						continue;
					// quickly reject players unlikely to be hit
					if(!other->RayCastApprox(muzzle, dir))
						continue;
					
					HitBoxes hb = other->GetHitBoxes();
					Vector3 hitPos;
					
					if(hb.head.RayCast(muzzle, dir, &hitPos)) {
						float dist = (hitPos - muzzle).GetLength();
						if(hitPlayer == NULL ||
						   dist < hitPlayerDistance){
							hitPlayer = other;
							hitPlayerDistance = dist;
							hitPart = HitBodyPart::Head;
						}
					}
					if(hb.torso.RayCast(muzzle, dir, &hitPos)) {
						float dist = (hitPos - muzzle).GetLength();
						if(hitPlayer == NULL ||
						   dist < hitPlayerDistance){
							hitPlayer = other;
							hitPlayerDistance = dist;
							hitPart = HitBodyPart::Torso;
						}
					}
					for(int j = 0; j < 3 ;j++){
						if(hb.limbs[j].RayCast(muzzle, dir, &hitPos)) {
							float dist = (hitPos - muzzle).GetLength();
							if(hitPlayer == NULL ||
							   dist < hitPlayerDistance){
								hitPlayer = other;
								hitPlayerDistance = dist;
								switch(j) {
									case 0: hitPart = HitBodyPart::Limb1; break;
									case 1: hitPart = HitBodyPart::Limb2; break;
									case 2: hitPart = HitBodyPart::Arms;  break;
								}
							}
						}
					}
				}
				
				Vector3 finalHitPos;
				finalHitPos = muzzle + dir * 128.f;
				
				if(hitPlayer == nullptr && !mapResult.hit) {
					// might hit water surface.
					
				}
				
				if(mapResult.hit && (mapResult.hitPos - muzzle).GetLength() < 128.f &&
				   (hitPlayer == NULL || (mapResult.hitPos - muzzle).GetLength() < hitPlayerDistance)){
					IntVector3 outBlockCoord = mapResult.hitBlock;
					// TODO: set correct ray distance
					// FIXME: why ray casting twice?
					
					finalHitPos = mapResult.hitPos;
					
					if(outBlockCoord.x >= 0 && outBlockCoord.y >= 0 && outBlockCoord.z >= 0 &&
					   outBlockCoord.x < map->Width() && outBlockCoord.y < map->Height() &&
					   outBlockCoord.z < map->Depth()){
						if(outBlockCoord.z == 63) {
							if(world->GetListener())
								world->GetListener()->BulletHitBlock(mapResult.hitPos,
																	 mapResult.hitBlock,
																	 mapResult.normal);
						}else if(outBlockCoord.z == 62) {
							// blocks at this level cannot be damaged
							if(world->GetListener())
								world->GetListener()->BulletHitBlock(mapResult.hitPos,
																	 mapResult.hitBlock,
																	 mapResult.normal);
						}else{
							int x = outBlockCoord.x;
							int y = outBlockCoord.y;
							int z = outBlockCoord.z;
							SPAssert(map->IsSolid(x, y, z));
							
							Vector3 blockF = {x + .5f, y + .5f, z + .5f};
							float distance = (blockF - muzzle).GetLength();
							
							uint32_t color = map->GetColor(x, y, z);
							int health = color >> 24;
							health -= weapon->GetDamage(HitTypeBlock, distance);
							if(health <= 0 && !blockDestroyed){
								health = 0;
								blockDestroyed = true;
								//send destroy cmd
								if(world->GetListener() &&
								   world->GetLocalPlayer() == this)
									world->GetListener()->LocalPlayerBlockAction
									(outBlockCoord, BlockActionTool);
								
							}
							color = (color & 0xffffff) | ((uint32_t)health << 24);
							if(map->IsSolid(x, y, z))
								map->Set(x, y, z, true, color);
							
							if(world->GetListener())
								world->GetListener()->BulletHitBlock(mapResult.hitPos,
																	 mapResult.hitBlock,
																	 mapResult.normal);
						}
					}
			    }else if(hitPlayer != NULL){
Example #27
0
	StdStream::StdStream(FILE *f, bool ac) : handle(f), autoClose(ac) {
		SPADES_MARK_FUNCTION();

		if (!f)
			SPInvalidArgument("f");
	}
		GLProgramManager::GLProgramManager(IGLDevice *d,
										   IGLShadowMapRenderer *smr,
                                           GLSettings &settings):
		device(d), shadowMapRenderer(smr), settings(settings) {
			SPADES_MARK_FUNCTION();
		}
		GLColorBuffer GLLensDustFilter::Filter(GLColorBuffer input) {
			SPADES_MARK_FUNCTION();
			
			UpdateNoise();
			
			std::vector<Level> levels;
			
			IGLDevice *dev = renderer->GetGLDevice();
			GLQuadRenderer qr(dev);
			
			static GLProgramAttribute thruPosition("positionAttribute");
			static GLProgramUniform thruColor("colorUniform");
			static GLProgramUniform thruTexture("mainTexture");
			static GLProgramUniform thruTexCoordRange("texCoordRange");
			
			thruPosition(thru);
			thruColor(thru);
			thruTexture(thru);
			thruTexCoordRange(thru);
						
			GLColorBuffer downSampled = DownSample(input, r_hdr ? false : true);
            downSampled = GaussianBlur(downSampled, false);
            downSampled = GaussianBlur(downSampled, true);
			
			thru->Use();
			thruColor.SetValue(1.f, 1.f, 1.f, 1.f);
			thruTexture.SetValue(0);
			dev->Enable(IGLDevice::Blend, false);
			
			levels.reserve(10);
			
			// create downsample levels
			for(int i = 0; i < 10; i++){
				GLColorBuffer prevLevel;
				if(i == 0){
					prevLevel = downSampled;
				}else{
					prevLevel = levels.back().buffer;
				}
				
				int prevW = prevLevel.GetWidth();
				int prevH = prevLevel.GetHeight();
				int newW = (prevW + 1) / 2;
				int newH = (prevH + 1) / 2;
				if(newW <= 1 || newH <= 1)
					break;
                GLColorBuffer newLevel = DownSample(prevLevel);
                newLevel = GaussianBlur(newLevel, false);
                newLevel = GaussianBlur(newLevel, true);
				
				Level lv;
				lv.w = newW; lv.h = newH;
				lv.buffer = newLevel;
				levels.push_back(lv);
			}
			
			dev->Enable(IGLDevice::Blend, true);
			dev->BlendFunc(IGLDevice::SrcAlpha,
						   IGLDevice::OneMinusSrcAlpha);
			
			// composite levels in the opposite direction
			thru->Use();
			qr.SetCoordAttributeIndex(thruPosition());
			for(int i = (int)levels.size() - 1; i >= 1; i--){
				int cnt = (int)levels.size() - i;
				float alpha = (float)cnt / (float)(cnt + 1);
                alpha = alpha;
				
				GLColorBuffer curLevel = levels[i].buffer;
				
				float sx = .25f / curLevel.GetWidth();
				float sy = .25f / curLevel.GetHeight();
				
				for(int j = 0; j < 4; j++) {
					if(i < (int)levels.size() - 1) {
						curLevel = levels[i].retBuf[j];
					}
					GLColorBuffer targLevel = levels[i - 1].buffer;
					GLColorBuffer targRet = input.GetManager()->CreateBufferHandle(targLevel.GetWidth(),
																	   targLevel.GetHeight(),
																	   false);
					levels[i - 1].retBuf[j] = targRet;
					
					dev->BindFramebuffer(IGLDevice::Framebuffer, targRet.GetFramebuffer());
					dev->Viewport(0, 0, targRet.GetWidth(), targRet.GetHeight());
					
					dev->BindTexture(IGLDevice::Texture2D, targLevel.GetTexture());
					thruColor.SetValue(1.f, 1.f, 1.f, 1.f);
					thruTexCoordRange.SetValue(0.f, 0.f, 1.f, 1.f);
					dev->Enable(IGLDevice::Blend, false);
					qr.Draw();
					
					float cx = 0.f, cy = 0.f;
					switch(j){
						case 0: cx = sx; break;
						case 1: cx = -sx; break;
						case 2: cy = sy; break;
						case 3: cy = -sy; break;
					}
					
					dev->BindTexture(IGLDevice::Texture2D, curLevel.GetTexture());
					thruColor.SetValue(1.f, 1.f, 1.f, alpha);
					thruTexCoordRange.SetValue(cx, cy, 1.f, 1.f);
					dev->Enable(IGLDevice::Blend, true);
					qr.Draw();
					
					dev->BindTexture(IGLDevice::Texture2D, 0);
				}
				
			}
			
			static GLProgramAttribute dustPosition("positionAttribute");
			static GLProgramUniform dustDustTexture("dustTexture");
			static GLProgramUniform dustBlurTexture1("blurTexture1");
			static GLProgramUniform dustBlurTexture2("blurTexture2");
			static GLProgramUniform dustBlurTexture3("blurTexture3");
			static GLProgramUniform dustBlurTexture4("blurTexture4");
			static GLProgramUniform dustInputTexture("inputTexture");
			static GLProgramUniform dustNoiseTexture("noiseTexture");
			static GLProgramUniform dustNoiseTexCoordFactor("noiseTexCoordFactor");
			
			dustPosition(dust);
			dustDustTexture(dust);
			dustBlurTexture1(dust);
			dustBlurTexture2(dust);
			dustBlurTexture3(dust);
			dustBlurTexture4(dust);
			dustInputTexture(dust);
			dustNoiseTexture(dust);
			dustNoiseTexCoordFactor(dust);
			
			dust->Use();
			
			float facX = renderer->ScreenWidth() / 128.f;
			float facY = renderer->ScreenHeight() / 128.f;
			dustNoiseTexCoordFactor.SetValue(facX, facY,
											 facX / 128.f,
											 facY / 128.f);
			
			// composite to the final image
			GLColorBuffer output = input.GetManager()->CreateBufferHandle();
			GLColorBuffer topLevel1 = levels[0].retBuf[0];
			GLColorBuffer topLevel2 = levels[0].retBuf[1];
			GLColorBuffer topLevel3 = levels[0].retBuf[2];
			GLColorBuffer topLevel4 = levels[0].retBuf[3];
			
			qr.SetCoordAttributeIndex(dustPosition());
			dev->ActiveTexture(0);
			dev->BindTexture(IGLDevice::Texture2D, input.GetTexture());
			dev->ActiveTexture(1);
			dev->BindTexture(IGLDevice::Texture2D, topLevel1.GetTexture());
			dev->ActiveTexture(2);
			dev->BindTexture(IGLDevice::Texture2D, topLevel2.GetTexture());
			dev->ActiveTexture(3);
			dev->BindTexture(IGLDevice::Texture2D, topLevel3.GetTexture());
			dev->ActiveTexture(4);
			dev->BindTexture(IGLDevice::Texture2D, topLevel4.GetTexture());
			dev->ActiveTexture(5);
			dustImg->Bind(IGLDevice::Texture2D);
			dev->ActiveTexture(6);
			dev->BindTexture(IGLDevice::Texture2D, noiseTex);
			dev->BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer());
			dev->Viewport(0, 0, output.GetWidth(), output.GetHeight());
			dustBlurTexture1.SetValue(2);
			dustBlurTexture2.SetValue(1);
			dustBlurTexture3.SetValue(3);
			dustBlurTexture4.SetValue(4);
			dustDustTexture.SetValue(5);
			dustNoiseTexture.SetValue(6);
			dustInputTexture.SetValue(0);
			qr.Draw();
			dev->BindTexture(IGLDevice::Texture2D, 0);
			
			dev->ActiveTexture(0);
			
			return output;
		}
		void GLSoftLitSpriteRenderer::Render() {
			SPADES_MARK_FUNCTION();
			
			if(sprites.empty())
				return;
			
			// light every sprite
			const std::vector<GLDynamicLight>& lights = renderer->lights;
			for(size_t i = 0; i < sprites.size(); i++){
				Sprite& spr = sprites[i];
				if(spr.color.w < .0001f) {
					// maybe emissive sprite...
					spr.emission = spr.color.GetXYZ();
					spr.color = MakeVector4(0.f, 0.f, 0.f, 0.f);
				}else{
					spr.emission = MakeVector3(0.f, 0.f, 0.f);
				}
				
				spr.dlR = MakeVector4(0, 0, 0, 0);
				spr.dlG = MakeVector4(0, 0, 0, 0);
				spr.dlB = MakeVector4(0, 0, 0, 0);
				
			}
			
			for(size_t j = 0; j < lights.size(); j++) {
				const GLDynamicLight& l = lights[j];
				const client::DynamicLightParam& dl = l.GetParam();
				float spotTan = dl.type == client::DynamicLightTypeSpotlight ? tanf(dl.spotAngle * .5f) : 0.;
				for(size_t i = 0; i < sprites.size(); i++){
					Sprite& spr = sprites[i];
				
					Vector3 v = dl.origin - spr.center;
					float effectiveRadius = spr.radius + dl.radius;
					
					if(v.GetChebyshevLength() > effectiveRadius)
						continue;
					float powdist = v.GetPoweredLength();
					if(powdist > effectiveRadius * effectiveRadius)
						continue;
					float att = 1.f - powdist / (effectiveRadius * effectiveRadius);
					float unif;
					float directionalFactor = 1.f;
					unif = 1.f - powdist / (spr.radius * spr.radius);
					unif = std::max(.2f, unif);
					
					if(dl.type == client::DynamicLightTypeSpotlight) {
						float forward = Vector3::Dot(v, dl.spotAxis[2]);
						if(forward > spr.radius) {
							continue;
						}else if(forward >= -spr.radius){
							att *= .5f - (forward / spr.radius) * .5f;
							directionalFactor = 1.f;
						}else{
							float cx = Vector3::Dot(spr.center - dl.origin, dl.spotAxis[0]);
							float cy = Vector3::Dot(spr.center - dl.origin, dl.spotAxis[1]);
							float sq = sqrtf(cx * cx + cy * cy);
							float sprTan = spr.radius / (-spr.radius - forward);
							float eff = sprTan + spotTan;
							sq /= -forward;
							if(sq > eff){
								continue;
							}
							if(sq > eff - spotTan){
								att *= (eff - sq) / spotTan;
							}
						}
						
					}
					
					Vector4 final;
					
					if(unif < .9999f) {
						Vector3 directional = v;
						directional *= att * directionalFactor * (1.f - unif) / sqrtf(powdist);
						final.x = directional.x;
						final.y = directional.y;
						final.z = directional.z;