ParticleSpriteEntity::ParticleSpriteEntity(Client *cli, IImage *image, Vector4 color):
		image(image), color(color)
		{
			position = MakeVector3(0,0,0);
			velocity = MakeVector3(0, 0, 0);
			radius = 1.f;
			radiusVelocity = 0.f;
			angle = 0.f;
			rotationVelocity = 0.f;
			velocityDamp = 1;
			gravityScale = 1.f;
			lifetime = 1.f;
			radiusDamp = 1.f;
			time = 0.f;
			fadeInDuration = .1f;
			fadeOutDuration = .5f;
			additive = false;
			blockHitAction = Delete;
			
			renderer = cli->GetRenderer();
			if(cli->GetWorld())
			map = cli->GetWorld()->GetMap();
			else
				map = NULL;
		}
Example #2
0
		GunCasing::GunCasing(Client *client,
							 IModel *model,
							 IAudioChunk *dropSound,
							 IAudioChunk *waterSound,
				  Vector3 pos,
				  Vector3 dir,
							 Vector3 flyDir):
		client(client),
		renderer(client->GetRenderer()), model(model),
		dropSound(dropSound), waterSound(waterSound){
			
			if(dropSound)
				dropSound->AddRef();
			if(waterSound)
				waterSound->AddRef();
			
			Vector3 up = MakeVector3(0, 0, 1);
			Vector3 right = Vector3::Cross(dir, up).Normalize();
			up = Vector3::Cross(right, dir);
			
			matrix = Matrix4::FromAxis(right, dir, up, pos);
			
			up = MakeVector3(0, 0, -1);
			rotAxis=Vector3::Cross(up, flyDir.Normalize());
			
			groundTime = 0.f;
			onGround = false;
			vel = flyDir * 10.f;
			rotSpeed = 40.f;
		}
Example #3
0
	Vector3 Matrix4::GetAxis(int axis) const {
		switch (axis) {
			case 0: return MakeVector3(m[0], m[1], m[2]);
			case 1: return MakeVector3(m[4], m[5], m[6]);
			default: SPAssert(false);
			case 2: return MakeVector3(m[8], m[9], m[10]);
		}
	}
Example #4
0
		void Corpse::SetNode(NodeType n, spades::Vector3 v){
			SPAssert(n >= 0); SPAssert(n < NodeCount);
			nodes[n].pos = v;
			nodes[n].vel = MakeVector3(VelNoise(),
									   VelNoise(),
									   0.f);
			nodes[n].lastPos = v;
			nodes[n].lastForce = MakeVector3(0, 0,0);
			
		}
Example #5
0
		void Client::PlayerHitBlockWithSpade(spades::client::Player *p, Vector3 hitPos,
		                                     IntVector3 blockPos, IntVector3 normal) {
			SPADES_MARK_FUNCTION();

			uint32_t col = map->GetColor(blockPos.x, blockPos.y, blockPos.z);
			IntVector3 colV = {(uint8_t)col, (uint8_t)(col >> 8), (uint8_t)(col >> 16)};
			Vector3 shiftedHitPos = hitPos;
			shiftedHitPos.x += normal.x * .05f;
			shiftedHitPos.y += normal.y * .05f;
			shiftedHitPos.z += normal.z * .05f;

			EmitBlockFragments(shiftedHitPos, colV);

			if (p == world->GetLocalPlayer()) {
				localFireVibrationTime = time;
			}

			if (!IsMuted()) {
				bool isLocal = p == world->GetLocalPlayer();
				Handle<IAudioChunk> c =
				  audioDevice->RegisterSound("Sounds/Weapons/Spade/HitBlock.opus");
				if (isLocal)
					audioDevice->PlayLocal(c, MakeVector3(.1f, -.1f, 1.2f), AudioParam());
				else
					audioDevice->Play(c, p->GetOrigin() + p->GetFront() * 0.5f - p->GetUp() * .2f,
					                  AudioParam());
			}
		}
Example #6
0
		void Client::LocalPlayerPulledGrenadePin() {
			SPADES_MARK_FUNCTION();

			if (!IsMuted()) {
				Handle<IAudioChunk> c =
				  audioDevice->RegisterSound("Sounds/Weapons/Grenade/Fire.opus");
				audioDevice->PlayLocal(c, MakeVector3(.4f, -.3f, .5f), AudioParam());
			}
		}
Example #7
0
	bool PlaneCullTest(const Plane3& plane, const AABB3& box){
		Vector3 testVertex;
		// find the vertex with the greatest distance value
		if(plane.n.x >= 0.f){
			if(plane.n.y >= 0.f){
				if(plane.n.z >= 0.f){
					testVertex = box.max;
				}else{
					testVertex = MakeVector3(box.max.x, box.max.y, box.min.z);
				}
			}else{
				if(plane.n.z >= 0.f){
					testVertex = MakeVector3(box.max.x, box.min.y, box.max.z);
				}else{
					testVertex = MakeVector3(box.max.x, box.min.y, box.min.z);
				}
			}
		}else{
			if(plane.n.y >= 0.f){
				if(plane.n.z >= 0.f){
					testVertex = MakeVector3(box.min.x, box.max.y, box.max.z);
				}else{
					testVertex = MakeVector3(box.min.x, box.max.y, box.min.z);
				}
			}else{
				if(plane.n.z >= 0.f){
					testVertex = MakeVector3(box.min.x, box.min.y, box.max.z);
				}else{
					testVertex = box.min;
				}
			}
		}
		return plane.GetDistanceTo(testVertex) >= 0.f;
	}
Example #8
0
		void Client::PlayerMissedSpade(spades::client::Player *p) {
			SPADES_MARK_FUNCTION();

			if (!IsMuted()) {
				bool isLocal = p == world->GetLocalPlayer();
				Handle<IAudioChunk> c = audioDevice->RegisterSound("Sounds/Weapons/Spade/Miss.opus");
				if (isLocal)
					audioDevice->PlayLocal(c, MakeVector3(.2f, -.1f, 0.7f), AudioParam());
				else
					audioDevice->Play(c, p->GetOrigin() + p->GetFront() * 0.8f - p->GetUp() * .2f,
					                  AudioParam());
			}
		}
Example #9
0
		void Client::PlayerRestocked(spades::client::Player *p) {
			if (!IsMuted()) {
				bool isLocal = p == world->GetLocalPlayer();
				Handle<IAudioChunk> c =
				  isLocal ? audioDevice->RegisterSound("Sounds/Weapons/RestockLocal.opus")
				          : audioDevice->RegisterSound("Sounds/Weapons/Restock.opus");
				if (isLocal)
					audioDevice->PlayLocal(c, MakeVector3(.4f, -.3f, .5f), AudioParam());
				else
					audioDevice->Play(c, p->GetEye() + p->GetFront() * 0.5f - p->GetUp() * .3f +
					                       p->GetRight() * .4f,
					                  AudioParam());
			}
		}
