Перейти к публикации
  • Сейчас на странице   Всего пользователей: 0   (0 пользователей, 0 гостей)

Rooster

Программирование, т. 7

  

536 пользователей проголосовало

У вас нет прав на голосование в этом опросе, или на просмотр результатов опроса. Пожалуйста, войдите или зарегистрируйтесь для голосования в опросе.

Рекомендованные сообщения

Мне одному кажется, что Crierr какой-то токсик мудила, который спорит ради спора?

просто защищает своё решение, потому что в данный момент оно ему кажется правильным

большая часть паттернов проектирования  зародилась благодаря тому, что проекты становились сложнее, разработчиков в них становилось всё больше и одни сменяли других, код превращался в вермишель а небольшие изменения могли случайно убить архитектора 

криер пока работает один(как я понял), ему не приходится участвовать в атракционе "пойми как работает чужой код за 5 минут", хуярь что бы работало и ни о чём не парься

Поделиться сообщением


Ссылка на сообщение

Я ничего не предлагаю, я же написал, каждый дрочит как хочет. Я не считаю, что твой код плохой, но это не ООП (имхо). Это типичный процедурный код, как 30 лет назад. Может быть в той сфере где ты работешь - так принято и это ок, но лично мне (да и судя по тому, что уже идет 6-ая страница обсуждения не только мне) такое писать моветон, потому что мне такое читать трудно, и длинные переменные читать трудно, и вложенные ифы читать трудно. Но может я аутист, тут такое.

Нет ты именно предложи как выглядит, каждый дрочит как хочет странная херня которая не интересна.

Вот у меня есть платформа и одна из функций ее, обновить края, края в данном случае 2 координаты, где земля заканчивается.

Есть 200 функция которую пд и софтина какая считает слишком большой, что ты предлагаешь делать?

 

Мне одному кажется, что Crierr какой-то токсик мудила, который спорит ради спора?

просто защищает своё решение, потому что в данный момент оно ему кажется правильным

большая часть паттернов проектирования  зародилась благодаря тому, что проекты становились сложнее, разработчиков в них становилось всё больше и одни сменяли других, код превращался в вермишель а небольшие изменения могли случайно убить архитектора 

криер пока работает один(как я понял), ему не приходится участвовать в атракционе "пойми как работает чужой код за 5 минут", хуярь что бы работало и ни о чём не парься

 

я думаю что размер != сложность и прятать 10 строк кода в отдельную функцию ни к чему не приводит кроме того что вы уменьшаете количество строк, метрику, а функционально ничего не меняется, такое себе Local Row Count Fallacy - когда меньше строк в любом выбраном месте всегда лучше.

Поделиться сообщением


Ссылка на сообщение

Так тебе не только о размере говорят, да и твердят тебе больше не о сложности, а о читабельности

Поделиться сообщением


Ссылка на сообщение

криер, в твоем коде много чего можно улучшить, тебе о многом написали уже

зачем ты дефаешь свой код будто он идеальный?

Поделиться сообщением


Ссылка на сообщение

Так тебе не только о размере говорят, да и твердят тебе больше не о сложности, а о читабельности

там из читабельности был только ifelse на все тело функци, плюс ты можешь говорить о читабельности кода на движке которого не знаешь, как так?

Поделиться сообщением


Ссылка на сообщение

 

Так тебе не только о размере говорят, да и твердят тебе больше не о сложности, а о читабельности

там из читабельности был только ifelse на все тело функци, плюс ты можешь говорить о читабельности кода на движке которого не знаешь, как так?

 

НУ СЕЛ БЫ УЖЕ ОТРЕФАКТОРИЛ А НЕ ПОСТЫ НА ПД НАБИВАЛ  :avtorklif:  :avtorklif:  :avtorklif:

fessnik понравилось это

Поделиться сообщением


Ссылка на сообщение

криер, в твоем коде много чего можно улучшить, тебе о многом написали уже

зачем ты дефаешь свой код будто он идеальный?

а что мне тупо слушать что вы говорите? Я защащаю свою точку зрения пока не увижу лучше, пока было пару комментов которые были объективно лучше, например проверка вначале и сходу ретурн, я сделал так в нескольких местах, мне действительно больше нравится, но больше ничего нормального я не слышал.

Поделиться сообщением


Ссылка на сообщение
(изменено)

Я не знаю архитектуру твоего проекта, что б зарефакторить его. Я когда писал свой первый проект - у меня тоже была такая каша, я подумал, что нужно поменять, что б код был более читаем и понятен, в итоге пришлось менять чуть более глобально нежели просто разбитие на модули.

 

Насколько я слышал, в крестах функции это FCC, попробуй свою проверку стейта объекта как-то унифицировать, передавая как один из параметров функцию, которая будет выполнять часть логики ифов на более глобальнгом уровне. Перепиши базовые методы, сделай их более общими. Сложно что-то посоветовать зная лишь вырванный из контекста кусок кода.


Изменено пользователем sonac

Поделиться сообщением


Ссылка на сообщение

программисты, нид хел с организацией инфраструктуры

 

есть 2 программы, одна генерирует большой объем данных (около 8-10 гигабайт) которые обновляются каждую неделю, вторая эти данные использует. Вопрос: как хранить данные от первой софтины? В текущий момент эти данные хранятся в репозитории программы2, но объем разрастается и апдейтить по часу уже не очень прикольно.  


Перегенерация не прокатит, так как это занимает по 2 дня : )

Поделиться сообщением


Ссылка на сообщение

AMQP

 

ебашь шину сообщений и в софтины пиши адаптеры к шине, одна чтоб отправляла, другая подписывалась

Поделиться сообщением


Ссылка на сообщение

 

 

не знаю архитектуру твоего проекта, что б зарефакторить его.

Вот  в этом и проблема, я вбросил сюда с вопросом, "есть что скзать?" и в ответ получил много проблем бла бла бла.

И сейчас юзеры по очереди врываются и говорят, много проблем, раньше говорили а ты защищаешь код как мудак он идеален бла бла бла токсичный юзер пиздос crierr.

тогда как объективно никто ничего не гвоорит уже сутки почти, а когда говорит то это слишком сложно потому что мнгого.

 

