/* backpropagtation algorithm */
void Backpropagation (int* input, int* targetOutput)
{
	int i = 0;
	float **hiddenDelta, *outputDelta;

	/* allocate output, hiddendelta and outputdelta */
	hiddenDelta = (float **)calloc(numHiddenLayers, sizeof(float *));
	outputDelta = (float *)calloc(numOutputNodes, sizeof(float));

	for(i = 0; i < numHiddenLayers; i++)
	{
		hiddenDelta[i] = (float *)calloc(neuronsPerLayer,  sizeof(float));
	}

	ForwardPropagation (input, outputOutputs);

	CalcDelta(targetOutput,
			hiddenDelta,
			outputDelta);

	UpdateNetwork(hiddenDelta, outputDelta, input);


	for(i = 0; i < numHiddenLayers; i++)
	{
		free(hiddenDelta[i]);
	}

	free(hiddenDelta);
	free(outputDelta);

	return;
}
Example #2
0
sRGBfloat cRenderWorker::TextureShader(
	const sShaderInputData &input, cMaterial::enumTextureSelection texSelect, cMaterial *mat) const
{
	cObjectData objectData = data->objectData[input.objectId];
	double texturePixelSize = 1.0;
	CVector3 textureVectorX, textureVectorY;
	CVector2<double> texPoint =
		TextureMapping(input.point, input.normal, objectData, mat, &textureVectorX, &textureVectorY)
		+ CVector2<double>(0.5, 0.5);

	// mipmapping - calculation of texture pixel size
	double delta = CalcDelta(input.point);
	double deltaTexX =
		((TextureMapping(input.point + textureVectorX * delta, input.normal, objectData, mat)
			 + CVector2<double>(0.5, 0.5))
			- texPoint)
			.Length();
	double deltaTexY =
		((TextureMapping(input.point + textureVectorY * delta, input.normal, objectData, mat)
			 + CVector2<double>(0.5, 0.5))
			- texPoint)
			.Length();

	if (deltaTexX > 0.5) deltaTexX = 1.0 - deltaTexX;
	if (deltaTexY > 0.5) deltaTexY = 1.0 - deltaTexY;

	deltaTexX = deltaTexX / fabs(input.viewVector.Dot(input.normal));
	deltaTexY = deltaTexY / fabs(input.viewVector.Dot(input.normal));

	texturePixelSize = 1.0 / max(deltaTexX, deltaTexY);

	sRGBfloat tex;
	switch (texSelect)
	{
		case cMaterial::texColor:
		{
			tex = input.material->colorTexture.Pixel(texPoint, texturePixelSize);
			break;
		}
		case cMaterial::texDiffuse:
		{
			tex = input.material->diffusionTexture.Pixel(texPoint, texturePixelSize);
			break;
		}
		case cMaterial::texLuminosity:
		{
			tex = input.material->luminosityTexture.Pixel(texPoint, texturePixelSize);
			break;
		}
		case cMaterial::texDisplacement:
		{
			tex = input.material->displacementTexture.Pixel(texPoint, texturePixelSize);
			break;
		}
	}

	return sRGBfloat(tex.R, tex.G, tex.B);
}
Example #3
0
CVector3 cRenderWorker::NormalMapShader(const sShaderInputData &input)
{
	cObjectData objectData = data->objectData[input.objectId];
	CVector3 texX, texY;
	double texturePixelSize = 1.0;
	CVector2<double> texPoint =
		TextureMapping(input.point, input.normal, objectData, input.material, &texX, &texY)
		+ CVector2<double>(0.5, 0.5);

	// mipmapping - calculation of texture pixel size
	double delta = CalcDelta(input.point);
	double deltaTexX =
		((TextureMapping(input.point + texX * delta, input.normal, objectData, input.material)
			 + CVector2<double>(0.5, 0.5))
			- texPoint)
			.Length();
	double deltaTexY =
		((TextureMapping(input.point + texY * delta, input.normal, objectData, input.material)
			 + CVector2<double>(0.5, 0.5))
			- texPoint)
			.Length();
	deltaTexX = deltaTexX / fabs(input.viewVector.Dot(input.normal));
	deltaTexY = deltaTexY / fabs(input.viewVector.Dot(input.normal));
	texturePixelSize = 1.0 / max(deltaTexX, deltaTexY);

	CVector3 n = input.normal;
	// tangent vectors:
	CVector3 t = n.Cross(texX);
	t.Normalize();
	CVector3 b = n.Cross(texY);
	b.Normalize();
	CMatrix33 tbn(b, t, n);

	CVector3 tex;

	if (input.material->normalMapTextureFromBumpmap)
	{
		tex = input.material->normalMapTexture.NormalMapFromBumpMap(
			texPoint, input.material->normalMapTextureHeight, texturePixelSize);
	}
	else
	{
		tex = input.material->normalMapTexture.NormalMap(
			texPoint, input.material->normalMapTextureHeight, texturePixelSize);
	}

	CVector3 result = tbn * tex;
	result.Normalize();
	return result;
}
Example #4
0
sRGBAfloat cRenderWorker::VolumetricShader(
	const sShaderInputData &input, sRGBAfloat oldPixel, sRGBAfloat *opacityOut)
{
	sRGBAfloat output;
	float totalOpacity = 0.0;

	output.R = oldPixel.R;
	output.G = oldPixel.G;
	output.B = oldPixel.B;
	output.A = oldPixel.A;

	// volumetric fog init
	double colourThresh = params->volFogColour1Distance;
	double colourThresh2 = params->volFogColour2Distance;
	double fogReduce = params->volFogDistanceFactor;
	double fogIntensity = params->volFogDensity;

	// visible lights init
	int numberOfLights = data->lights.GetNumberOfLights();
	if (numberOfLights < 4) numberOfLights = 4;

	// glow init
	double glow = input.stepCount * params->glowIntensity / 512.0 * params->DEFactor;
	double glowN = 1.0 - glow;
	if (glowN < 0.0) glowN = 0.0;
	double glowR = (params->glowColor1.R * glowN + params->glowColor2.R * glow) / 65536.0;
	double glowG = (params->glowColor1.G * glowN + params->glowColor2.G * glow) / 65536.0;
	double glowB = (params->glowColor1.B * glowN + params->glowColor2.B * glow) / 65536.0;

	double totalStep = 0.0;

	// qDebug() << "Start volumetric shader &&&&&&&&&&&&&&&&&&&&";

	sShaderInputData input2 = input;
	for (int index = input.stepCount - 1; index > 0; index--)
	{
		double step = input.stepBuff[index].step;
		double distance = input.stepBuff[index].distance;
		CVector3 point = input.stepBuff[index].point;
		totalStep += step;

		input2.point = point;
		input2.distThresh = input.stepBuff[index].distThresh;

		// qDebug() << "i" << index << "dist" << distance << "iters" << input.stepBuff[index].iters <<
		// "distThresh" << input2.distThresh << "step" << step << "point" << point.Debug();

		if (totalStep < CalcDelta(point))
		{
			continue;
		}
		step = totalStep;
		totalStep = 0.0;

		//------------------- glow
		if (params->glowEnabled)
		{
			double glowOpacity = glow / input.stepCount;
			if (glowOpacity > 1.0) glowOpacity = 1.0;
			output.R = glowOpacity * glowR + (1.0 - glowOpacity) * output.R;
			output.G = glowOpacity * glowG + (1.0 - glowOpacity) * output.G;
			output.B = glowOpacity * glowB + (1.0 - glowOpacity) * output.B;
			output.A += glowOpacity;
		}
		// qDebug() << "step" << step;
		//------------------ visible light
		if (params->auxLightVisibility > 0)
		{
			double miniStep = 0.0;
			double lastMiniSteps = -1.0;

			for (double miniSteps = 0.0; miniSteps < step; miniSteps += miniStep)
			{
				double lowestLightSize = 1e10;
				double lowestLightDist = 1e10;
				for (int i = 0; i < numberOfLights; ++i)
				{
					const cLights::sLight *light = data->lights.GetLight(i);
					if (light->enabled)
					{
						CVector3 lightDistVect = (point - input.viewVector * miniSteps) - light->position;
						double lightDist = lightDistVect.Length();
						double lightSize = sqrt(light->intensity) * params->auxLightVisibilitySize;
						double distToLightSurface = lightDist - lightSize;
						if (distToLightSurface < 0.0) distToLightSurface = 0.0;
						if (distToLightSurface <= lowestLightDist)
						{
							if (lightSize < lowestLightSize)
							{
								lowestLightSize = lightSize;
							}
							lowestLightDist = distToLightSurface;
						}
					}
				}

				miniStep = 0.1 * (lowestLightDist + 0.1 * lowestLightSize);
				if (miniStep > step - miniSteps) miniStep = step - miniSteps;
				// qDebug() << "lowDist:" << lowestLightDist << "lowSize" << lowestLightSize << "miniStep"
				// << miniStep;

				for (int i = 0; i < numberOfLights; ++i)
				{
					const cLights::sLight *light = data->lights.GetLight(i);
					if (light->enabled)
					{
						CVector3 lightDistVect = (point - input.viewVector * miniSteps) - light->position;
						double lightDist = lightDistVect.Length();
						double lightSize = sqrt(light->intensity) * params->auxLightVisibilitySize;
						double r2 = lightDist / lightSize;
						double bellFunction = 1.0 / (1.0 + pow(r2, 4.0));
						double lightDensity = miniStep * bellFunction * params->auxLightVisibility / lightSize;

						output.R += lightDensity * light->colour.R / 65536.0;
						output.G += lightDensity * light->colour.G / 65536.0;
						output.B += lightDensity * light->colour.B / 65536.0;
						output.A += lightDensity;
					}
				}
				if (miniSteps == lastMiniSteps)
				{
					// qWarning() << "Dead computation\n"
					//		<< "\npoint:" << (point - input.viewVector * miniSteps).Debug();
					break;
				}
				lastMiniSteps = miniSteps;
			}
		}

		// fake lights (orbit trap)
		if (params->fakeLightsEnabled)
		{
			sFractalIn fractIn(point, params->minN, params->N, params->common, -1);
			sFractalOut fractOut;
			Compute<fractal::calcModeOrbitTrap>(*fractal, fractIn, &fractOut);
			double r = fractOut.orbitTrapR;
			r = sqrt(1.0f / (r + 1.0e-30f));
			double fakeLight = 1.0 / (pow(r, 10.0 / params->fakeLightsVisibilitySize)
																	 * pow(10.0, 10.0 / params->fakeLightsVisibilitySize)
																 + 1e-100);
			output.R += fakeLight * step * params->fakeLightsVisibility;
			output.G += fakeLight * step * params->fakeLightsVisibility;
			output.B += fakeLight * step * params->fakeLightsVisibility;
			output.A += fakeLight * step * params->fakeLightsVisibility;
		}

		//---------------------- volumetric lights with shadows in fog

		for (int i = 0; i < 5; i++)
		{
			if (i == 0 && params->volumetricLightEnabled[0])
			{
				sRGBAfloat shadowOutputTemp = MainShadow(input2);
				output.R += shadowOutputTemp.R * step * params->volumetricLightIntensity[0]
										* params->mainLightColour.R / 65536.0;
				output.G += shadowOutputTemp.G * step * params->volumetricLightIntensity[0]
										* params->mainLightColour.G / 65536.0;
				output.B += shadowOutputTemp.B * step * params->volumetricLightIntensity[0]
										* params->mainLightColour.B / 65536.0;
				output.A += (shadowOutputTemp.R + shadowOutputTemp.G + shadowOutputTemp.B) / 3.0 * step
										* params->volumetricLightIntensity[0];
			}
			if (i > 0)
			{
				const cLights::sLight *light = data->lights.GetLight(i - 1);
				if (light->enabled && params->volumetricLightEnabled[i])
				{
					CVector3 lightVectorTemp = light->position - point;
					double distanceLight = lightVectorTemp.Length();
					double distanceLight2 = distanceLight * distanceLight;
					lightVectorTemp.Normalize();
					double lightShadow = AuxShadow(input2, distanceLight, lightVectorTemp);
					output.R += lightShadow * light->colour.R / 65536.0 * params->volumetricLightIntensity[i]
											* step / distanceLight2;
					output.G += lightShadow * light->colour.G / 65536.0 * params->volumetricLightIntensity[i]
											* step / distanceLight2;
					output.B += lightShadow * light->colour.B / 65536.0 * params->volumetricLightIntensity[i]
											* step / distanceLight2;
					output.A += lightShadow * params->volumetricLightIntensity[i] * step / distanceLight2;
				}
			}
		}

		//----------------------- basic fog
		if (params->fogEnabled)
		{
			double fogDensity = step / params->fogVisibility;
			if (fogDensity > 1.0) fogDensity = 1.0;
			output.R = fogDensity * params->fogColor.R / 65536.0 + (1.0 - fogDensity) * output.R;
			output.G = fogDensity * params->fogColor.G / 65536.0 + (1.0 - fogDensity) * output.G;
			output.B = fogDensity * params->fogColor.B / 65536.0 + (1.0 - fogDensity) * output.B;
			totalOpacity = fogDensity + (1.0 - fogDensity) * totalOpacity;
			output.A = fogDensity + (1.0 - fogDensity) * output.A;
		}

		//-------------------- volumetric fog
		if (fogIntensity > 0.0 && params->volFogEnabled)
		{
			double densityTemp = (step * fogReduce) / (distance * distance + fogReduce * fogReduce);

			double k = distance / colourThresh;
			if (k > 1) k = 1.0;
			double kn = 1.0 - k;
			double fogRtemp = (params->volFogColour1.R * kn + params->volFogColour2.R * k);
			double fogGtemp = (params->volFogColour1.G * kn + params->volFogColour2.G * k);
			double fogBtemp = (params->volFogColour1.B * kn + params->volFogColour2.B * k);

			double k2 = distance / colourThresh2 * k;
			if (k2 > 1) k2 = 1.0;
			kn = 1.0 - k2;
			fogRtemp = (fogRtemp * kn + params->volFogColour3.R * k2);
			fogGtemp = (fogGtemp * kn + params->volFogColour3.G * k2);
			fogBtemp = (fogBtemp * kn + params->volFogColour3.B * k2);

			double fogDensity = 0.3 * fogIntensity * densityTemp / (1.0 + fogIntensity * densityTemp);
			if (fogDensity > 1) fogDensity = 1.0;

			output.R = fogDensity * fogRtemp / 65536.0 + (1.0 - fogDensity) * output.R;
			output.G = fogDensity * fogGtemp / 65536.0 + (1.0 - fogDensity) * output.G;
			output.B = fogDensity * fogBtemp / 65536.0 + (1.0 - fogDensity) * output.B;
			// qDebug() << "densityTemp " << densityTemp << "k" << k << "k2" << k2 << "fogTempR" <<
			// fogRtemp << "fogDensity" << fogDensity << "output.R" << output.R;

			totalOpacity = fogDensity + (1.0 - fogDensity) * totalOpacity;
			output.A = fogDensity + (1.0 - fogDensity) * output.A;
		}

		// iter fog
		if (params->iterFogEnabled)
		{
			int L = input.stepBuff[index].iters;
			double opacity =
				IterOpacity(step, L, params->N, params->iterFogOpacityTrim, params->iterFogOpacity);

			sRGBAfloat newColour(0.0, 0.0, 0.0, 0.0);
			if (opacity > 0)
			{
				// fog colour
				double iterFactor1 = (L - params->iterFogOpacityTrim)
														 / (params->iterFogColor1Maxiter - params->iterFogOpacityTrim);
				double k = iterFactor1;
				if (k > 1.0) k = 1.0;
				if (k < 0.0) k = 0.0;
				double kn = 1.0 - k;
				double fogColR = (params->iterFogColour1.R * kn + params->iterFogColour2.R * k);
				double fogColG = (params->iterFogColour1.G * kn + params->iterFogColour2.G * k);
				double fogColB = (params->iterFogColour1.B * kn + params->iterFogColour2.B * k);

				double iterFactor2 = (L - params->iterFogColor1Maxiter)
														 / (params->iterFogColor2Maxiter - params->iterFogColor1Maxiter);
				double k2 = iterFactor2;
				if (k2 < 0.0) k2 = 0.0;
				if (k2 > 1.0) k2 = 1.0;
				kn = 1.0 - k2;
				fogColR = (fogColR * kn + params->iterFogColour3.R * k2);
				fogColG = (fogColG * kn + params->iterFogColour3.G * k2);
				fogColB = (fogColB * kn + params->iterFogColour3.B * k2);
				//----

				for (int i = 0; i < 5; i++)
				{
					if (i == 0)
					{
						if (params->mainLightEnable && params->mainLightIntensity > 0.0)
						{
							sRGBAfloat shadowOutputTemp = MainShadow(input2);
							newColour.R += shadowOutputTemp.R * params->mainLightColour.R / 65536.0
														 * params->mainLightIntensity;
							newColour.G += shadowOutputTemp.G * params->mainLightColour.G / 65536.0
														 * params->mainLightIntensity;
							newColour.B += shadowOutputTemp.B * params->mainLightColour.B / 65536.0
														 * params->mainLightIntensity;
						}
					}

					if (i > 0)
					{
						const cLights::sLight *light = data->lights.GetLight(i - 1);
						if (light->enabled)
						{
							CVector3 lightVectorTemp = light->position - point;
							double distanceLight = lightVectorTemp.Length();
							double distanceLight2 = distanceLight * distanceLight;
							lightVectorTemp.Normalize();
							double lightShadow = AuxShadow(input2, distanceLight, lightVectorTemp);
							double intensity = light->intensity * 100.0;
							newColour.R += lightShadow * light->colour.R / 65536.0 / distanceLight2 * intensity;
							newColour.G += lightShadow * light->colour.G / 65536.0 / distanceLight2 * intensity;
							newColour.B += lightShadow * light->colour.B / 65536.0 / distanceLight2 * intensity;
						}
					}
				}

				if (params->ambientOcclusionEnabled
						&& params->ambientOcclusionMode == params::AOmodeMultipeRays)
				{
					sRGBAfloat AO = AmbientOcclusion(input2);
					newColour.R += AO.R * params->ambientOcclusion;
					newColour.G += AO.G * params->ambientOcclusion;
					newColour.B += AO.B * params->ambientOcclusion;
				}

				if (opacity > 1.0) opacity = 1.0;

				output.R = output.R * (1.0 - opacity) + newColour.R * opacity * fogColR / 65536.0;
				output.G = output.G * (1.0 - opacity) + newColour.G * opacity * fogColG / 65536.0;
				output.B = output.B * (1.0 - opacity) + newColour.B * opacity * fogColB / 65536.0;
				totalOpacity = opacity + (1.0 - opacity) * totalOpacity;
				output.A = opacity + (1.0 - opacity) * output.A;
			}
		}

		if (totalOpacity > 1.0) totalOpacity = 1.0;
		if (output.A > 1.0) output.A = 1.0;
		(*opacityOut).R = totalOpacity;
		(*opacityOut).G = totalOpacity;
		(*opacityOut).B = totalOpacity;

	} // next stepCount

	return output;
}
void FilterLinearKeysTemplate(
	TArray<T>& Keys,
	TArray<float>& Times,
	TArray<FTransform>& BoneAtoms,
	const TArray<float>* ParentTimes,
	const TArray<FTransform>& RawWorldBones,
	const TArray<FTransform>& NewWorldBones,
	const TArray<int32>& TargetBoneIndices,
	int32 NumFrames,
	int32 BoneIndex,
	int32 ParentBoneIndex,
	float ParentScale,
	float MaxDelta,
	float MaxTargetDelta,
	float EffectorDiffSocket,
	const TArray<FBoneData>& BoneData
	)
{
	const int32 KeyCount = Keys.Num();
	check( Keys.Num() == Times.Num() );
	check( KeyCount >= 1 );
	
	// generate new arrays we will fill with the final keys
	TArray<T> NewKeys;
	TArray<float> NewTimes;
	NewKeys.Empty(KeyCount);
	NewTimes.Empty(KeyCount);

	// Only bother doing anything if we have some keys!
	if(KeyCount > 0)
	{
		int32 LowKey = 0;
		int32 HighKey = KeyCount-1;
		int32 PrevKey = 0;
		
		// copy the low key (this one is a given)
		NewTimes.Add(Times[0]);
		NewKeys.Add(Keys[0]);

		FTransform DummyBone(FQuat::Identity, FVector(END_EFFECTOR_SOCKET_DUMMY_BONE_SIZE, END_EFFECTOR_SOCKET_DUMMY_BONE_SIZE, END_EFFECTOR_SOCKET_DUMMY_BONE_SIZE));

		float const DeltaThreshold = (BoneData[BoneIndex].IsEndEffector() && (BoneData[BoneIndex].bHasSocket || BoneData[BoneIndex].bKeyEndEffector)) ? EffectorDiffSocket : MaxTargetDelta;

		// We will test within a sliding window between LowKey and HighKey.
		// Therefore, we are done when the LowKey exceeds the range
		while (LowKey < KeyCount-1)
		{
			// high key always starts at the top of the range
			HighKey = KeyCount-1;

			// keep testing until the window is closed
			while (HighKey > LowKey+1)
			{
				// get the parameters of the window we are testing
				const float LowTime = Times[LowKey];
				const float HighTime = Times[HighKey];
				const T LowValue = Keys[LowKey];
				const T HighValue = Keys[HighKey];
				const float Range = HighTime - LowTime;
				const float InvRange = 1.0f/Range;

				// iterate through all interpolated members of the window to
				// compute the error when compared to the original raw values
				float MaxLerpError = 0.0f;
				float MaxTargetError = 0.0f;
				for (int32 TestKey = LowKey+1; TestKey< HighKey; ++TestKey)
				{
					// get the parameters of the member being tested
					float TestTime = Times[TestKey];
					T TestValue = Keys[TestKey];

					// compute the proposed, interpolated value for the key
					const float Alpha = (TestTime - LowTime) * InvRange;
					const T LerpValue = Interpolate(LowValue, HighValue, Alpha);

					// compute the error between our interpolated value and the desired value
					float LerpError = CalcDelta(TestValue, LerpValue);

					// if the local-space lerp error is within our tolerances, we will also check the
					// effect this interpolated key will have on our target end effectors
					float TargetError = -1.0f;
					if (LerpError <= MaxDelta)
					{
						// get the raw world transform for this bone (the original world-space position)
						const int32 FrameIndex = TestKey;
						const FTransform& RawBase = RawWorldBones[(BoneIndex*NumFrames) + FrameIndex];
						
						// generate the proposed local bone atom and transform (local space)
						FTransform ProposedTM = UpdateBoneAtom(BoneIndex, BoneAtoms[FrameIndex], LerpValue);

						// convert the proposed local transform to world space using this bone's parent transform
						const FTransform& CurrentParent = ParentBoneIndex != INDEX_NONE ? NewWorldBones[(ParentBoneIndex*NumFrames) + FrameIndex] : FTransform::Identity;
						FTransform ProposedBase = ProposedTM * CurrentParent;
						
						// for each target end effector, compute the error we would introduce with our proposed key
						for (int32 TargetIndex=0; TargetIndex<TargetBoneIndices.Num(); ++TargetIndex)
						{
							// find the offset transform from the raw base to the end effector
							const int32 TargetBoneIndex = TargetBoneIndices[TargetIndex];
							FTransform RawTarget = RawWorldBones[(TargetBoneIndex*NumFrames) + FrameIndex];
							const FTransform& RelTM = RawTarget.GetRelativeTransform(RawBase); 

							// forecast where the new end effector would be using our proposed key
							FTransform ProposedTarget = RelTM * ProposedBase;

							// If this is an EndEffector with a Socket attached to it, add an extra bone, to measure error introduced by effector rotation compression.
							if( BoneData[TargetIndex].bHasSocket || BoneData[TargetIndex].bKeyEndEffector )
							{
								ProposedTarget = DummyBone * ProposedTarget;
								RawTarget = DummyBone * RawTarget;
							}

							// determine the extend of error at the target end effector
							float ThisError = (ProposedTarget.GetTranslation() - RawTarget.GetTranslation()).Size();
							TargetError = FMath::Max(TargetError, ThisError); 

							// exit early when we encounter a large delta
							float const TargetDeltaThreshold = BoneData[TargetIndex].bHasSocket ? EffectorDiffSocket : DeltaThreshold;
							if( TargetError > TargetDeltaThreshold )
							{ 
								break;
							}
						}
					}

					// If the parent has a key at this time, we'll scale our error values as requested.
					// This increases the odds that we will choose keys on the same frames as our parent bone,
					// making the skeleton more uniform in key distribution.
					if (ParentTimes)
					{
						if (ParentTimes->Find(TestTime) != INDEX_NONE)
						{
							// our parent has a key at this time, 
							// inflate our perceived error to increase our sensitivity
							// for also retaining a key at this time
							LerpError *= ParentScale;
							TargetError *= ParentScale;
						}
					}
					
					// keep track of the worst errors encountered for both 
					// the local-space 'lerp' error and the end effector drift we will cause
					MaxLerpError = FMath::Max(MaxLerpError, LerpError);
					MaxTargetError = FMath::Max(MaxTargetError, TargetError);

					// exit early if we have failed in this span
					if (MaxLerpError > MaxDelta ||
						MaxTargetError > DeltaThreshold)
					{
						break;
					}
				}

				// determine if the span succeeded. That is, the worst errors found are within tolerances
				if (MaxLerpError <= MaxDelta &&
					MaxTargetError <= DeltaThreshold)
				{
					// save the high end of the test span as our next key
					NewTimes.Add(Times[HighKey]);
					NewKeys.Add(Keys[HighKey]);

					// start testing a new span
					LowKey = HighKey;
					HighKey =  KeyCount-1;
				}
				else
				{
					// we failed, shrink the test span window and repeat
					--HighKey;
				}
			}

			// if the test window is still valid, accept the high key
			if (HighKey > LowKey)
			{
				NewTimes.Add(Times[HighKey]);
				NewKeys.Add(Keys[HighKey]);
			}
			LowKey= HighKey;
		}

		// The process has ended, but we must make sure the last key is accounted for
		if (NewTimes.Last() != Times.Last() &&
			CalcDelta(Keys.Last(), NewKeys.Last()) >= MaxDelta )
		{
			NewTimes.Add(Times.Last());
			NewKeys.Add(Keys.Last());
		}

		// return the new key set to the caller
		Times= NewTimes;
		Keys= NewKeys;
	}
}
Example #6
0
	void expand_macro_one(StringA& str)
	{
		if( str.IsBlockNull() )
			return ;

		//loop
		do {
			//find
			uintptr uCount = 0;
			uintptr uStart = 0;
			do {
				auto iter(StringHelper::Find(str, '{', uStart));
				if( iter.IsNull() )
					break;
				intptr delta = iter.CalcDelta(str.GetAt(uStart));
				if( iter != str.GetBegin() ) {
					auto iter1(iter);
					iter1.MovePrev();
					// \{
					if( iter1.get_Value() == '\\' ) {
						uStart += (delta + 1);
						continue;
					}
				}
				uStart += (delta + 1);
				uCount ++;
				uintptr uLeftC = uStart;
				do {
					auto iterE(StringHelper::Find(str, '}', uStart));
					if( iterE.IsNull() ) {
						uCount --;
						break;
					}
					delta = iterE.CalcDelta(str.GetAt(uStart));
					auto iter1(iterE);
					iter1.MovePrev();
					// \}
					if( iter1.get_Value() == '\\' ) {
						uStart += (delta + 1);
						continue;
					}
					uStart += (delta + 1);
					intptr len = iterE.CalcDelta(iter);
					//empty
					if( len <= 1 ) {
						uCount --;
						break;
					}
					//macro name
					StringA strMacro(StringHelper::MakeEmptyString<CharA>(MemoryHelper::GetCrtMemoryManager()));  //may throw
					StringUtilHelper::Sub(str, uLeftC, len - 1, strMacro);  //may throw
					ConstStringA c_macro_name(StringUtilHelper::To_ConstString(strMacro));
					StringA strV;
					uint id = m_macro_table.get_ID(c_macro_name);
					if( id == 0 ) {
						id = m_token_table.get_ID(c_macro_name);
						if( id == 0 ) {
							uCount --;
							break;
						}
						strV = m_token_regex[id - m_token_table.GetMinID()].get_Value();
					}
					else {
						strV = m_macro_regex[id - m_macro_table.GetMinID()].get_Value();
					}
					iter.get_Value() = '(';
					iterE.get_Value() = ')';
					StringHelper::Delete(uLeftC, len - 1, str);
					StringUtilHelper::Insert(uLeftC, strV, str);  //may throw
					//now iterators are invalid
					uStart = uLeftC + strV.GetLength() + 1;
					break;
				} while(true);
			} while(true);
			if( uCount == 0 )
				break;
		} while(true);
	}