Example #10
0
		void Client::PlayerDryFiredWeapon(spades::client::Player *p) {
			SPADES_MARK_FUNCTION();

			if (!IsMuted()) {
				bool isLocal = p == world->GetLocalPlayer();
				Handle<IAudioChunk> c = audioDevice->RegisterSound("Sounds/Weapons/DryFire.opus");
				if (isLocal)
					audioDevice->PlayLocal(c, MakeVector3(.4f, -.3f, .5f), AudioParam());
				else
					audioDevice->Play(c, p->GetEye() + p->GetFront() * 0.5f - p->GetUp() * .3f +
					                       p->GetRight() * .4f,
					                  AudioParam());
			}
		}
Example #11
0
		void Client::PlayerThrownGrenade(spades::client::Player *p, Grenade *g) {
			SPADES_MARK_FUNCTION();

			if (!IsMuted()) {
				bool isLocal = p == world->GetLocalPlayer();
				Handle<IAudioChunk> c =
				  audioDevice->RegisterSound("Sounds/Weapons/Grenade/Throw.opus");

				if (g && isLocal) {
					net->SendGrenade(g);
				}

				if (isLocal)
					audioDevice->PlayLocal(c, MakeVector3(.4f, 0.1f, .3f), AudioParam());
				else
					audioDevice->Play(c, p->GetEye() + p->GetFront() * 0.5f - p->GetUp() * .2f +
					                       p->GetRight() * .3f,
					                  AudioParam());
			}
		}
Example #12
0
		void Client::PlayerChangedTool(spades::client::Player *p) {
			SPADES_MARK_FUNCTION();

			if (!IsMuted()) {
				bool isLocal = p == world->GetLocalPlayer();
				Handle<IAudioChunk> c;
				if (isLocal) {
					// played by ClientPlayer::Update
					return;
				} else {
					c = audioDevice->RegisterSound("Sounds/Weapons/Switch.opus");
				}
				if (isLocal)
					audioDevice->PlayLocal(c, MakeVector3(.4f, -.3f, .5f), AudioParam());
				else
					audioDevice->Play(c, p->GetEye() + p->GetFront() * 0.5f - p->GetUp() * .3f +
					                       p->GetRight() * .4f,
					                  AudioParam());
			}
		}
		void GLBasicShadowMapRenderer::BuildMatrix(float near, float far){
			// TODO: variable light direction?
			Vector3 lightDir = MakeVector3(0, -1, -1).Normalize();
			// set better up dir?
			Vector3 up = MakeVector3(0, 0, 1);
			Vector3 side = Vector3::Cross(up, lightDir).Normalize();
			up = Vector3::Cross(lightDir, side).Normalize();
			
			// build frustrum
			client::SceneDefinition def = GetRenderer()->GetSceneDef();
			Vector3 frustrum[8];
			float tanX = tanf(def.fovX * .5f);
			float tanY = tanf(def.fovY * .5f);
			
			frustrum[0] = FrustrumCoord(def, tanX, tanY, near);
			frustrum[1] = FrustrumCoord(def, tanX, -tanY, near);
			frustrum[2] = FrustrumCoord(def, -tanX, tanY, near);
			frustrum[3] = FrustrumCoord(def, -tanX, -tanY, near);
			frustrum[4] = FrustrumCoord(def, tanX, tanY, far);
			frustrum[5] = FrustrumCoord(def, tanX, -tanY, far);
			frustrum[6] = FrustrumCoord(def, -tanX, tanY, far);
			frustrum[7] = FrustrumCoord(def, -tanX, -tanY, far);
			
			// compute frustrum's x,y boundary
			float minX, maxX, minY, maxY;
			minX = maxX = Vector3::Dot(frustrum[0], side);
			minY = maxY = Vector3::Dot(frustrum[0], up);
			for(int i = 1; i < 8; i++){
				float x = Vector3::Dot(frustrum[i], side);
				float y = Vector3::Dot(frustrum[i], up);
				if(x < minX) minX = x;
				if(x > maxX) maxX = x;
				if(y < minY) minY = y;
				if(y > maxY) maxY = y;
			}
			
			// compute frustrum's z boundary
			Segment seg;
			Plane3 plane1(0,0,1,-4.f);
			Plane3 plane2(0,0,1,64.f);
			seg += ZRange(side * minX + up * minY,
						  lightDir, plane1, plane2);
			seg += ZRange(side * minX + up * maxY,
						  lightDir, plane1, plane2);
			seg += ZRange(side * maxX + up * minY,
						  lightDir, plane1, plane2);
			seg += ZRange(side * maxX + up * maxY,
						  lightDir, plane1, plane2);
			
			
			for(int i = 1; i < 8; i++){
				seg += Vector3::Dot(frustrum[i], lightDir);
			}
			
			
			// build frustrum obb
			Vector3 origin = side * minX + up * minY + lightDir * seg.low;
			Vector3 axis1 = side * (maxX - minX);
			Vector3 axis2 = up * (maxY - minY);
			Vector3 axis3 = lightDir * (seg.high - seg.low);
			
			obb = OBB3(Matrix4::FromAxis(axis1, axis2, axis3,
										 origin));
			vpWidth = 2.f / axis1.GetLength();
			vpHeight = 2.f / axis2.GetLength();
		
			// convert to projectionview matrix
			matrix = obb.m.InversedFast();
			
			matrix = Matrix4::Scale(2.f) * matrix;
			matrix = Matrix4::Translate(-1, -1, -1) * matrix;
			
			// scale a little big for padding
			matrix = Matrix4::Scale(.98f) * matrix;
			//
			matrix = Matrix4::Scale(1,1,-1) * matrix;
			
			// make sure frustrums in range
#ifndef NDEBUG
			for(int i = 0; i < 8; i++){
				Vector4 v = matrix * frustrum[i];
				SPAssert(v.x >= -1.f);
				SPAssert(v.y >= -1.f);
				//SPAssert(v.z >= -1.f);
				SPAssert(v.x < 1.f);
				SPAssert(v.y < 1.f);
				//SPAssert(v.z < 1.f);
			}
#endif
		}
