Example #1
0
		bool Player::RayCastApprox(spades::Vector3 start, spades::Vector3 dir){
			Vector3 diff = position - start;
			
			// |P-A| * cos(theta)
			float c = Vector3::Dot(diff, dir);
			
			// |P-A|^2
			float sq = diff.GetPoweredLength();
			
			// |P-A| * sin(theta)
			float dist = sqrtf(sq - c * c);
			
			return dist < 8.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 #3
0
	bool OBB3::RayCast(spades::Vector3 start,
					   spades::Vector3 dir,
					   spades::Vector3 *hitPos) {
		Vector3 normX = {m.m[0], m.m[1], m.m[2]};
		Vector3 normY = {m.m[4], m.m[5], m.m[6]};
		Vector3 normZ = {m.m[8], m.m[9], m.m[10]};
		
		// subtract offset
		Vector3 origin = {m.m[12], m.m[13], m.m[14]};
		start -= origin;
		
		Vector3 end = start + dir;
		
		float dotX = Vector3::Dot(dir, normX);
		float dotY = Vector3::Dot(dir, normY);
		float dotZ = Vector3::Dot(dir, normZ);
		
		// inside?
		if(*this && start){
			*hitPos = start;
			return true;
		}
		
		// x-plane hit test
		if(dotX != 0.f){
			float startp = Vector3::Dot(start, normX);
			float endp = Vector3::Dot(end, normX);
			float boxp = Vector3::Dot(normX, normX);
			float hit; // 0=start, 1=end
			if(startp < endp){
				hit = startp / (startp - endp);
			}else{
				hit = (boxp - startp) / (endp - startp);
			}
			if(hit >= 0.f){
				*hitPos = start + dir * hit;
				
				float yd = Vector3::Dot(*hitPos, normY);
				float zd = Vector3::Dot(*hitPos, normZ);
				if(yd >= 0 && zd >= 0 &&
				   yd <= normY.GetPoweredLength() &&
				   zd <= normZ.GetPoweredLength()) {
					// hit x-plane
					*hitPos += origin;
					return true;
				}
			}
		}
		
		// y-plane hit test
		if(dotY != 0.f){
			float startp = Vector3::Dot(start, normY);
			float endp = Vector3::Dot(end, normY);
			float boxp = Vector3::Dot(normY, normY);
			float hit; // 0=start, 1=end
			if(startp < endp){
				hit = startp / (startp - endp);
			}else{
				hit = (boxp - startp) / (endp - startp);
			}
			if(hit >= 0.f){
				*hitPos = start + dir * hit;
				
				float xd = Vector3::Dot(*hitPos, normX);
				float zd = Vector3::Dot(*hitPos, normZ);
				if(xd >= 0 && zd >= 0 &&
				   xd <= normX.GetPoweredLength() &&
				   zd <= normZ.GetPoweredLength()) {
					// hit y-plane
					*hitPos += origin;
					return true;
				}
			}
		}
		
		// z-plane hit test
		if(dotZ != 0.f){
			float startp = Vector3::Dot(start, normZ);
			float endp = Vector3::Dot(end, normZ);
			float boxp = Vector3::Dot(normZ, normZ);
			float hit; // 0=start, 1=end
			if(startp < endp){
				hit = startp / (startp - endp);
			}else{
				hit = (boxp - startp) / (endp - startp);
			}
			if(hit >= 0.f){
				*hitPos = start + dir * hit;
				
				float xd = Vector3::Dot(*hitPos, normX);
				float yd = Vector3::Dot(*hitPos, normY);
				if(xd >= 0 && yd >= 0 &&
				   xd <= normX.GetPoweredLength() &&
				   yd <= normY.GetPoweredLength()) {
					// hit z-plane
					*hitPos += origin;
					return true;
				}
			}
		}
		
		return false;
	}
Example #4
0
		void SWRenderer::ApplyDynamicLight(const DynamicLight &light) {
			int fw = this->fb->GetWidth();
			int fh = this->fb->GetHeight();
			
			float fovX = tanf(sceneDef.fovX * 0.5f);
			float fovY = tanf(sceneDef.fovY * 0.5f);
			
			float dvx = -fovX * 2.f / static_cast<float>(fw);
			float dvy = -fovY * 2.f / static_cast<float>(fh);
			
			int minX = light.minX;
			int minY = light.minY;
			int maxX = light.maxX;
			int maxY = light.maxY;
			int lightHeight = maxY - minY;
			
			SPAssert(minX >= 0);
			SPAssert(minY >= 0);
			SPAssert(maxX <= fw);
			SPAssert(maxY <= fh);
			
			Vector3 lightCenter;
			Vector3 diff = light.param.origin - sceneDef.viewOrigin;
			lightCenter.x = Vector3::Dot(diff, sceneDef.viewAxis[0]);
			lightCenter.y = Vector3::Dot(diff, sceneDef.viewAxis[1]);
			lightCenter.z = Vector3::Dot(diff, sceneDef.viewAxis[2]);
			
			int lightR = ToFixedFactor8(light.param.color.x);
			int lightG = ToFixedFactor8(light.param.color.y);
			int lightB = ToFixedFactor8(light.param.color.z);
			
			float invRadius2 = 1.f / (light.param.radius * light.param.radius);
			
			InvokeParallel2([=](unsigned int threadId, unsigned int numThreads) {
				int startY = lightHeight * threadId / numThreads;
				int endY = lightHeight * (threadId + 1) / numThreads;
				startY += minY;
				endY += minY;
				
				auto *fb = this->fb->GetPixels();
				float *db = depthBuffer.data();
				fb += startY * fw + minX;
				db += startY * fw + minX;
				
				float vy = fovY + dvy * startY;
				float vx = fovX + dvx * minX;
				
				int lightWidth = maxX - minX;
				
				for(int y = startY; y < endY; y++) {
					float vx2 = vx;
					auto *fb2 = fb;
					auto *db2 = db;
					
					for(int x = lightWidth; x > 0; x--) {
						Vector3 pos;
						
						pos.z = *db2;
						pos.x = vx2 * pos.z;
						pos.y = vy  * pos.z;
						
						pos -= lightCenter;
						
						float dist = pos.GetPoweredLength();
						dist *= invRadius2;
						
						if(dist < 1.f) {
							float strength = 1.f - dist;
							strength *= strength;
							strength *= 256.f;
							
							int factor = static_cast<int>(strength);
							
							int actualLightR = lightR * factor;
							int actualLightG = lightG * factor;
							int actualLightB = lightB * factor;
							
							auto srcColor = *fb2;
							auto srcColorR = (srcColor >> 16) & 0xff;
							auto srcColorG = (srcColor >> 8) & 0xff;
							auto srcColorB = srcColor & 0xff;
							
							actualLightR *= srcColorR;
							actualLightG *= srcColorG;
							actualLightB *= srcColorB;
							
							auto destColorR = actualLightR >> 16;
							auto destColorG = actualLightG >> 16;
							auto destColorB = actualLightB >> 16;
							
							destColorR = std::min<uint32_t>(destColorR+srcColorR, 255);
							destColorG = std::min<uint32_t>(destColorG+srcColorG, 255);
							destColorB = std::min<uint32_t>(destColorB+srcColorB, 255);
							
							uint32_t destColor = destColorB |
							(destColorG<<8) | (destColorR<<16);
							
							*fb2 = destColor;
						}
						
						vx2 += dvx;
						fb2++; db2++;
					}
					
					vy += dvy;
					fb += fw;
					db += fw;
				}
			});