Jump to content
reepblue

[4.6 Beta] World Pick Can Fail

Recommended Posts

Hello,

After updating my project to 4.6, I've noticed that the picking system seems to be not as accurate as the 4.5 release. I've uploaded my project in full. Launch the player.map and look around near the edges of walls and floors. The axis crosshair will vanish. Pressing Mouse one will spawn an object at the calculated pick. Compile this with 4.5, and it works as expected.

The picking operations are under Game.cpp while the rest of the game is in Lua.

This may have to do with a previous update from December.

Quote

A new build is available on the beta branch. This changes the model picking system to use a different raycasting implementation under-the-hood. Sphere picking (using a radius) will also now correctly return the first hit triangle. You will also notice much faster loading times when you load up a detailed model in the editor!

 

Cyclone.zip

Share this post


Link to post
5 minutes ago, Josh said:

Where is the code located that is performing the pick?

The camera pick is done in CycloneCameraPlacement.Lua. This is the pick that causes the object (Cyclone) to be placed in walls.

function Script:UpdateTrace()
    local pickinfo=PickInfo()
    local p0 = self.entity:GetPosition(true)
	local p1 = Transform:Point(0, 0, 999, self.entity, nil)
    if self.entity.world:Pick(p0, p1, pickinfo, 0, true, Collision.LineOfSight) then
		self.target:SetPosition(pickinfo.position)
		self.target:AlignToVector(pickinfo.normal)

		self.box:SetColor(1,0,0) 
		self.box:Show()

		local hit =  window:MouseHit(1)
		local hitPos = pickinfo.position
		if Game:TestCyclonePlacement(pickinfo, self.box)==true then
			self.box:SetColor(0,1,0) 
			if hit==true then
				self:PlaceCyclone(pickinfo)
			end
		end
		hit = false
	end
end

Here is Game:TestCyclone located in Game.cpp for the correction placement. (To move the position away from corners)

bool Game::TestCyclonePlacement(PickInfo* pPickInfo, Entity* pTargetEntity)
	{
		if (!gamerules) InstallGameRules();

		// If there is no entity, return;
		if (pPickInfo->entity == nullptr) { return false; }

		// Check for surface
		if (pPickInfo->surface == nullptr) { return false; }

		//Check for a shape...
		if (pPickInfo->entity->GetShape() == nullptr) { return false; }

		// Check to see if it's CSG.
		if (pPickInfo->entity->GetClass() != Object::ModelClass)
		{
			return false;
		}
		else if (pPickInfo->entity->GetClass() == Object::ModelClass)
		{
			auto cast = static_cast<Model*>(pPickInfo->entity);
			if (cast->collapsedfrombrushes == false)
				return false;
		}

		// Test the material.
		if (CanPlaceOnSurface(pPickInfo->surface->GetMaterial()) == false)
		{
			return false;
		}

		// The target entity should be a pivot or something.
		// Basicly, the pivot position is where the cyclone is actually going to spawn at.
		if (pTargetEntity != NULL)
		{
			pTargetEntity->SetPosition(pPickInfo->position + pPickInfo->normal * 0.1);
			pTargetEntity->SetRotation(0, 0, 0);
			pTargetEntity->AlignToVector(pPickInfo->normal);

			float x = 0;
			float y = 0;

			PickInfo Pickinfo;
			auto world = World::GetCurrent();
			float distance = 0.64;
			float radius = 0;
			Vec3 tracetest;

			tracetest = Transform::Point(0, distance, 0, pTargetEntity, nullptr);
			if (world->Pick(pTargetEntity->GetPosition(false), tracetest, Pickinfo, radius, true, COLLISION_CYCLONEBUMPER))
			{
				y = -distance + MakePositve(pTargetEntity->GetPosition(false).DistanceToPoint(Pickinfo.position));
			}

			tracetest = Transform::Point(0, -distance, 0, pTargetEntity, nullptr);
			if (world->Pick(pTargetEntity->GetPosition(false), tracetest, Pickinfo, radius, true, COLLISION_CYCLONEBUMPER))
			{
				y = distance - MakePositve(pTargetEntity->GetPosition(false).DistanceToPoint(Pickinfo.position));
			}

			tracetest = Transform::Point(-distance, 0, 0, pTargetEntity, nullptr);
			if (world->Pick(pTargetEntity->GetPosition(false), tracetest, Pickinfo, radius, true, COLLISION_CYCLONEBUMPER))
			{
				x = distance - MakePositve(pTargetEntity->GetPosition(false).DistanceToPoint(Pickinfo.position));
			}

			tracetest = Transform::Point(distance, 0, 0, pTargetEntity, nullptr);
			if (world->Pick(pTargetEntity->GetPosition(false), tracetest, Pickinfo, radius, true, COLLISION_CYCLONEBUMPER))
			{
				x = -distance + MakePositve(pTargetEntity->GetPosition(false).DistanceToPoint(Pickinfo.position));
			}

			pTargetEntity->Move(x, y, 0);
			//pTargetEntity->AlignToVector(pPickInfo->normal);

			tracetest = Transform::Point(0, 0, -0.5, pTargetEntity, nullptr);
			if (world->Pick(pTargetEntity->GetPosition(false), tracetest, Pickinfo, 0, true, COLLISION_CYCLONEBUMPER) == false)
			{
				return false;
			}
		}

 

 

Share this post


Link to post

I think I have the fix. Stay tuned.

  • Like 1

Share this post


Link to post

I think this is fixed in latest build on beta branch.

Share this post


Link to post

Tested this for a few minutes and it seems to be working as it should. I can't say if picks with a radius were effected or not. If there are any issues, I'll let you know as always.

  • Thanks 1

Share this post


Link to post
Guest
This topic is now closed to further replies.
×
×
  • Create New...