Example #14
0
		void SWModelRenderer::RenderInner(spades::draw::SWModel *model,
									 const client::ModelRenderParam &param) {
			auto& mat = param.matrix;
			auto origin = mat.GetOrigin();
			auto axis1 = mat.GetAxis(0);
			auto axis2 = mat.GetAxis(1);
			auto axis3 = mat.GetAxis(2);
			auto *rawModel = model->GetRawModel();
			auto rawModelOrigin = rawModel->GetOrigin();
			rawModelOrigin += 0.1f;
			origin += axis1 * rawModelOrigin.x;
			origin += axis2 * rawModelOrigin.y;
			origin += axis3 * rawModelOrigin.z;
			
			int w = rawModel->GetWidth();
			int h = rawModel->GetHeight();
			//int d = rawModel->GetDepth();
			
			// evaluate brightness for each normals
			uint8_t brights[3*3*3];
			{
				auto lightVec = MakeVector3(0.f, -0.707f, -0.707f);
				float dot1 = Vector3::Dot(axis1, lightVec) * fastRSqrt(axis1.GetPoweredLength());
				float dot2 = Vector3::Dot(axis2, lightVec) * fastRSqrt(axis2.GetPoweredLength());
				float dot3 = Vector3::Dot(axis3, lightVec) * fastRSqrt(axis3.GetPoweredLength());
				for(int x = 0; x < 3; x++){
					float d;
					int cnt;
					switch(x){
						case 0: d = -dot1; cnt = 1; break;
						case 1: d = 0.f; cnt = 0; break;
						case 2: d = dot1; cnt = 1; break;
					}
					for(int y = 0; y < 3; y++){
						auto d2 = d;
						auto cnt2 = cnt;
						switch(y){
							case 0: d2 -= dot2; cnt2++; break;
							case 1: break;
							case 2: d2 += dot2; cnt2++; break;
						}
						for(int z = 0; z < 3; z++) {
							auto d3 = d;
							auto cnt3 = cnt2;
							switch(y){
								case 0: d3 -= dot3; cnt3++; break;
								case 1: break;
								case 2: d3 += dot3; cnt3++; break;
							}
							switch(cnt3){
								case 2:
									d3 *= 0.707f;
									break;
								case 3:
									d3 *= 0.57735f;
									break;
							}
							d3 = 192.f + d3 * 62.f;
							brights[x + y * 3 + z * 9]
							= static_cast<uint8_t>(d3);
						}
					}
				}
			}
				
			
			// compute center coord. for culling
			{
				auto center = origin;
				auto localCenter = model->GetCenter();
				center += axis1 * localCenter.x;
				center += axis2 * localCenter.y;
				center += axis3 * localCenter.z;
				
				float largestAxis = axis1.GetPoweredLength();
				largestAxis = std::max(largestAxis, axis2.GetPoweredLength());
				largestAxis = std::max(largestAxis, axis3.GetPoweredLength());
				
				if(!r->SphereFrustrumCull(center, model->GetRadius() * sqrtf(largestAxis)))
					return;
			}
			
			Bitmap *fbmp = r->fb;
			auto *fb = fbmp->GetPixels();
			int fw = fbmp->GetWidth();
			int fh = fbmp->GetHeight();
			auto *db = r->depthBuffer.data();
			
			Matrix4 viewproj = r->GetProjectionViewMatrix();
			Vector4 ndc2scrscale = {fw * 0.5f, -fh * 0.5f, 1.f, 1.f};
			//Vector4 ndc2scroff = {fw * 0.5f, fh * 0.5f, 0.f, 0.f};
			int ndc2scroffX = fw >> 1;
			int ndc2scroffY = fh >> 1;
			
			
			// render each points
			auto tOrigin = viewproj * MakeVector4(origin.x, origin.y, origin.z, 1.f);
			auto tAxis1 = viewproj * MakeVector4(axis1.x, axis1.y, axis1.z, 0.f);
			auto tAxis2 = viewproj * MakeVector4(axis2.x, axis2.y, axis2.z, 0.f);
			auto tAxis3 = viewproj * MakeVector4(axis3.x, axis3.y, axis3.z, 0.f);
			tOrigin *= ndc2scrscale;
			tAxis1 *= ndc2scrscale;
			tAxis2 *= ndc2scrscale;
			tAxis3 *= ndc2scrscale;
			
			float pointDiameter;// = largestAxis * 0.55f * fh * 0.5f;
			{
				float largestAxis = tAxis1.GetPoweredLength();
				largestAxis = std::max(largestAxis, tAxis2.GetPoweredLength());
				largestAxis = std::max(largestAxis, tAxis3.GetPoweredLength());
				pointDiameter = sqrtf(largestAxis);
			}
			
			uint32_t customColor;
			customColor =
			ToFixed8(param.customColor.z) |
			(ToFixed8(param.customColor.y) << 8) |
			(ToFixed8(param.customColor.x) << 16);
			
			auto v1 = tOrigin;
			float zNear = r->sceneDef.zNear;
			for(int x = 0; x < w; x++) {
				auto v2 = v1;
				for(int y = 0; y < h; y++) {
					auto *mp = &model->renderData
					[model->renderDataAddr[x + y * w]];
					while(*mp != -1) {
						uint32_t data = *(mp++);
						uint32_t normal = *(mp++);
						int z = static_cast<int>(data >> 24);
						//SPAssert(z < d);
						SPAssert(z >= 0);
						
						auto vv = v2 + tAxis3 * zvals[z];
						if(vv.z < zNear) continue;
						
						// save Z value (don't divide this by W!)
						float zval = vv.z;
						
						// use vv.z for point radius to be divided by W
						vv.z = pointDiameter;
						
						// perspective division
						float scl = fastRcp(vv.w);
						vv *= scl;
						
						int ix = static_cast<int>(vv.x) + ndc2scroffX;
						int iy = static_cast<int>(vv.y) + ndc2scroffY;
						int idm = static_cast<int>(vv.z + .99f);
						idm = std::max(1, idm);
						int minX = ix - (idm >> 1);
						int minY = iy - (idm >> 1);
						if(minX >= fw || minY >= fh) continue;
						int maxX = ix + idm;
						int maxY = iy + idm;
						if(maxX <= 0 || maxY <= 0) continue;
						
						minX = std::max(minX, 0);
						minY = std::max(minY, 0);
						maxX = std::min(maxX, fw);
						maxY = std::min(maxY, fh);
						
						auto *fb2 = fb + (minX + minY * fw);
						auto *db2 = db + (minX + minY * fw);
						int w = maxX - minX;
						
						uint32_t color = data & 0xffffff;
						if(color == 0)
							color = customColor;
						
						SPAssert(normal < 27);
						int bright = brights[normal];
#if ENABLE_SSE2
						if(lvl == SWFeatureLevel::SSE2) {
							auto m = _mm_setr_epi32(color, 0, 0, 0);
							auto f = _mm_set1_epi16(bright << 8);
							
							m = _mm_unpacklo_epi8(m, _mm_setzero_si128());
							m = _mm_mulhi_epu16(m, f);
							m = _mm_packus_epi16(m, m);
							
							_mm_store_ss(reinterpret_cast<float*>(&color),
										 _mm_castsi128_ps(m));
						}else
#endif
						{
							uint32_t c1 = color & 0xff00;
							uint32_t c2 = color & 0xff00ff;
							c1 *= bright;
							c2 *= bright;
							color = ((c1&0xff0000) | (c2&0xff00ff00)) >> 8;
						}
						
						for(int yy = minY; yy < maxY; yy++){
							auto *fb3 = fb2;
							auto *db3 = db2;
							
							for(int xx = w; xx > 0; xx--) {
								if(zval < *db3) {
									*db3 = zval;
									*fb3 = color;
								}
								fb3++; db3++;
							}
							
							fb2 += fw;
							db2 += fw;
						}
						
						
					}
					v2 += tAxis2;
				}
				v1 += tAxis1;
			}
		}