bool AWalkingPlatform::UpdateBoundaries()
{
	if (GetWorld())
	{
		return false;
	}
	bool bSuccessfulTraceRoutine = false;
	FVector traceHitResult(ForceInit);
	// Lambda for trace routine.
	auto traceRoutine = [&](FVector& OutTraceRoutineHitResult, const FVector& InSideTraceStepOffset) -> bool
	{
		bool bTraceHit = false;
		bool bHitOnceBefore = false;
		OutTraceRoutineHitResult = FVector::ZeroVector;
		FHitResult boundariesTraceHitResult(ForceInit);
		FHitResult wallTraceHitResult(ForceInit);
		FVector floorTraceStart;
		FVector floorTraceEnd;
		const FCollisionShape traceShape = TraceShapeEnumFunctions::MakeShapeForTrace(TraceShapeType, TraceShapeSize);
		FCollisionQueryParams groundTraceParams;
		groundTraceParams.bTraceAsyncScene = true;
		FCollisionQueryParams wallTraceParams = groundTraceParams;
		if (bDrawBoundarySearchTrace)
		{
			const FName traceTag("InitTraceTag");
			GetWorld()->DebugDrawTraceTag = traceTag;
			groundTraceParams.TraceTag = traceTag;
			if (bDrawBoundarySearchWallTrace)
			{
				wallTraceParams.TraceTag = traceTag;
			}
		}
		else
		{
			if (bDrawBoundarySearchWallTrace)
			{
				const FName traceTag("InitTraceTag");
				GetWorld()->DebugDrawTraceTag = traceTag;
				wallTraceParams.TraceTag = traceTag;
			}
		}
		for (int32 i = 0; i < BoundaryTraceSideStepLimit; ++i)
		{
			boundariesTraceHitResult.Init();
			floorTraceStart = GetActorLocation() + InSideTraceStepOffset * i;
			floorTraceStart.Z = floorTraceStart.Z + BoundaryTraceStartZOffset;

			// Trace sideways to find is there is a wall on the way.
			if (bCheckWallsOnBoundariesUpdate)
			{
				FVector wallTraceEnd = TraceShapeEnumFunctions::GetExtent(traceShape, TraceShapeType);
				wallTraceEnd.X = wallTraceEnd.X + floorTraceStart.X + 2.f * InSideTraceStepOffset.X;
				wallTraceEnd.Y = wallTraceEnd.Y + floorTraceStart.Y + 2.f * InSideTraceStepOffset.Y;
				wallTraceEnd.Z = floorTraceStart.Z;
				bTraceHit = GetWorld()->SweepSingleByChannel(boundariesTraceHitResult
					, FVector(GetActorLocation().X, GetActorLocation().Y, floorTraceStart.Z)
					, wallTraceEnd
					, FQuat(), ECollisionChannel::ECC_Visibility, traceShape, wallTraceParams);
				if (bTraceHit)
				{
					break;
				}
			}

			floorTraceEnd.Set(floorTraceStart.X, floorTraceStart.Y, floorTraceStart.Z - BoundaryTraceLengthZ);
			// Trace for floor
			if (TraceShapeType == ETraceShape::ETS_Line)
			{
				bTraceHit = GetWorld()->LineTraceSingleByChannel(boundariesTraceHitResult
					, floorTraceStart
					, floorTraceEnd
					, ECollisionChannel::ECC_Visibility, groundTraceParams);
				if (bTraceHit)
				{
					OutTraceRoutineHitResult = boundariesTraceHitResult.Location;
					bHitOnceBefore = true;
				}
				else
				{
					break;
				}
			}
			else
			{
				bTraceHit = GetWorld()->SweepSingleByChannel(boundariesTraceHitResult
					, floorTraceStart
					, floorTraceEnd
					, FQuat(), ECollisionChannel::ECC_Visibility, traceShape, groundTraceParams);
				if (bTraceHit)
				{
					OutTraceRoutineHitResult = boundariesTraceHitResult.ImpactPoint;
					bHitOnceBefore = true;
				}
				else
				{
					break;
				}
			}
		} //for (int32 i = 0; i < BoundaryTraceSideStepLimit; ++i)

		// Reset Debug Draw
		if (bDrawBoundarySearchTrace || bDrawBoundarySearchWallTrace)
		{
			GetWorld()->DebugDrawTraceTag = NAME_None;
		}
		return bHitOnceBefore;
	}; //~ traceRoutine

	auto resetBoundaries = [&]()
	{
		LeftBoundary.Reset();
		RightBoundary.Reset();
		LeftBoundaryLocation = FVector::ZeroVector;
		RightBoundaryLocation = FVector::ZeroVector;
		if (LeftBoundaryGuideSphere)
		{
			LeftBoundaryGuideSphere->SetWorldLocation(GetActorLocation());
		}
		if (RightBoundaryGuideSphere)
		{
			RightBoundaryGuideSphere->SetWorldLocation(GetActorLocation());
		}
	}; //~ resetBoundaries

	// Trace Left
	bSuccessfulTraceRoutine = traceRoutine(traceHitResult, LeftDirection * BoundaryTraceStepLength);
	if (bSuccessfulTraceRoutine)
	{
		LeftBoundary.SetNodeLocation(traceHitResult + TraceResutlToBoundaryOffsetLeft);
		LeftBoundaryLocation = LeftBoundary.GetNodeLocation();
		if (LeftBoundaryGuideSphere)
		{
			LeftBoundaryGuideSphere->SetWorldLocation(LeftBoundaryLocation);
		}
	} //bSuccessfulTraceRoutine
	else
	{
		resetBoundaries();
		return false;
	}

	// Trace Right
	bSuccessfulTraceRoutine = traceRoutine(traceHitResult, RightDirection * BoundaryTraceStepLength);
	if (bSuccessfulTraceRoutine)
	{
		RightBoundary.SetNodeLocation(traceHitResult + TraceResutlToBoundaryOffsetRight);
		RightBoundaryLocation = RightBoundary.GetNodeLocation();
		if (RightBoundaryGuideSphere)
		{
			RightBoundaryGuideSphere->SetWorldLocation(RightBoundaryLocation);
		}
		if (bDrawBoundaryLocation)
		{
			DrawDebugSphere(GetWorld(), LeftBoundary.GetNodeLocation(), 20.f, 12, FColor(255, 0, 0), false, BoundaryLocationDrawLifetime);
			DrawDebugSphere(GetWorld(), RightBoundary.GetNodeLocation(), 20.f, 12, FColor(0, 0, 255), false, BoundaryLocationDrawLifetime);
		}
		return true;
	}
	else
	{
		resetBoundaries();
		return false;
	}
} 

 


Вот есть что сказать, вот тыкнуть в код и сказать ВОТ ТАК НЕ НАДО ДЕЛАТЬ ПОТОМУ ЧТО ... А НАДО ВОТ ТАК.
Я сильно сомневаюсь ибо опять же специфика проекта, как ты скзал.

Поделиться сообщением


Ссылка на сообщение

Да делай как хочешь, чувак. Твой код могут судить только люди работающие с тобой или знающие твой проект. Ты кидаешь кусок вырвиглазного кода, который одному тебе известно, что делает и "ЧТО НЕ ТАК?". Кидай линк на гит, где весь проект лежит, тогда уже и можно будет более менее объективно критиковать, а рефакторить один метод не зная всей архитектуры - это хуйня. 

Поделиться сообщением


Ссылка на сообщение

 

 

Ты кидаешь кусок вырвиглазного кода

Поделиться сообщением


Ссылка на сообщение
(изменено)

https://www.codeproject.com/Articles/768052/Golden-Rules-Of-Good-OOP

 

Даже твои куски нарушают как минимум 4 из 10 пунктов, а если увидеть весь проект целиком - то я уверен, что там все еще хуже будет. Я уж молчу про SOLID, и судя по твоим методам, в проекте нарушаются как минимум SRP, ISP (хотя я не видел твоих интерфейсов, но судя по тому объему работы который выполняет лишь один метод можно сделать вывод) и DIP.


После этого пишешь "бля, а как по-другому", а так, что не зная всей архитектуры тебе врядли кто-то подскажет как переписать код на нормальный.