Example #7
0
cRenderWorker::sRayRecursionOut cRenderWorker::RayRecursion(sRayRecursionIn in,
		sRayRecursionInOut &inOut)
{
	sRayMarchingOut rayMarchingOut;

	*inOut.rayMarchingInOut.buffCount = 0;

	//trace the light in given direction
	CVector3 point = RayMarching(in.rayMarchingIn, &inOut.rayMarchingInOut, &rayMarchingOut);

	sRGBAfloat resultShader = in.resultShader;
	sRGBAfloat objectColour = in.objectColour;

	//here will be called branch for RayRecursion();

	sRGBAfloat objectShader;
	objectShader.A = 0.0;
	sRGBAfloat backgroundShader;
	sRGBAfloat volumetricShader;
	sRGBAfloat specular;

	//prepare data for shaders
	CVector3 lightVector = shadowVector;
	sShaderInputData shaderInputData;
	shaderInputData.distThresh = rayMarchingOut.distThresh;
	shaderInputData.delta = CalcDelta(point);
	shaderInputData.lightVect = lightVector;
	shaderInputData.point = point;
	shaderInputData.viewVector = in.rayMarchingIn.direction;
	shaderInputData.lastDist = rayMarchingOut.lastDist;
	shaderInputData.depth = rayMarchingOut.depth;
	shaderInputData.stepCount = *inOut.rayMarchingInOut.buffCount;
	shaderInputData.stepBuff = inOut.rayMarchingInOut.stepBuff;
	shaderInputData.invertMode = in.calcInside;
	shaderInputData.objectId = rayMarchingOut.objectId;

	cObjectData objectData = data->objectData[shaderInputData.objectId];
	shaderInputData.material = &data->materials[objectData.materialId];

	sRGBAfloat reflectShader = in.resultShader;
	double reflect = shaderInputData.material->reflectance;

	sRGBAfloat transparentShader = in.resultShader;
	double transparent = shaderInputData.material->transparencyOfSurface;
	sRGBfloat transparentColor = sRGBfloat(shaderInputData.material->transparencyInteriorColor.R / 65536.0,
																				 shaderInputData.material->transparencyInteriorColor.G / 65536.0,
																				 shaderInputData.material->transparencyInteriorColor.B / 65536.0);
	resultShader.R = transparentColor.R;
	resultShader.G = transparentColor.G;
	resultShader.B = transparentColor.B;

	CVector3 vn;

	//if found any object
	if (rayMarchingOut.found)
	{
		//calculate normal vector
		vn = CalculateNormals(shaderInputData);
		shaderInputData.normal = vn;

		if(shaderInputData.material->diffusionTexture.IsLoaded())
			shaderInputData.texDiffuse = TextureShader(shaderInputData, cMaterial::texDiffuse, shaderInputData.material);
		else
			shaderInputData.texDiffuse = sRGBfloat(1.0, 1.0, 1.0);

		if(shaderInputData.material->normalMapTexture.IsLoaded())
		{
			vn = NormalMapShader(shaderInputData);
		}

		//prepare refraction values
		double n1, n2;
		if (in.calcInside) //if trance is inside the object
		{
			n1 = shaderInputData.material ->transparencyIndexOfRefraction; //reverse refractive indices
			n2 = 1.0;
		}
		else
		{
			n1 = 1.0;
			n2 = shaderInputData.material ->transparencyIndexOfRefraction;
			;
		}

		if (inOut.rayIndex < reflectionsMax)
		{

			//calculate refraction (transparency)
			if (transparent > 0.0)
			{
				sRayRecursionIn recursionIn;
				sRayMarchingIn rayMarchingIn;
				sRayMarchingInOut rayMarchingInOut;

				//calculate direction of refracted light
				CVector3 newDirection = RefractVector(vn, in.rayMarchingIn.direction, n1, n2);

				//move starting point a little
				CVector3 newPoint = point + in.rayMarchingIn.direction * shaderInputData.distThresh * 1.0;

				//if is total internal reflection the use reflection instead of refraction
				bool internalReflection = false;
				if (newDirection.Length() == 0.0)
				{
					newDirection = ReflectionVector(vn, in.rayMarchingIn.direction);
					newPoint = point + in.rayMarchingIn.direction * shaderInputData.distThresh * 1.0;
					internalReflection = true;
				}

				//preparation for new recursion
				rayMarchingIn.binaryEnable = true;
				rayMarchingIn.direction = newDirection;
				rayMarchingIn.maxScan = params->viewDistanceMax;
				rayMarchingIn.minScan = 0.0;
				rayMarchingIn.start = newPoint;
				rayMarchingIn.invertMode = !in.calcInside || internalReflection;
				recursionIn.rayMarchingIn = rayMarchingIn;
				recursionIn.calcInside = !in.calcInside || internalReflection;
				recursionIn.resultShader = resultShader;
				recursionIn.objectColour = objectColour;

				//setup buffers for ray data
				inOut.rayIndex++; //increase recursion index
				rayMarchingInOut.buffCount = &rayBuffer[inOut.rayIndex].buffCount;
				rayMarchingInOut.stepBuff = rayBuffer[inOut.rayIndex].stepBuff;
				inOut.rayMarchingInOut = rayMarchingInOut;

				//recursion for refraction
				sRayRecursionOut recursionOutTransparent = RayRecursion(recursionIn, inOut);
				transparentShader = recursionOutTransparent.resultShader;
			}

			//calculate reflection
			if (reflect > 0.0)
			{
				sRayRecursionIn recursionIn;
				sRayMarchingIn rayMarchingIn;
				sRayMarchingInOut rayMarchingInOut;

				//calculate new direction of reflection
				CVector3 newDirection = ReflectionVector(vn, in.rayMarchingIn.direction);
				CVector3 newPoint = point + newDirection * shaderInputData.distThresh;

				//prepare for new recursion
				rayMarchingIn.binaryEnable = true;
				rayMarchingIn.direction = newDirection;
				rayMarchingIn.maxScan = params->viewDistanceMax;
				rayMarchingIn.minScan = 0.0;
				rayMarchingIn.start = newPoint;
				rayMarchingIn.invertMode = false;
				recursionIn.rayMarchingIn = rayMarchingIn;
				recursionIn.calcInside = false;
				recursionIn.resultShader = resultShader;
				recursionIn.objectColour = objectColour;

				//setup buffers for ray data
				inOut.rayIndex++; //increase recursion index
				rayMarchingInOut.buffCount = &rayBuffer[inOut.rayIndex].buffCount;
				rayMarchingInOut.stepBuff = rayBuffer[inOut.rayIndex].stepBuff;
				inOut.rayMarchingInOut = rayMarchingInOut;

				//recursion for reflection
				sRayRecursionOut recursionOutReflect = RayRecursion(recursionIn, inOut);
				reflectShader = recursionOutReflect.resultShader;

			}
			if (transparent > 0.0) inOut.rayIndex--; //decrease recursion index
			if (reflect > 0.0) inOut.rayIndex--; //decrease recursion index
		}

		shaderInputData.normal = vn;

		//calculate effects for object surface
		objectShader = ObjectShader(shaderInputData, &objectColour, &specular);

		//calculate reflectance according to Fresnel equations
		double reflectance = 1.0;
		double reflectanceN = 1.0;

		if (shaderInputData.material->fresnelReflectance)
		{
			reflectance = Reflectance(vn, in.rayMarchingIn.direction, n1, n2);
			if (reflectance < 0.0) reflectance = 0.0;
			if (reflectance > 1.0) reflectance = 1.0;
			reflectanceN = 1.0 - reflectance;
		}

		//combine all results
		resultShader.R = (objectShader.R + specular.R);
		resultShader.G = (objectShader.G + specular.G);
		resultShader.B = (objectShader.B + specular.B);

		if (reflectionsMax > 0)
		{
			sRGBfloat reflectDiffused;
			double diffIntes = shaderInputData.material->diffussionTextureIntensity;
			double diffIntesN = 1.0 - diffIntes;
			reflectDiffused.R = reflect * shaderInputData.texDiffuse.R * diffIntes + reflect * diffIntesN;
			reflectDiffused.G = reflect * shaderInputData.texDiffuse.G * diffIntes + reflect * diffIntesN;
			reflectDiffused.B = reflect * shaderInputData.texDiffuse.B * diffIntes + reflect * diffIntesN;

			resultShader.R = transparentShader.R * transparent * reflectanceN
					+ (1.0 - transparent * reflectanceN) * resultShader.R;
			resultShader.G = transparentShader.G * transparent * reflectanceN
					+ (1.0 - transparent * reflectanceN) * resultShader.G;
			resultShader.B = transparentShader.B * transparent * reflectanceN
					+ (1.0 - transparent * reflectanceN) * resultShader.B;

			resultShader.R = reflectShader.R * reflectDiffused.R * reflectance
					+ (1.0 - reflectDiffused.R * reflectance) * resultShader.R;
			resultShader.G = reflectShader.G * reflectDiffused.G * reflectance
					+ (1.0 - reflectDiffused.G * reflectance) * resultShader.G;
			resultShader.B = reflectShader.B * reflectDiffused.B * reflectance
					+ (1.0 - reflectDiffused.B * reflectance) * resultShader.B;
		}
		if(resultShader.R < 0.0) resultShader.R = 0.0;
		if(resultShader.G < 0.0) resultShader.G = 0.0;
		if(resultShader.B < 0.0) resultShader.B = 0.0;
	}
	else //if object not found then calculate background
	{
		backgroundShader = BackgroundShader(shaderInputData);
		resultShader = backgroundShader;
		shaderInputData.depth = 1e20;
		vn =  mRot.RotateVector(CVector3(0.0, -1.0, 0.0));
	}

	sRGBAfloat opacityOut;

	if (in.calcInside) //if the object interior is traced, then the absorption of light has to be calculated
	{
		for (int index = shaderInputData.stepCount - 1; index > 0; index--)
		{
			double step = shaderInputData.stepBuff[index].step;

			//CVector3 point = shaderInputData.stepBuff[index].point;
			//shaderInputData.point = point;
			//sRGBAfloat color = SurfaceColour(shaderInputData);
			//transparentColor.R = color.R;
			//transparentColor.G = color.G;
			//transparentColor.B = color.B;

			double opacity = -log(shaderInputData.material ->transparencyOfInterior) * step;
			if (opacity > 1.0) opacity = 1.0;

			resultShader.R = opacity * transparentColor.R + (1.0 - opacity) * resultShader.R;
			resultShader.G = opacity * transparentColor.G + (1.0 - opacity) * resultShader.G;
			resultShader.B = opacity * transparentColor.B + (1.0 - opacity) * resultShader.B;
		}
	}
	else //if now is outside the object, then calculate all volumetric effects like fog, glow...
	{
		volumetricShader = VolumetricShader(shaderInputData, resultShader, &opacityOut);
		resultShader = volumetricShader;
	}

	//prepare final result
	sRayRecursionOut out;
	out.point = point;
	out.rayMarchingOut = rayMarchingOut;
	out.objectColour = objectColour;
	out.resultShader = resultShader;
	out.found = (shaderInputData.depth == 1e20) ? false : true;
	out.fogOpacity = opacityOut.R;
	out.normal = vn;

	return out;
}