Example #15
0
	VoxelModel *VoxelModel::LoadKV6(spades::IStream *stream) {
		SPADES_MARK_FUNCTION();
		
		if(stream->Read(4) != "Kvxl"){
			SPRaise("Invalid magic");
		}
		
		KV6Header header;
		if(stream->Read(&header, sizeof(header)) < sizeof(header)){
			SPRaise("File truncated: failed to read header");
		}
		
		std::vector<KV6Block> blkdata;
		blkdata.resize(header.blklen);
		
		if(stream->Read(blkdata.data(), sizeof(KV6Block) * header.blklen) <
		   sizeof(KV6Block) * header.blklen){
			SPRaise("File truncated: failed to read blocks");
		}
		
		std::vector<uint32_t> xoffset;
		xoffset.resize(header.xsiz);
		
		if(stream->Read(xoffset.data(), sizeof(uint32_t) * header.xsiz) <
		   sizeof(uint32_t) * header.xsiz){
			SPRaise("File truncated: failed to read xoffset");
		}
		
		std::vector<uint16_t> xyoffset;
		xyoffset.resize(header.xsiz * header.ysiz);
		
		if(stream->Read(xyoffset.data(), sizeof(uint16_t) * header.xsiz * header.ysiz) <
		   sizeof(uint16_t) * header.xsiz * header.ysiz){
			SPRaise("File truncated: failed to read xyoffset");
		}
		
		// validate: zpos < depth
		for(size_t i = 0; i < blkdata.size(); i++)
			if(blkdata[i].zPos >= header.zsiz)
				SPRaise("File corrupted: blkData[i].zPos >= header.zsiz");
		
		// validate sum(xyoffset) = blkLen
		{
			uint64_t ttl = 0;
			for(size_t i = 0; i < xyoffset.size(); i++){
				ttl += (uint32_t)xyoffset[i];
			}
			if(ttl != (uint64_t)blkdata.size())
				SPRaise("File corrupted: sum(xyoffset) != blkdata.size()");
		}
		
		VoxelModel *model = new VoxelModel(header.xsiz, header.ysiz, header.zsiz);
		model->SetOrigin(MakeVector3(-header.xpivot,
									 -header.ypivot,
									 -header.zpivot));
		try{
			int pos = 0;
			for(int x = 0; x < (int)header.xsiz; x++)
				for(int y = 0; y < (int)header.ysiz; y++){
					int spanBlocks = (int)xyoffset[x *header.ysiz + y];
					int lastZ = -1;
					//printf("pos: %d, (%d, %d): %d\n",
					//	   pos, x, y, spanBlocks);
					while(spanBlocks--){
						const KV6Block& b = blkdata[pos];
						//printf("%d, %d, %d: %d, %d\n", x, y, b.zPos,
						//	   b.visFaces, b.lighting);
						if(model->IsSolid(x, y, b.zPos)){
							SPRaise("Duplicate voxel (%d, %d, %d)",
									x, y, b.zPos);
						}
						if(b.zPos <= lastZ){
							SPRaise("Not Z-sorted");
						}
						lastZ = b.zPos;
						model->SetSolid(x, y, b.zPos,
										swapColor(b.color));
						pos++;
					}
				}
			
			SPAssert(pos == blkdata.size());
			
			return model;
		}catch(...){
			delete model;
			throw;
		}
	}
Example #16
0
			virtual Vector3 GetRecoil() {
				return MakeVector3(0.05f, 0.1f, 0.f); // measured
			}
Example #17
0
		void Client::GrenadeExploded(spades::client::Grenade *g) {
			SPADES_MARK_FUNCTION();

			bool inWater = g->GetPosition().z > 63.f;

			if (inWater) {
				if (!IsMuted()) {
					Handle<IAudioChunk> c =
					  audioDevice->RegisterSound("Sounds/Weapons/Grenade/WaterExplode.opus");
					AudioParam param;
					param.volume = 10.f;
					audioDevice->Play(c, g->GetPosition(), param);

					c = audioDevice->RegisterSound("Sounds/Weapons/Grenade/WaterExplodeFar.opus");
					param.volume = 6.f;
					param.referenceDistance = 10.f;
					audioDevice->Play(c, g->GetPosition(), param);

					c = audioDevice->RegisterSound("Sounds/Weapons/Grenade/WaterExplodeStereo.opus");
					param.volume = 2.f;
					audioDevice->Play(c, g->GetPosition(), param);
				}

				GrenadeExplosionUnderwater(g->GetPosition());
			} else {

				GrenadeExplosion(g->GetPosition());

				if (!IsMuted()) {
					Handle<IAudioChunk> c, cs;

					switch (SampleRandomInt(0, 1)) {
						case 0:
							c = audioDevice->RegisterSound("Sounds/Weapons/Grenade/Explode1.opus");
							cs = audioDevice->RegisterSound(
							  "Sounds/Weapons/Grenade/ExplodeStereo1.opus");
							break;
						case 1:
							c = audioDevice->RegisterSound("Sounds/Weapons/Grenade/Explode2.opus");
							cs = audioDevice->RegisterSound(
							  "Sounds/Weapons/Grenade/ExplodeStereo2.opus");
							break;
					}

					AudioParam param;
					param.volume = 30.f;
					param.referenceDistance = 5.f;
					audioDevice->Play(c, g->GetPosition(), param);

					param.referenceDistance = 1.f;
					audioDevice->Play(cs, g->GetPosition(), param);

					c = audioDevice->RegisterSound("Sounds/Weapons/Grenade/ExplodeFar.opus");
					param.volume = 6.f;
					param.referenceDistance = 40.f;
					audioDevice->Play(c, g->GetPosition(), param);

					c = audioDevice->RegisterSound("Sounds/Weapons/Grenade/ExplodeFarStereo.opus");
					param.referenceDistance = 10.f;
					audioDevice->Play(c, g->GetPosition(), param);

					// debri sound
					c = audioDevice->RegisterSound("Sounds/Weapons/Grenade/Debris.opus");
					param.volume = 5.f;
					param.referenceDistance = 3.f;
					IntVector3 outPos;
					Vector3 soundPos = g->GetPosition();
					if (world->GetMap()->CastRay(soundPos, MakeVector3(0, 0, 1), 8.f, outPos)) {
						soundPos.z = (float)outPos.z - .2f;
					}
					audioDevice->Play(c, soundPos, param);
				}
			}
		}