Изменено пользователем sonac

Поделиться сообщением


Ссылка на сообщение

 

 

Даже твои куски нарушают как минимум 4 из 10 пунктов
 

какие именно?


Я ктстати вообще не понимаю при чем тут ооп, объект в мире сам обновляет свои данные по реквесту извне, все.
Ты уже второй пост ссылаешься на ооп и кучу каких то интересных слов вбрасываешь.

Поделиться сообщением


Ссылка на сообщение

Очевидно 1, 2, 9, 10

Поделиться сообщением


Ссылка на сообщение

1 хуйня - этот класс обновляет одну частичку своих данных и все и эта функция и есть обновление этих данных, она одна единственная которая обновляет эти данные таким образом, это рутина.
2 хуйня - тут эта функция делает A->B->C->D шаги которые есть вызов одной другой функции каждый, так как это и есть обновление шаг B может быть сделан с дополнительным параметром который проверяется на if.
9 - один фор ич луп который вызывает метод и если он не фейлится вызывает другой
10 - хуйня, no long methods лол

Я прочел всю ссылочку, вот сильное чувство что он гавкает совершенно в другую сторону и на какой то особый паттерн который ему не нравится.
Вот еще кусок кода, сколько это нарушает? точно no long methods, так же ифов дохера, может еще что?

 

bool UParticleModuleSpawnPerUnit::GetSpawnAmount(FParticleEmitterInstance* Owner, 
	int32 Offset, float OldLeftover, float DeltaTime, int32& Number, float& Rate)
{
	check(Owner);

	bool bMoved = false;
	FParticleSpawnPerUnitInstancePayload* SPUPayload = NULL;
	float NewTravelLeftover = 0.0f;

	float ParticlesPerUnit = SpawnPerUnit.GetValue(Owner->EmitterTime, Owner->Component) / UnitScalar;
	// Allow for PPU of 0.0f to allow for 'turning off' an emitter when moving
	if (ParticlesPerUnit >= 0.0f)
	{
		float LeftoverTravel = 0.0f;
		uint8* InstData = Owner->GetModuleInstanceData(this);
		if (InstData)
		{
			SPUPayload = (FParticleSpawnPerUnitInstancePayload*)InstData;
			LeftoverTravel = SPUPayload->CurrentDistanceTravelled;
		}

		// Calculate movement delta over last frame, include previous remaining delta
		FVector TravelDirection = Owner->Location - Owner->OldLocation;
		FVector RemoveComponentMultiplier(
			bIgnoreMovementAlongX ? 0.0f : 1.0f,
			bIgnoreMovementAlongY ? 0.0f : 1.0f,
			bIgnoreMovementAlongZ ? 0.0f : 1.0f
			);
		TravelDirection *= RemoveComponentMultiplier;

		// Calculate distance traveled
		float TravelDistance = TravelDirection.Size();
		if (MaxFrameDistance > 0.0f)
		{
			if (TravelDistance > MaxFrameDistance)
			{
				// Clear it out!
				//@todo. Need to 'shift' the start point closer so we can still spawn...
				TravelDistance = 0.0f;
				if ( SPUPayload )
				{
					SPUPayload->CurrentDistanceTravelled = 0.0f;
				}
			}
		}

		if (TravelDistance > 0.0f)
		{
			if (TravelDistance > (MovementTolerance * UnitScalar))
			{
				bMoved = true;
			}

			// Normalize direction for use later
			TravelDirection.Normalize();

			// Calculate number of particles to emit
			float NewLeftover = (TravelDistance + LeftoverTravel) * ParticlesPerUnit;
			Number = FMath::FloorToInt(NewLeftover);
			float InvDeltaTime = (DeltaTime > 0.0f) ? 1.0f / DeltaTime : 0.0f;
			Rate = Number * InvDeltaTime;
			NewTravelLeftover = (TravelDistance + LeftoverTravel) - (Number * UnitScalar);
			if (SPUPayload)
			{
				SPUPayload->CurrentDistanceTravelled = FMath::Max<float>(0.0f, NewTravelLeftover);
			}

		}
		else
		{
			Number = 0;
			Rate = 0.0f;
		}
	}
	else
	{
		Number = 0;
		Rate = 0.0f;
	}

	if (bIgnoreSpawnRateWhenMoving == true)
	{
		if (bMoved == true)
		{
			return false;
		}
		return true;
	}

	return bProcessSpawnRate;
} 

 

 

Поделиться сообщением


Ссылка на сообщение

 

не знаю архитектуру твоего проекта, что б зарефакторить его.

И сейчас юзеры по очереди врываются и говорят, много проблем, раньше говорили а ты защищаешь код как мудак он идеален бла бла бла токсичный юзер пиздос crierr.

 

 

Токсичный и мудак? Скорей всего)

А по коду я ничего тебе и не говорил)

Поделиться сообщением


Ссылка на сообщение

Ну если ты считаешь, что эти правила хуйня - то че ты тут спрашиваешь советов? Выкладывай код где сидят такие-же братюни как и ты и облизывайте там друг-друга за свои методы в 200 строчек.

Поделиться сообщением


Ссылка на сообщение

@@madvlaydin
можешь проверить это на совтинке, мне просто интересно сколько нащитает апдейт колес из библиотеки ибо это реальная функция из реального места.

 

не советую открывать

 