Example #18
0
		Client::Client(IRenderer *r, IAudioDevice *audioDev,
                       const ServerAddress& host, std::string playerName)
            : playerName(playerName)
            , logStream(nullptr)
            , hostname(host)
            , renderer(r)
            , audioDevice(audioDev)
            , time(0.f)
            , readyToClose(false)
            , worldSubFrame(0.f)
            , frameToRendererInit(5)
            , timeSinceInit(0.f)
            , hasLastTool(false)
            , lastPosSentTime(0.f)
            , lastAliveTime(0.f)
            , lastKills(0)
            , hasDelayedReload(false)
            , localFireVibrationTime(-1.f)
            , grenadeVibration(0.f)
            , scoreboardVisible(false)
            , flashlightOn(false)
            , focalLength(20.f)
            , targetFocalLength(20.f)
            , autoFocusEnabled(true)
            , hitFeedbackFriendly(false)
            , lastMyCorpse(nullptr)

            , nextScreenShotIndex(0)
            , nextMapShotIndex(0)

            , alertDisappearTime(-10000.f)
		
        // FIXME: preferences?
            , corpseSoftTimeLimit(30.f) // FIXME: this is not used
            , corpseSoftLimit(6)
            , corpseHardLimit(16)

            , followYaw(0.f)
            , followPitch(0.f)
		{
			SPADES_MARK_FUNCTION();
			SPLog("Initializing...");
			
			designFont.Set(CreateSquareDesignFont(renderer), false);
			textFont.Set(CreateGuiFont(renderer), false);
			bigTextFont.Set(CreateLargeFont(renderer), false);
			
			renderer->SetFogDistance(128.f);
			renderer->SetFogColor(MakeVector3(.8f, 1.f, 1.f));
			
			chatWindow.reset(new ChatWindow(this, GetRenderer(), textFont, false));
			killfeedWindow.reset(new ChatWindow(this, GetRenderer(), textFont, true));
			
			hurtRingView.reset(new HurtRingView(this));
			centerMessageView.reset(new CenterMessageView(this, bigTextFont));
			mapView.reset(new MapView(this, false));
			largeMapView.reset(new MapView(this, true));
			scoreboard.reset(new ScoreboardView(this));
			limbo.reset(new LimboView(this));
			paletteView.reset(new PaletteView(this));
			tcView.reset(new TCProgressView(this));
			scriptedUI.Set(new ClientUI(renderer, audioDev, textFont, this), false);
			
			
			renderer->SetGameMap(nullptr);
		}
Example #19
0
		bool GunCasing::Update(float dt) {
			if(onGround){
				groundTime += dt;
				if(groundTime > 2.f){
					return false;
				}
				
				GameMap *map = client->GetWorld()->GetMap();
				if(!map->ClipWorld(groundPos.x, groundPos.y, groundPos.z)){
					return false;
				}
			}else{
				Matrix4 lastMat = matrix;
				
				matrix = matrix * Matrix4::Rotate(rotAxis, dt * rotSpeed);
				matrix = Matrix4::Translate(vel * dt) * matrix;
				vel.z += dt * 32.f;
				
				IntVector3 lp = matrix.GetOrigin().Floor();
				GameMap *m = client->GetWorld()->GetMap();
				
				if(lp.z >= 63){
					// dropped into water
					float dist = (client->GetLastSceneDef().viewOrigin - matrix.GetOrigin()).GetPoweredLength();
					
					if(waterSound){
						if(dist < 40.f * 40.f && !client->IsMuted()){
							IAudioDevice *dev = client->GetAudioDevice();
							AudioParam param;
							param.referenceDistance = .6f;
							param.pitch = .9f + GetRandom() * .2f;
							
							dev->Play(waterSound, lastMat.GetOrigin(),
									  param);
						}
						waterSound = NULL;
					}
					
					if(dist < 40.f * 40.f){
						int splats = rand() % 3;
						
						Handle<IImage> img = client->GetRenderer()->RegisterImage("Gfx/White.tga");
						
						Vector4 col = {1, 1, 1, 0.8f};
						Vector3 pt = matrix.GetOrigin();
						pt.z = 62.99f;
						for(int i = 0; i < splats; i++){
							ParticleSpriteEntity *ent =
							new ParticleSpriteEntity(client, img, col);
							ent->SetTrajectory(pt,
											   MakeVector3(GetRandom()-GetRandom(),
														   GetRandom()-GetRandom(),
														   -GetRandom()) * 2.f,
											   1.f, .4f);
							ent->SetRotation(GetRandom() * (float)M_PI * 2.f);
							ent->SetRadius(0.1f + GetRandom()*GetRandom()*0.1f);
							ent->SetLifeTime(2.f, 0.f, 1.f);
							client->AddLocalEntity(ent);
						}
							
					}
					
					return false;
				}
				
				if(m->ClipWorld(lp.x,lp.y,lp.z)){
					// hit a wall
					
					IntVector3 lp2 = lastMat.GetOrigin().Floor();
					if (lp.z != lp2.z && ((lp.x == lp2.x && lp.y == lp2.y) ||
										  !m->ClipWorld(lp.x, lp.y, lp2.z))){
						vel.z = -vel.z;
						if(lp2.z < lp.z){
							// ground hit
							if(vel.GetLength() < .5f + dt * 100.f && !dropSound){
								// stick to ground
								onGround = true;
								groundPos = lp;
								
								// move to surface
								float z = matrix.GetOrigin().z;
								float shift = z - floorf(z);
								matrix = Matrix4::Translate(0,0,-shift) * matrix;
								
								// lie
								Vector3 v1 = matrix.GetAxis(0);
								Vector3 v2 = matrix.GetAxis(1);
								v1.z = 0; v2.z = 0;
								v1 = v1.Normalize();
								v2 = v2.Normalize();
								
								Vector3 v3 = Vector3::Cross(v1, v2).Normalize();
								
								v1 = Vector3::Cross(v2, v3).Normalize();
								
								matrix = Matrix4::FromAxis(v1, v2, v3, matrix.GetOrigin());
							}else{
								if(dropSound){
									float dist = (client->GetLastSceneDef().viewOrigin - matrix.GetOrigin()).GetPoweredLength();
									if(dist < 40.f * 40.f && !client->IsMuted()){
										IAudioDevice *dev = client->GetAudioDevice();
										AudioParam param;
										param.referenceDistance = .6f;
									
										dev->Play(dropSound, lastMat.GetOrigin(),
												  param);
									}
									dropSound = NULL;
								}
							}
						}
					}else if(lp.x != lp2.x && ((lp.y == lp2.y && lp.z == lp2.z) ||
											  !m->ClipWorld(lp2.x, lp.y, lp.z)))
						vel.x = -vel.x;
					else if(lp.y != lp2.y && ((lp.x == lp2.x && lp.z == lp2.z) ||
											  !m->ClipWorld(lp.x, lp2.y, lp.z)))
						vel.y = -vel.y;
					else
						return false;
					if(!onGround){
						matrix = lastMat;
						vel *= .2f;
						rotAxis = RandomAxis();
						
						Vector3 r;
						r.x = GetRandom() - GetRandom();
						r.y = GetRandom() - GetRandom();
						r.z = GetRandom() - GetRandom();
						
						vel += r * 0.1f;
						
						rotSpeed *= .2f;
					}
				}
			}
			return true;
		}
Example #20
0
			virtual Vector3 GetRecoil () {
				return MakeVector3(0.0002f, -0.1f, 0.f);
			}
Example #21
0
		void Client::RunFrame(float dt) {
			SPADES_MARK_FUNCTION();
			
			fpsCounter.MarkFrame();
			
			if(frameToRendererInit > 0){
				// waiting for renderer initialization
				
				DrawStartupScreen();
				
				frameToRendererInit--;
				if(frameToRendererInit == 0){
					DoInit();
					
				}else{
					return;
				}
			}
			
			timeSinceInit += std::min(dt, .03f);
			
			// update network
			try{
				if(net->GetStatus() == NetClientStatusConnected)
					net->DoEvents(0);
				else
					net->DoEvents(10);
			}catch(const std::exception& ex){
				if(net->GetStatus() == NetClientStatusNotConnected){
					SPLog("Disconnected because of error:\n%s", ex.what());
					NetLog("Disconnected because of error:\n%s", ex.what());
					throw;
				}else{
					SPLog("Exception while processing network packets (ignored):\n%s", ex.what());
				}
			}
			
			hurtRingView->Update(dt);
			centerMessageView->Update(dt);
			mapView->Update(dt);
			largeMapView->Update(dt);
			
			UpdateAutoFocus(dt);
			
			if(world){
				UpdateWorld(dt);
			}else{
				renderer->SetFogColor(MakeVector3(0.f, 0.f, 0.f));
			}
			
			chatWindow->Update(dt);
			killfeedWindow->Update(dt);
			limbo->Update(dt);
			
			// CreateSceneDefinition also can be used for sounds
			SceneDefinition sceneDef = CreateSceneDefinition();
			lastSceneDef = sceneDef;
			
			// Update sounds
			try{
				audioDevice->Respatialize(sceneDef.viewOrigin,
										  sceneDef.viewAxis[2],
										  sceneDef.viewAxis[1]);
			}catch(const std::exception& ex){
				SPLog("Audio subsystem returned error (ignored):\n%s",
					  ex.what());
			}
			
			// render scene
			DrawScene();
			
			// draw 2d
			Draw2D();
			
			// draw scripted GUI
			scriptedUI->RunFrame(dt);
			if(scriptedUI->WantsClientToBeClosed())
				readyToClose = true;
			
			// Well done!
			renderer->FrameDone();
			renderer->Flip();
            
            // reset all "delayed actions" (in case we forget to reset these)
            hasDelayedReload = false;
			
			time += dt;
		}
Example #22
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 #23
0
	Vector3 Matrix4::GetOrigin() const {
		return MakeVector3(m[12], m[13], m[14]);
	}