void processSuspTireWheels
(const PxU32 startWheelIndex, 
 const ProcessSuspWheelTireConstData& constData, const ProcessSuspWheelTireInputData& inputData, 
 ProcessSuspWheelTireOutputData& outputData)
{
	PX_SIMD_GUARD; //tzRaw.normalize(); in computeTireDirs threw a denorm exception on osx
	
#if PX_DEBUG_VEHICLE_ON
	PX_ASSERT(0==(startWheelIndex & 3));
#endif

#if PX_DEBUG_VEHICLE_ON
	zeroGraphDataWheels(startWheelIndex,PxVehicleWheelGraphChannel::eJOUNCE);
	zeroGraphDataWheels(startWheelIndex,PxVehicleWheelGraphChannel::eSUSPFORCE);
	zeroGraphDataWheels(startWheelIndex,PxVehicleWheelGraphChannel::eTIRELOAD);
	zeroGraphDataWheels(startWheelIndex,PxVehicleWheelGraphChannel::eNORMALIZED_TIRELOAD);
	zeroGraphDataWheels(startWheelIndex,PxVehicleWheelGraphChannel::eNORM_TIRE_LONG_FORCE);
	zeroGraphDataWheels(startWheelIndex,PxVehicleWheelGraphChannel::eNORM_TIRE_LAT_FORCE);
	zeroGraphDataWheels(startWheelIndex,PxVehicleWheelGraphChannel::eTIRE_LONG_SLIP);
	zeroGraphDataWheels(startWheelIndex,PxVehicleWheelGraphChannel::eTIRE_LAT_SLIP);
	zeroGraphDataWheels(startWheelIndex,PxVehicleWheelGraphChannel::eTIRE_FRICTION);
#endif

	//Unpack the logically constant data.
	const PxVec3& gravity=constData.gravity;
	const PxF32 timeFraction=constData.timeFraction;
	const PxF32 timeStep=constData.subTimeStep;
	const PxF32 recipTimeStep=constData.recipSubTimeStep;
	const PxF32 recipGravityMagnitude=constData.recipGravityMagnitude;
	const PxF32 gravityMagnitude=constData.gravityMagnitude;
	const bool isTank=constData.isTank;
	const PxF32 minLongSlipDenominator=constData.minLongSlipDenominator;

	//Unpack the input data (physically constant data).
	const PxVehicleWheels4SimData& wheelsSimData=*inputData.vehWheels4SimData;
	const PxVehicleWheels4DynData& wheelsDynData=*inputData.vehWheels4DynData;
	const PxVehicleTireForceCalculator4& tireForceCalculator=*inputData.vehWheels4TireForceCalculator;
	const PxVehicleTireLoadFilterData& tireLoadFilterData=*inputData.vehWheels4TireLoadFilterData;
	//More constant data describing the 4 wheels under consideration.
	const PxF32* PX_RESTRICT tireRestLoads=wheelsSimData.getTireRestLoadsArray();
	const PxF32* PX_RESTRICT recipTireRestLoads=wheelsSimData.getRecipTireRestLoadsArray();
	//Compute the right direction for later.
	const PxTransform& carChassisTrnsfm=inputData.carChassisTrnsfm;
	const PxVec3 latDir=inputData.carChassisTrnsfm.rotate(gRight);
	//Unpack the linear and angular velocity of the rigid body.
	const PxVec3& carChassisLinVel=inputData.carChassisLinVel;
	const PxVec3& carChassisAngVel=inputData.carChassisAngVel;
	//Wheel local poses
	const PxQuat* PX_RESTRICT wheelLocalPoseRotations = inputData.wheelLocalPoseRotations;
	const PxF32* PX_RESTRICT wheelThetas = inputData.wheelThetas;
	//Inputs (accel, steer, brake).
	const bool isIntentionToAccelerate=inputData.isIntentionToAccelerate;
	const PxF32* steerAngles=inputData.steerAngles;
	const bool* isBrakeApplied=inputData.isBrakeApplied;
	const bool* isAccelApplied=inputData.isAccelApplied;
	//Disabled/enabled wheel states.
	const bool* activeWheelStates=inputData.activeWheelStates;
	//Current low forward/side speed timers.  Note that the updated timers
	//are stored in newLowForwardSpeedTimers and newLowSideSpeedTimers.
	const PxF32* PX_RESTRICT lowForwardSpeedTimers=wheelsDynData.mTireLowForwardSpeedTimers;
	const PxF32* PX_RESTRICT lowSideSpeedTimers=wheelsDynData.mTireLowSideSpeedTimers;
	//Susp jounces and speeds from previous call to processSuspTireWheels.
	const PxF32* PX_RESTRICT prevJounces=wheelsDynData.mJounces;

	//Unpack the output data (the data we are going to compute).
	//Start with the data stored for reporting to PxVehicleWheelQueryResult.
	//PxVec3* suspLineStarts=outputData.suspLineStarts;
	//PxVec3* suspLineDirs=outputData.suspLineDirs;
	//PxF32* suspLineLengths=outputData.suspLineLengths;
	bool* isInAirs=outputData.isInAir;	
	PxActor** tireContactActors=outputData.tireContactActors;
	PxShape** tireContactShapes=outputData.tireContactShapes;
	PxMaterial** tireSurfaceMaterials=outputData.tireSurfaceMaterials;
	PxU32* tireSurfaceTypes=outputData.tireSurfaceTypes;
	PxVec3* tireContactPoints=outputData.tireContactPoints;
	PxVec3* tireContactNormals=outputData.tireContactNormals;
	PxF32* frictions=outputData.frictions;
	PxF32* jounces=outputData.jounces;
	PxF32* suspensionSpringForces=outputData.suspensionSpringForces;
	PxVec3* tireLongitudinalDirs=outputData.tireLongitudinalDirs;
	PxVec3* tireLateralDirs=outputData.tireLateralDirs;
	PxF32* longSlips=outputData.longSlips;
	PxF32* latSlips=outputData.latSlips;
	//Now unpack the forward speeds that are used later to blend the integrated wheel 
	//rotation angle between rolling speed and computed speed when the wheel rotation 
	//speeds become unreliable at low forward speeds.
	PxF32* forwardSpeeds=outputData.forwardSpeeds;
	//Unpack the real outputs of this function (wheel torques to apply to 1d rigid body wheel and forces/torques
	//to apply to 3d rigid body chassis).
	PxF32* tireTorques=outputData.tireTorques;
	PxVec3& chassisForce=outputData.chassisForce;
	PxVec3& chassisTorque=outputData.chassisTorque;
	//Unpack the low speed timers that will be computed.
	PxF32* newLowForwardSpeedTimers=outputData.newLowForwardSpeedTimers;
	PxF32* newLowSideSpeedTimers=outputData.newLowSideSpeedTimers;
	//Unpack the constraint data for suspensions limit and sticky tire constraints.
	//Susp limits.
	bool* suspLimitActiveFlags=outputData.vehConstraintData.mSuspLimitData.mActiveFlags;
	PxVec3* suspLimitDirs=outputData.vehConstraintData.mSuspLimitData.mDirs;
	PxVec3* suspLimitCMOffsets=outputData.vehConstraintData.mSuspLimitData.mCMOffsets;
	PxF32* suspLimitErrors=outputData.vehConstraintData.mSuspLimitData.mErrors;
	//Longitudinal sticky tires.
	bool* stickyTireForwardActiveFlags=outputData.vehConstraintData.mStickyTireForwardData.mActiveFlags;
	PxVec3* stickyTireForwardDirs=outputData.vehConstraintData.mStickyTireForwardData.mDirs;
	PxVec3* stickyTireForwardCMOffsets=outputData.vehConstraintData.mStickyTireForwardData.mCMOffsets;
	PxF32* stickyTireForwardTargetSpeeds=outputData.vehConstraintData.mStickyTireForwardData.mTargetSpeeds;
	//Lateral sticky tires.
	bool* stickyTireSideActiveFlags=outputData.vehConstraintData.mStickyTireSideData.mActiveFlags;
	PxVec3* stickyTireSideDirs=outputData.vehConstraintData.mStickyTireSideData.mDirs;
	PxVec3* stickyTireSideCMOffsets=outputData.vehConstraintData.mStickyTireSideData.mCMOffsets;
	PxF32* stickyTireSideTargetSpeeds=outputData.vehConstraintData.mStickyTireSideData.mTargetSpeeds;
	//Hit data.  Store the contact data so it can be reused.
	PxU32* cachedHitCounts=outputData.cachedHitCounts;
	PxVec4* cachedHitPlanes=outputData.cachedHitPlanes;
	PxF32* cachedHitDistances=outputData.cachedHitDistances;
	PxF32* cachedFrictionMultipliers=outputData.cachedFrictionMultipliers;
	PxU16* cachedHitQueryTypes=outputData.cachedHitQueryTypes;
	//Hit actor data.
	PxRigidDynamic** hitActors=outputData.hitActors;
	PxVec3* hitActorForces=outputData.hitActorForces;
	PxVec3* hitActorForcePositions=outputData.hitActorForcePositions;

	//Compute all the hit data (counts, distances, planes, frictions, actors, shapes, materials etc etc).
	//If we just did a raycast/sweep then we need to compute all this from the hit reports.
	//If we are using cached raycast/sweep results then just copy the cached hit result data.
	PxU32 hitCounts4[4];
	PxF32 hitDistances4[4];
	PxVec4 hitPlanes4[4];
	PxF32 hitFrictionMultipliers4[4];
	PxU16 hitQueryTypes4[4];
	PxShape* hitContactShapes4[4];
	PxRigidActor* hitContactActors4[4];
	PxMaterial* hitContactMaterials4[4];
	PxU32 hitSurfaceTypes4[4];
	PxVec3 hitContactPoints4[4];
	PxVec3 hitContactNormals4[4];
	const PxRaycastQueryResult* PX_RESTRICT raycastResults=inputData.vehWheels4DynData->mRaycastResults;
	const PxSweepQueryResult* PX_RESTRICT sweepResults=inputData.vehWheels4DynData->mSweepResults;
	if(raycastResults || sweepResults)
	{
		const PxU16 queryType = raycastResults ? 0u : 1u;

		//If we have a blocking hit then always take that.
		//If we don't have a blocking hit then search for the "best" hit from all the touches.
		for(PxU32 i=0;i<inputData.numActiveWheels;i++)
		{
			//Test that raycasts issue blocking hits.
			PX_CHECK_AND_RETURN(!raycastResults || (0 == raycastResults[i].nbTouches), "Raycasts must generate blocking hits");

			PxU32 hitCount = 0;
			if ((raycastResults && raycastResults[i].hasBlock) || (sweepResults && sweepResults[i].hasBlock))
			{
				//We have a blocking it so use that.
				const PxLocationHit& hit = raycastResults ? static_cast<const PxLocationHit&>(raycastResults[i].block) : static_cast<const PxLocationHit&>(sweepResults[i].block);

				//Test that the hit actor isn't the vehicle itself.
				PX_CHECK_AND_RETURN(constData.vehActor != hit.actor, "Vehicle raycast has hit itself.  Please check the filter data to avoid this.");

				//Reject if the sweep started inside the hit shape.
				if (hit.distance != 0)
				{
					//Compute the plane of the hit.
					const PxVec3 hitPos = hit.position;
					const PxVec3 hitNorm = hit.normal;
					const PxF32 hitD = -hitNorm.dot(hitPos);
					PxVec4 hitPlane(hitNorm, hitD);

					//Store the hit data in the various arrays.
					storeHit(constData, inputData,
						queryType,
						hit, hitPlane,
						i,
						hitCounts4,
						hitDistances4,
						hitPlanes4,
						hitFrictionMultipliers4,
						hitQueryTypes4,
						hitContactShapes4,
						hitContactActors4,
						hitContactMaterials4,
						hitSurfaceTypes4,
						hitContactPoints4,
						hitContactNormals4,
						cachedHitCounts,
						cachedHitPlanes,
						cachedHitDistances,
						cachedFrictionMultipliers,
						cachedHitQueryTypes);

					hitCount = 1;
				}
			}
			else if (sweepResults && sweepResults[i].nbTouches)
			{
				//We need wheel info so that we can analyse the hit and reject/accept it.
				//Get what we need now.
				const PxVehicleWheelData& wheel = wheelsSimData.getWheelData(i);
				const PxVehicleSuspensionData& susp = wheelsSimData.getSuspensionData(i);
				const PxVec3& bodySpaceWheelCentreOffset = wheelsSimData.getWheelCentreOffset(i);
				const PxVec3& bodySpaceSuspTravelDir = wheelsSimData.getSuspTravelDirection(i);
				const PxQuat& wheelLocalPoseRotation = wheelLocalPoseRotations[i];
				const PxF32 wheelTheta = wheelThetas[i];
				const PxF32 width = wheel.mWidth;
				const PxF32 radius = wheel.mRadius;
				const PxF32 maxBounce = susp.mMaxCompression;

				//Compute the global pose of the wheel at zero jounce.
				PxTransform suspPose;
				PxVec3 suspDir;
				computeSuspensionSweep(
					carChassisTrnsfm, 
					wheelLocalPoseRotation, wheelTheta,
					bodySpaceWheelCentreOffset, bodySpaceSuspTravelDir, 0.0f, 0.0f, 
					suspPose, suspDir);

				//Iterate over all touches and cache the deepest hit that we accept. 
				PxF32 bestTouchDistance = -PX_MAX_F32;
				for (PxU32 j = 0; j < sweepResults[i].nbTouches; j++)
				{
					//Get the next candidate hit.
					const PxLocationHit& hit = sweepResults[i].touches[j];

					//Test that the hit actor isn't the vehicle itself.
					PX_CHECK_AND_RETURN(constData.vehActor != hit.actor, "Vehicle raycast has hit itself.  Please check the filter data to avoid this.");

					//Reject if the sweep started inside the hit shape.
					if (hit.distance != 0.0f)
					{
						//Compute the plane of the hit.
						const PxVec3 hitPos = hit.position;
						const PxVec3 hitNorm = hit.normal;
						const PxF32 hitD = -hitNorm.dot(hitPos);
						PxVec4 hitPlane(hitNorm, hitD);

						//Intersect the wheel disc with the hit plane and compute the jounce required to move the wheel free of the hit plane.
						PxF32 dx;
						PxVec3 wheelBottomPos;
						bool successIntersection = 
							intersectCylinderPlane
								(suspPose, suspDir,
								 width, radius, maxBounce,
								 hitPlane,
								 true, 
								 dx, wheelBottomPos);

						//If we accept the intersection and it requires more jounce than previously encountered then 
						//store the hit. 
						if (successIntersection && dx > bestTouchDistance)
						{
							storeHit(constData, inputData,
								    queryType,
									hit, hitPlane,
									i,
									hitCounts4,
									hitDistances4,
									hitPlanes4,
									hitFrictionMultipliers4,
									hitQueryTypes4,
									hitContactShapes4,
									hitContactActors4,
									hitContactMaterials4,
									hitSurfaceTypes4,
									hitContactPoints4,
									hitContactNormals4,
									cachedHitCounts,
									cachedHitPlanes,
									cachedHitDistances,
									cachedFrictionMultipliers,
									cachedHitQueryTypes);

							bestTouchDistance = dx;

							hitCount = 1;
						}
					}
				}
			}

			if(0 == hitCount)
			{
				hitCounts4[i]=0;
				hitDistances4[i]=0;
				hitPlanes4[i]=PxVec4(0,0,0,0);
				hitFrictionMultipliers4[i]=0;
				hitQueryTypes4[i]=0u;
				hitContactShapes4[i]=NULL;
				hitContactActors4[i]=NULL;
				hitContactMaterials4[i]=NULL;
				hitSurfaceTypes4[i]=PxU32(PxVehicleDrivableSurfaceType::eSURFACE_TYPE_UNKNOWN);
				hitContactPoints4[i]=PxVec3(0,0,0);
				hitContactNormals4[i]=PxVec3(0,0,0);

				//When we're finished here we need to copy this back to the vehicle.
				cachedHitCounts[i]=0;
				cachedHitPlanes[i]=PxVec4(0,0,0,0);
				cachedHitDistances[i]=0;
				cachedFrictionMultipliers[i]=0;
				cachedHitQueryTypes[i] = 0u;
			}
		}
	}
	else
	{
		//If we have no sq results then we must have a cached raycast hit result.
		const PxVehicleWheels4DynData::CachedSuspLineSceneQuerytHitResult& cachedHitResult = 
			reinterpret_cast<const PxVehicleWheels4DynData::CachedSuspLineSceneQuerytHitResult&>(inputData.vehWheels4DynData->mQueryOrCachedHitResults);

		for(PxU32 i=0;i<inputData.numActiveWheels;i++)
		{
			hitCounts4[i]=cachedHitResult.mCounts[i];
			hitDistances4[i]=cachedHitResult.mDistances[i];
			hitPlanes4[i]=cachedHitResult.mPlanes[i];
			hitFrictionMultipliers4[i]=cachedHitResult.mFrictionMultipliers[i];
			hitQueryTypes4[i] = cachedHitResult.mQueryTypes[i];
			hitContactShapes4[i]=NULL;
			hitContactActors4[i]=NULL;
			hitContactMaterials4[i]=NULL;
			hitSurfaceTypes4[i]=PxU32(PxVehicleDrivableSurfaceType::eSURFACE_TYPE_UNKNOWN);
			hitContactPoints4[i]=PxVec3(0,0,0);
			hitContactNormals4[i]=PxVec3(0,0,0);

			//When we're finished here we need to copy this back to the vehicle.
			cachedHitCounts[i]=cachedHitResult.mCounts[i];
			cachedHitPlanes[i]=cachedHitResult.mPlanes[i];
			cachedHitDistances[i]=cachedHitResult.mDistances[i];
			cachedFrictionMultipliers[i]=cachedHitResult.mFrictionMultipliers[i];
			cachedHitQueryTypes[i]=cachedHitResult.mQueryTypes[i];
		}
	}

	//Iterate over all 4 wheels.
	for(PxU32 i=0;i<4;i++)
	{
		//Constant data of the ith wheel.
		const PxVehicleWheelData& wheel=wheelsSimData.getWheelData(i);
		const PxVehicleSuspensionData& susp=wheelsSimData.getSuspensionData(i);
		const PxVehicleTireData& tire=wheelsSimData.getTireData(i);
		const PxVec3& bodySpaceWheelCentreOffset=wheelsSimData.getWheelCentreOffset(i);
		const PxVec3& bodySpaceSuspTravelDir=wheelsSimData.getSuspTravelDirection(i);

		//Take a copy of the low forward/side speed timer of the ith wheel (time spent at low forward/side speed)
		//Do this so we can quickly tell if the low/side forward speed timer changes.
		newLowForwardSpeedTimers[i]=lowForwardSpeedTimers[i];
		newLowSideSpeedTimers[i]=lowSideSpeedTimers[i];

		//Reset the graph of the jounce to max droop.
		//This will get updated as we learn more about the suspension.
#if PX_DEBUG_VEHICLE_ON
		updateGraphDataSuspJounce(startWheelIndex, i,-susp.mMaxDroop);
#endif

		//Reset the jounce to max droop.
		//This will get updated as we learn more about the suspension and tire.
		PxF32 jounce=-susp.mMaxDroop;
		jounces[i]=jounce;

		//Deactivate the sticky tire and susp limit constraint.
		//These will get updated as we learn more about the suspension and tire.
		suspLimitActiveFlags[i]=false;
		suspLimitErrors[i]=0.0f;
		stickyTireForwardActiveFlags[i]=false;
		stickyTireForwardTargetSpeeds[i]=0;
		stickyTireSideActiveFlags[i]=false;
		stickyTireSideTargetSpeeds[i]=0;

		//The vehicle is in the air until we know otherwise.
		isInAirs[i]=true;

		//If there has been a hit then compute the suspension force and tire load.
		//Ignore the hit if the raycast starts inside the hit shape (eg wheel completely underneath surface of a heightfield).
		const bool activeWheelState=activeWheelStates[i];
		const PxU32 numHits=hitCounts4[i];
		const PxVec3 hitNorm(hitPlanes4[i].x, hitPlanes4[i].y,hitPlanes4[i].z);
		const PxVec3 w = carChassisTrnsfm.q.rotate(bodySpaceSuspTravelDir);
		if(activeWheelState && numHits > 0 && hitDistances4[i] != 0.0f && hitNorm.dot(w) < 0.0f)
		{
			//Get the friction multiplier from the combination of surface type and tire type.
			const PxF32 frictionMultiplier=hitFrictionMultipliers4[i];
			PX_ASSERT(frictionMultiplier>=0);

			PxF32 dx;
			PxVec3 wheelBottomPos;
			bool successIntersection = true;
			if(0 == hitQueryTypes4[i])
			{
				successIntersection  = intersectRayPlane
					(carChassisTrnsfm, 
					 bodySpaceWheelCentreOffset, bodySpaceSuspTravelDir, wheel.mWidth, wheel.mRadius, susp.mMaxCompression, 
					 hitPlanes4[i], 
					 dx, wheelBottomPos);
			}
			else
			{
				PX_ASSERT(1 == hitQueryTypes4[i]);
				successIntersection = intersectCylinderPlane
					(carChassisTrnsfm, 
					 wheelLocalPoseRotations[i], wheelThetas[i],
					 bodySpaceWheelCentreOffset, bodySpaceSuspTravelDir, wheel.mWidth, wheel.mRadius, susp.mMaxCompression, 
					 hitPlanes4[i], 
					 false, 
					 dx, wheelBottomPos);
			}

			//If the spring is elongated past its max droop then the wheel isn't touching the ground.
			//In this case the spring offers zero force and provides no support for the chassis/sprung mass.
			//Only carry on computing the spring force if the wheel is touching the ground.
			PX_ASSERT(susp.mMaxCompression>=0);
			PX_ASSERT(susp.mMaxDroop>=0);
			if(dx > -susp.mMaxDroop && successIntersection)
			{
				//We can record the hit shape, hit actor, hit material, hit surface type, hit point, and hit normal now because we've got a hit.
				tireContactShapes[i]=hitContactShapes4[i];
				tireContactActors[i]=hitContactActors4[i];
				tireSurfaceMaterials[i]=hitContactMaterials4[i];
				tireSurfaceTypes[i]=hitSurfaceTypes4[i];
				tireContactPoints[i]=hitContactPoints4[i];
				tireContactNormals[i]=hitContactNormals4[i];

				//We know that the vehicle is not in the air.
				isInAirs[i]=false;

				//Clamp the spring compression so that it is never greater than the max bounce.
				//Apply the susp limit constraint if the spring compression is greater than the max bounce.
				suspLimitErrors[i] = (w.dot(hitNorm))*(-dx + susp.mMaxCompression);
				suspLimitActiveFlags[i] = (dx > susp.mMaxCompression);
				suspLimitCMOffsets[i] = bodySpaceWheelCentreOffset;
				suspLimitDirs[i] = bodySpaceSuspTravelDir;
				jounce=PxMin(dx,susp.mMaxCompression);

				//Store the jounce (having a local copy avoids lhs).
				jounces[i]=jounce;

				//Store the jounce in the graph.
#if PX_DEBUG_VEHICLE_ON
				updateGraphDataSuspJounce(startWheelIndex, i,jounce);
#endif

				//Compute the speed of the rigid body along the suspension travel dir at the 
				//bottom of the wheel.
				const PxVec3 r=wheelBottomPos-carChassisTrnsfm.p;
				PxVec3 wheelBottomVel=carChassisLinVel;
				wheelBottomVel+=carChassisAngVel.cross(r);

				//Modify the relative velocity at the wheel contact point if the hit actor is a dynamic.
				PxRigidDynamic* dynamicHitActor=NULL;
				PxVec3 hitActorVelocity(0,0,0);
				if(hitContactActors4[i] && ((dynamicHitActor = hitContactActors4[i]->is<PxRigidDynamic>()) != NULL))
				{
					hitActorVelocity = PxRigidBodyExt::getVelocityAtPos(*dynamicHitActor,wheelBottomPos);
					wheelBottomVel -= hitActorVelocity;
				}

				//Get the speed of the jounce.
				const PxF32 jounceSpeed = (PX_MAX_F32 != prevJounces[i]) ? (jounce - prevJounces[i])*recipTimeStep : 0.0f;

				//Decompose gravity into a term along w and a term perpendicular to w
				//gravity = w*alpha + T*beta
				//where T is a unit vector perpendicular to w; alpha and beta are scalars.
				//The vector w*alpha*mass is the component of gravitational force that acts along the spring direction.
				//The vector T*beta*mass is the component of gravitational force that will be resisted by the spring 
				//because the spring only supports a single degree of freedom along w.
				//We only really need to know T*beta so don't bother calculating T or beta.
				const PxF32 alpha = PxMax(0.0f, gravity.dot(w));
				const PxVec3 TTimesBeta = (0.0f != alpha) ? gravity - w*alpha : PxVec3(0,0,0);
				//Compute the magnitude of the force along w.
				PxF32 suspensionForceW =	
					PxMax(0.0f, 
					susp.mSprungMass*alpha + 							//force to support sprung mass at zero jounce
					susp.mSpringStrength*jounce);						//linear spring
				suspensionForceW += susp.mSpringDamperRate*jounceSpeed;	//damping
				//Compute the total force acting on the suspension.
				//Remember that the spring force acts along -w.
				//Remember to account for the term perpendicular to w and that it acts along -TTimesBeta
				PxF32 suspensionForceMag = hitNorm.dot(-w*suspensionForceW - TTimesBeta*susp.mSprungMass);

				//Apply the opposite force to the hit object.
				//Clamp suspensionForceMag if required.
				if (dynamicHitActor && !(dynamicHitActor->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC))
				{
					const PxF32 dynamicActorInvMass = dynamicHitActor->getInvMass();
					const PxF32 dynamicActorMass = dynamicHitActor->getMass();
					const PxF32 forceSign = computeSign(suspensionForceMag);
					const PxF32 forceMag = PxAbs(suspensionForceMag);
					const PxF32 clampedAccelMag = PxMin(forceMag*dynamicActorInvMass, gMaxHitActorAcceleration);
					const PxF32 clampedForceMag = clampedAccelMag*dynamicActorMass*forceSign;
					PX_ASSERT(clampedForceMag*suspensionForceMag >= 0.0f);

					suspensionForceMag = clampedForceMag;

					hitActors[i] = dynamicHitActor;
					hitActorForces[i] = hitNorm*(-clampedForceMag*timeFraction);
					hitActorForcePositions[i] = hitContactPoints4[i];
				}

				//Store the spring force now (having a local copy avoids lhs).
				suspensionSpringForces[i] = suspensionForceMag;

				//Store the spring force in the graph.
#if PX_DEBUG_VEHICLE_ON
				updateGraphDataSuspForce(startWheelIndex, i, suspensionForceMag);
#endif

				//Suspension force can be computed now.
				const PxVec3 suspensionForce = hitNorm*suspensionForceMag;

				//Torque from spring force.
				const PxVec3 suspForceCMOffset = carChassisTrnsfm.rotate(wheelsSimData.getSuspForceAppPointOffset(i));
				const PxVec3 suspensionTorque = suspForceCMOffset.cross(suspensionForce);

				//Add the suspension force/torque to the chassis force/torque.
				chassisForce+=suspensionForce;
				chassisTorque+=suspensionTorque;

				//Now compute the tire load.
				const PxF32 tireLoad = suspensionForceMag;

				//Normalize the tire load 
				//Now work out the normalized tire load.
				const PxF32 normalisedTireLoad=tireLoad*recipGravityMagnitude*recipTireRestLoads[i];
				//Filter the normalized tire load and compute the filtered tire load too.
				const PxF32 filteredNormalisedTireLoad=computeFilteredNormalisedTireLoad(tireLoadFilterData,normalisedTireLoad);
				const PxF32 filteredTireLoad=filteredNormalisedTireLoad*gravityMagnitude*tireRestLoads[i];

#if PX_DEBUG_VEHICLE_ON
				updateGraphDataTireLoad(startWheelIndex,i,filteredTireLoad);
				updateGraphDataNormTireLoad(startWheelIndex,i,filteredNormalisedTireLoad);
#endif

				//Compute the lateral and longitudinal tire axes in the ground plane.
				PxVec3 tireLongDir;
				PxVec3 tireLatDir;
				computeTireDirs(latDir,hitNorm,steerAngles[i],tireLongDir,tireLatDir);

				//Store the tire long and lat dirs now (having a local copy avoids lhs).
				tireLongitudinalDirs[i]= tireLongDir;
				tireLateralDirs[i]=tireLatDir;

				//Now compute the speeds along each of the tire axes.
				const PxF32 tireLongSpeed=wheelBottomVel.dot(tireLongDir);
				const PxF32 tireLatSpeed=wheelBottomVel.dot(tireLatDir);

				//Store the forward speed (having a local copy avoids lhs).
				forwardSpeeds[i]=tireLongSpeed;

				//Now compute the slips along each axes.
				const bool hasAccel=isAccelApplied[i];
				const bool hasBrake=isBrakeApplied[i];
				const PxF32 wheelOmega=wheelsDynData.mWheelSpeeds[i];
				const PxF32 wheelRadius=wheel.mRadius;
				PxF32 longSlip;
				PxF32 latSlip;
				computeTireSlips
					(tireLongSpeed,tireLatSpeed,wheelOmega,wheelRadius,minLongSlipDenominator,
					 hasAccel,hasBrake,
					 isTank,
					 longSlip,latSlip);

				//Store the lat and long slip (having local copies avoids lhs).
				longSlips[i]=longSlip;
				latSlips[i]=latSlip;

				//Camber angle.
				PxF32 camber=susp.mCamberAtRest;
				if(jounce>0)
				{
					camber += jounce*susp.mCamberAtMaxCompression*susp.getRecipMaxCompression();
				}
				else
				{
					camber -= jounce*susp.mCamberAtMaxDroop*susp.getRecipMaxDroop();
				}

				//Compute the friction that will be experienced by the tire.
				PxF32 friction;
				computeTireFriction(tire,longSlip,frictionMultiplier,friction);

				//Store the friction (having a local copy avoids lhs).
				frictions[i]=friction;

				if(filteredTireLoad*frictionMultiplier>0)
				{
					//Either tire forces or sticky tire friction constraint will be applied here.
					const PxVec3 tireForceCMOffset = carChassisTrnsfm.rotate(wheelsSimData.getTireForceAppPointOffset(i));

					PxF32 newLowForwardSpeedTimer;
					{
						//check the accel value here
						//Update low forward speed timer.
						const PxF32 recipWheelRadius=wheel.getRecipRadius();
						newLowForwardSpeedTimer=newLowForwardSpeedTimers[i];
						updateLowForwardSpeedTimer(tireLongSpeed,wheelOmega,wheelRadius,recipWheelRadius,isIntentionToAccelerate,timeStep,newLowForwardSpeedTimer);

						//Activate sticky tire forward friction constraint if required.
						//If sticky tire friction is active then set the longitudinal slip to zero because 
						//the sticky tire constraint will take care of the longitudinal component of motion.
						bool stickyTireForwardActiveFlag=false;
						PxF32 stickyTireForwardTargetSpeed=0.0f;
						activateStickyFrictionForwardConstraint(tireLongSpeed,wheelOmega,newLowForwardSpeedTimer,isIntentionToAccelerate,stickyTireForwardActiveFlag,stickyTireForwardTargetSpeed);
						stickyTireForwardTargetSpeed += hitActorVelocity.dot(tireLongDir);

						//Store the sticky tire data (having local copies avoids lhs). 
						newLowForwardSpeedTimers[i] = newLowForwardSpeedTimer;
						stickyTireForwardActiveFlags[i]=stickyTireForwardActiveFlag;
						stickyTireForwardTargetSpeeds[i]=stickyTireForwardTargetSpeed;
						stickyTireForwardDirs[i]=tireLongDir;
						stickyTireForwardCMOffsets[i]=tireForceCMOffset;

						//Deactivate the long slip if sticky tire constraint is active.
						longSlip=(!stickyTireForwardActiveFlag ? longSlip : 0.0f); 

						//Store the long slip (having local copies avoids lhs). 
						longSlips[i]=longSlip;
					}

					PxF32 newLowSideSpeedTimer;
					{
						//check the accel value here
						//Update low side speed timer.
						newLowSideSpeedTimer=newLowSideSpeedTimers[i];
						updateLowSideSpeedTimer(tireLatSpeed,isIntentionToAccelerate,timeStep,newLowSideSpeedTimer);

						//Activate sticky tire side friction constraint if required.
						//If sticky tire friction is active then set the lateral slip to zero because 
						//the sticky tire constraint will take care of the lateral component of motion.
						bool stickyTireSideActiveFlag=false;
						PxF32 stickyTireSideTargetSpeed=0.0f;
						activateStickyFrictionSideConstraint(tireLatSpeed,newLowForwardSpeedTimer,newLowSideSpeedTimer,isIntentionToAccelerate,stickyTireSideActiveFlag,stickyTireSideTargetSpeed);
						stickyTireSideTargetSpeed += hitActorVelocity.dot(tireLatDir);

						//Store the sticky tire data (having local copies avoids lhs). 
						newLowSideSpeedTimers[i] = newLowSideSpeedTimer;
						stickyTireSideActiveFlags[i]=stickyTireSideActiveFlag;
						stickyTireSideTargetSpeeds[i]=stickyTireSideTargetSpeed;
						stickyTireSideDirs[i]=tireLatDir;
						stickyTireSideCMOffsets[i]=tireForceCMOffset;

						//Deactivate the lat slip if sticky tire constraint is active.
						latSlip=(!stickyTireSideActiveFlag ? latSlip : 0.0f); 

						//Store the long slip (having local copies avoids lhs). 
						latSlips[i]=latSlip;
					}

					//Compute the various tire torques.
					PxF32 wheelTorque=0;
					PxF32 tireLongForceMag=0;
					PxF32 tireLatForceMag=0;
					PxF32 tireAlignMoment=0;
					const PxF32 restTireLoad=gravityMagnitude*tireRestLoads[i];
					const PxF32 recipWheelRadius=wheel.getRecipRadius();
					tireForceCalculator.mShader(
						tireForceCalculator.mShaderData[i],
						friction,
						longSlip,latSlip,camber,
						wheelOmega,wheelRadius,recipWheelRadius,
						restTireLoad,filteredNormalisedTireLoad,filteredTireLoad,
						gravityMagnitude, recipGravityMagnitude,
						wheelTorque,tireLongForceMag,tireLatForceMag,tireAlignMoment);

					//Store the tire torque ((having a local copy avoids lhs).
					tireTorques[i]=wheelTorque;

					//Apply the torque to the chassis.
					//Compute the tire force to apply to the chassis.
					const PxVec3 tireLongForce=tireLongDir*tireLongForceMag;
					const PxVec3 tireLatForce=tireLatDir*tireLatForceMag;
					const PxVec3 tireForce=tireLongForce+tireLatForce;
					//Compute the torque to apply to the chassis.
					const PxVec3 tireTorque=tireForceCMOffset.cross(tireForce);
					//Add all the forces/torques together.
					chassisForce+=tireForce;
					chassisTorque+=tireTorque;

					//Graph all the data we just computed.
#if PX_DEBUG_VEHICLE_ON
					if(gCarTireForceAppPoints)
						gCarTireForceAppPoints[i]=carChassisTrnsfm.p + tireForceCMOffset;
					if(gCarSuspForceAppPoints)
						gCarSuspForceAppPoints[i]=carChassisTrnsfm.p + suspForceCMOffset;

					if(gCarWheelGraphData[0])
					{
						updateGraphDataNormLongTireForce(startWheelIndex, i, PxAbs(tireLongForceMag)*normalisedTireLoad/tireLoad);
						updateGraphDataNormLatTireForce(startWheelIndex, i, PxAbs(tireLatForceMag)*normalisedTireLoad/tireLoad);
						updateGraphDataNormTireAligningMoment(startWheelIndex, i, tireAlignMoment*normalisedTireLoad/tireLoad);
						updateGraphDataLongTireSlip(startWheelIndex, i,longSlips[i]);
						updateGraphDataLatTireSlip(startWheelIndex, i,latSlips[i]);
						updateGraphDataTireFriction(startWheelIndex, i,frictions[i]);
					}
#endif
				}//filteredTireLoad*frictionMultiplier>0
			}//if(dx > -susp.mMaxCompression)
		}//if(numHits>0)
	}//i
} 

 

 


Ну если ты считаешь, что эти правила хуйня - то че ты тут спрашиваешь советов? Выкладывай код где сидят такие-же братюни как и ты и облизывайте там друг-друга за свои методы в 200 строчек.

я говорю что в данном случае не применимо = хуйня, все кроме слишком длинный код ибо это почти нигде не применимо имхо.

Поделиться сообщением


Ссылка на сообщение
Гость
Эта тема закрыта для публикации сообщений.

×
×
  • Создать...