Example #24
0
		void Corpse::AddToScene() {
			if(false){
				// debug line only
				Vector4 col = {1, 1, 0, 0};
				renderer->AddDebugLine(nodes[Torso1].pos,
									   nodes[Torso2].pos,
									   col);
				renderer->AddDebugLine(nodes[Torso2].pos,
									   nodes[Torso3].pos,
									   col);
				renderer->AddDebugLine(nodes[Torso3].pos,
									   nodes[Torso4].pos,
									   col);
				renderer->AddDebugLine(nodes[Torso4].pos,
									   nodes[Torso1].pos,
									   col);
				
				renderer->AddDebugLine(nodes[Torso2].pos,
									   nodes[Torso4].pos,
									   col);
				renderer->AddDebugLine(nodes[Torso1].pos,
									   nodes[Torso3].pos,
									   col);
				
				
				renderer->AddDebugLine(nodes[Torso1].pos,
									   nodes[Arm1].pos,
									   col);
				renderer->AddDebugLine(nodes[Torso2].pos,
									   nodes[Arm2].pos,
									   col);
				
				renderer->AddDebugLine(nodes[Torso3].pos,
									   nodes[Leg1].pos,
									   col);
				renderer->AddDebugLine(nodes[Torso4].pos,
									   nodes[Leg2].pos,
									   col);
				
				
				renderer->AddDebugLine((nodes[Torso1].pos+nodes[Torso2].pos)*.5f,
									   nodes[Head].pos,
									   col);
				return;
			}
			
			ModelRenderParam param;
			param.customColor = color;
			
			IModel *model;
			Matrix4 scaler = Matrix4::Scale(.1f);
			
			// draw torso
			Matrix4 torso;
			Vector3 tX, tY;
			{
				Vector3 tX1 = nodes[Torso1].pos - nodes[Torso2].pos;
				Vector3 tX2 = nodes[Torso4].pos - nodes[Torso3].pos;
				Vector3 tY1 = nodes[Torso1].pos + nodes[Torso2].pos;
				Vector3 tY2 = nodes[Torso4].pos + nodes[Torso3].pos;
				tX = ((tX1 + tX2) * .5f).Normalize();
				tY = ((tY2 - tY1) * .5f).Normalize();
				Vector3 tZ = Vector3::Cross(tX, tY).Normalize();
				tY = Vector3::Cross(tX, tZ).Normalize();
				Vector3 tOrigin = tY1 * .5f;
				torso = Matrix4::FromAxis(tX, -tZ, -tY, tOrigin);
				
				param.matrix = torso * scaler;
				
				model = renderer->RegisterModel
				("Models/Player/Torso.kv6");
				renderer->RenderModel(model, param);
			}
			// draw Head
			{
				Vector3 headBase =
				(torso * MakeVector3(0.0f, 0.f, 0.f)).GetXYZ();
				
				model = renderer->RegisterModel
				("Models/Player/Head.kv6");
				
				Vector3 aX, aY, aZ;
				Vector3 center = (nodes[Torso1].pos + nodes[Torso2].pos) * .5f;
				
				aZ = nodes[Head].pos - center;
				aZ = -torso.GetAxis(2);
				aZ = aZ.Normalize();
				aY = nodes[Torso2].pos - nodes[Torso1].pos;
				aY = Vector3::Cross(aY, aZ).Normalize();
				aX = Vector3::Cross(aY, aZ).Normalize();
				param.matrix = Matrix4::FromAxis(-aX, aY, -aZ, headBase) * scaler;
				
				renderer->RenderModel(model, param);
			}
			
			// draw Arms
			{
				Vector3 arm1Base =
				(torso * MakeVector3(0.4f, 0.f, 0.2f)).GetXYZ();
				Vector3 arm2Base =
				(torso * MakeVector3(-0.4f, 0.f, 0.2f)).GetXYZ();
				
				model = renderer->RegisterModel
				("Models/Player/Arm.kv6");
				
				Vector3 aX, aY, aZ;
				
				aZ = nodes[Arm1].pos - nodes[Torso1].pos;
				aZ = aZ.Normalize();
				aY = nodes[Torso2].pos - nodes[Torso1].pos;
				aY = Vector3::Cross(aY, aZ).Normalize();
				aX = Vector3::Cross(aY, aZ).Normalize();
				param.matrix = Matrix4::FromAxis(aX, aY, aZ, arm1Base) * scaler;
				
				renderer->RenderModel(model, param);
				
				aZ = nodes[Arm2].pos - nodes[Torso2].pos;
				aZ = aZ.Normalize();
				aY = nodes[Torso1].pos - nodes[Torso2].pos;
				aY = Vector3::Cross(aY, aZ).Normalize();
				aX = Vector3::Cross(aY, aZ).Normalize();
				param.matrix = Matrix4::FromAxis(aX, aY, aZ, arm2Base) * scaler;
				
				renderer->RenderModel(model, param);
			}
			
			// draw Leg
			{
				Vector3 leg1Base =
				(torso * MakeVector3(0.25f, 0.f, 0.9f)).GetXYZ();
				Vector3 leg2Base =
				(torso * MakeVector3(-0.25f, 0.f, 0.9f)).GetXYZ();
				
				model = renderer->RegisterModel
				("Models/Player/Leg.kv6");
				
				Vector3 aX, aY, aZ;
				
				aZ = nodes[Leg1].pos - nodes[Torso3].pos;
				aZ = aZ.Normalize();
				aY = nodes[Torso1].pos - nodes[Torso2].pos;
				aY = Vector3::Cross(aY, aZ).Normalize();
				aX = Vector3::Cross(aY, aZ).Normalize();
				param.matrix = Matrix4::FromAxis(aX, aY, aZ, leg1Base) * scaler;
				
				renderer->RenderModel(model, param);
				
				aZ = nodes[Leg2].pos - nodes[Torso4].pos;
				aZ = aZ.Normalize();
				aY = nodes[Torso1].pos - nodes[Torso2].pos;
				aY = Vector3::Cross(aY, aZ).Normalize();
				aX = Vector3::Cross(aY, aZ).Normalize();
				param.matrix = Matrix4::FromAxis(aX, aY, aZ, leg2Base) * scaler;
				
				renderer->RenderModel(model, param);
			}
		}
Example #25
0
			virtual Vector3 GetRecoil () {
				return MakeVector3(0.00005f, -0.0125f, 0.f);
			}
Example #26
0
			virtual Vector3 GetRecoil() {
				// FIXME: needs to measured
				return MakeVector3(0.0002f, 0.075f, 0.f);
			}
		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;
Example #28
0
		void Client::PlayerKilledPlayer(spades::client::Player *killer,
		                                spades::client::Player *victim, KillType kt) {
			// play hit sound
			if (kt == KillTypeWeapon || kt == KillTypeHeadshot) {
				// don't play on local: see BullethitPlayer
				if (victim != world->GetLocalPlayer()) {
					if (!IsMuted()) {
						Handle<IAudioChunk> c;
						switch (SampleRandomInt(0, 2)) {
							case 0:
								c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/Flesh1.opus");
								break;
							case 1:
								c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/Flesh2.opus");
								break;
							case 2:
								c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/Flesh3.opus");
								break;
						}
						AudioParam param;
						param.volume = 4.f;
						audioDevice->Play(c, victim->GetEye(), param);
					}
				}
			}

			// The local player is dead; initialize the look-you-are-dead cam
			if (victim == world->GetLocalPlayer()) {
				followCameraState.enabled = false;

				Vector3 v = -victim->GetFront();
				followAndFreeCameraState.yaw = atan2(v.y, v.x);
				followAndFreeCameraState.pitch = 30.f * M_PI / 180.f;
			}

			// emit blood (also for local player)
			// FIXME: emiting blood for either
			// client-side or server-side hit?
			switch (kt) {
				case KillTypeGrenade:
				case KillTypeHeadshot:
				case KillTypeMelee:
				case KillTypeWeapon: Bleed(victim->GetEye()); break;
				default: break;
			}

			// create ragdoll corpse
			if (cg_ragdoll && victim->GetTeamId() < 2) {
				Corpse *corp;
				corp = new Corpse(renderer, map, victim);
				if (victim == world->GetLocalPlayer())
					lastMyCorpse = corp;
				if (killer != victim && kt != KillTypeGrenade) {
					Vector3 dir = victim->GetPosition() - killer->GetPosition();
					dir = dir.Normalize();
					if (kt == KillTypeMelee) {
						dir *= 6.f;
					} else {
						if (killer->GetWeapon()->GetWeaponType() == SMG_WEAPON) {
							dir *= 2.8f;
						} else if (killer->GetWeapon()->GetWeaponType() == SHOTGUN_WEAPON) {
							dir *= 4.5f;
						} else {
							dir *= 3.5f;
						}
					}
					corp->AddImpulse(dir);
				} else if (kt == KillTypeGrenade) {
					corp->AddImpulse(MakeVector3(0, 0, -4.f - SampleRandomFloat() * 4.f));
				}
				corp->AddImpulse(victim->GetVelocty() * 32.f);
				corpses.emplace_back(corp);

				if (corpses.size() > corpseHardLimit) {
					corpses.pop_front();
				} else if (corpses.size() > corpseSoftLimit) {
					RemoveInvisibleCorpses();
				}
			}

			// add chat message
			std::string s;
			s = ChatWindow::TeamColorMessage(killer->GetName(), killer->GetTeamId());

			std::string cause;
			bool isFriendlyFire = killer->GetTeamId() == victim->GetTeamId();
			if (killer == victim)
				isFriendlyFire = false;

			Weapon *w =
			  killer ? killer->GetWeapon() : nullptr; // only used in case of KillTypeWeapon
			switch (kt) {
				case KillTypeWeapon:
					switch (w ? w->GetWeaponType() : RIFLE_WEAPON) {
						case RIFLE_WEAPON: cause += _Tr("Client", "Rifle"); break;
						case SMG_WEAPON: cause += _Tr("Client", "SMG"); break;
						case SHOTGUN_WEAPON: cause += _Tr("Client", "Shotgun"); break;
					}
					break;
				case KillTypeFall:
					//! A cause of death shown in the kill feed.
					cause += _Tr("Client", "Fall");
					break;
				case KillTypeMelee:
					//! A cause of death shown in the kill feed.
					cause += _Tr("Client", "Melee");
					break;
				case KillTypeGrenade:
					cause += _Tr("Client", "Grenade");
					break;
				case KillTypeHeadshot:
					//! A cause of death shown in the kill feed.
					cause += _Tr("Client", "Headshot");
					break;
				case KillTypeTeamChange:
					//! A cause of death shown in the kill feed.
					cause += _Tr("Client", "Team Change");
					break;
				case KillTypeClassChange:
					//! A cause of death shown in the kill feed.
					cause += _Tr("Client", "Weapon Change");
					break;
				default:
					cause += "???";
					break;
			}

			s += " [";
			if (isFriendlyFire)
				s += ChatWindow::ColoredMessage(cause, MsgColorFriendlyFire);
			else if (killer == world->GetLocalPlayer() || victim == world->GetLocalPlayer())
				s += ChatWindow::ColoredMessage(cause, MsgColorGray);
			else
				s += cause;
			s += "] ";

			if (killer != victim) {
				s += ChatWindow::TeamColorMessage(victim->GetName(), victim->GetTeamId());
			}

			killfeedWindow->AddMessage(s);

			// log to netlog
			if (killer != victim) {
				NetLog("%s (%s) [%s] %s (%s)", killer->GetName().c_str(),
				       world->GetTeam(killer->GetTeamId()).name.c_str(), cause.c_str(),
				       victim->GetName().c_str(), world->GetTeam(victim->GetTeamId()).name.c_str());
			} else {
				NetLog("%s (%s) [%s]", killer->GetName().c_str(),
				       world->GetTeam(killer->GetTeamId()).name.c_str(), cause.c_str());
			}

			// show big message if player is involved
			if (victim != killer) {
				Player *local = world->GetLocalPlayer();
				if (killer == local || victim == local) {
					std::string msg;
					if (killer == local) {
						if ((int)cg_centerMessage == 2)
							msg = _Tr("Client", "You have killed {0}", victim->GetName());
					} else {
						msg = _Tr("Client", "You were killed by {0}", killer->GetName());
					}
					centerMessageView->AddMessage(msg);
				}
			}
		}
Example #29
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 #30
0
		Tracer::Tracer(Client *client,
					   Player *player,
					   IModel *model,
					   Vector3 p1,
					   Vector3 p2,
					   float bulletVel,
					   IntVector3 team) :
		client(client), player(player), model(model), startPos(p1), velocity(bulletVel), teamCol(team)
		{
			dir = (p2 - p1).Normalize();
			length = (p2 - p1).GetLength()-2;

			startPos += dir*8;

			const float maxTimeSpread = 1.f / 60.f;
			const float shutterTime = 0.3f / 60.f;
			
			visibleLength = shutterTime * bulletVel;
			curDistance = -visibleLength + 8;
			curDistance += maxTimeSpread; //* GetRandom();
			
			firstUpdate = true;
			
			image = client->GetRenderer()->RegisterImage("Gfx/WhitePixel.tga");
			//image2 = client->GetRenderer()->RegisterImage("Gfx/WhiteDisk.tga");

			//Chameleon: .wav sounds for tracers
			int x = GetRandom()*4;
			switch (x % 4)
			{
				case 0:
					snd = bulletVel > 350 ?
						client->GetAudioDevice()->RegisterSound("Sounds/Weapons/Objects/TracerSUP1.wav") :
						client->GetAudioDevice()->RegisterSound("Sounds/Weapons/Objects/TracerSUB1.wav");
					break;
				case 1:
					snd = bulletVel > 350 ?
						client->GetAudioDevice()->RegisterSound("Sounds/Weapons/Objects/TracerSUP2.wav") :
						client->GetAudioDevice()->RegisterSound("Sounds/Weapons/Objects/TracerSUB2.wav");
					break;
				case 2:
					snd = bulletVel > 350 ?
						client->GetAudioDevice()->RegisterSound("Sounds/Weapons/Objects/TracerSUP3.wav") :
						client->GetAudioDevice()->RegisterSound("Sounds/Weapons/Objects/TracerSUB3.wav");
					break;
				case 3:
					snd = bulletVel > 350 ?
						client->GetAudioDevice()->RegisterSound("Sounds/Weapons/Objects/TracerSUP4.wav") :
						client->GetAudioDevice()->RegisterSound("Sounds/Weapons/Objects/TracerSUB4.wav");
					break;
				default:
					break;
			}

			if (player)
			{
				if (player->IsLocalPlayer() || (p1 - player->GetPosition()).GetPoweredLength() < 64)
					flyByDist = -1;
			}
			else
			{
				flyByDist = 0;
			}
			//soundPlayed = false;

			//Chameleon: .kv6 tracers
			Vector3 up = MakeVector3(0, 0, 1);
			Vector3 right = Vector3::Cross(dir, up).Normalize();
			up = Vector3::Cross(right, dir);

			matrix = Matrix4::FromAxis(right, dir, up, startPos);

			//Chameleon: teamCol tracers
			//int colFac = (int)opt_tracers;
			colour = Vector3(teamCol.x / 255.f, teamCol.y / 255.f, teamCol.z / 255.f);
			colour = Vector3(colour.x / colour.GetLength(), colour.y / colour.GetLength(), colour.z / colour.GetLength());
			colour = (colour + Vector3(1, 1, 1)) / 1.9f;

			dlight = r_dlights && opt_tracersDLight;
		}