Jump to content

Question about Physic


Schoppy0384
 Share

Recommended Posts

Hi,

the Tank in the Photo has a - SetPhysicsMode(Leadwerks::Entity::CharacterPhysics)-.

With -tankPivot->GoToPoint(moveTarget,speed,acceleration)- I give the tank new coordinates and the tank drive to this new position.

 

The problem is that the tank is not rotating on the y coordinates.

The physics does not apply heir anyway.

 

Is there a way to correct them?

 

Thanks

post-8630-0-33159700-1391368471_thumb.jpg

Link to comment
Share on other sites

I think you mean the x axis. If you expect it to rotate upward/downward that's not the y axis but the x axis. Character controllers only rotate on the y axis (turns left/right). You'll either have to manually rotate the model yourself up/down based on some factor or use a different physics method to move your tank around.

Link to comment
Share on other sites

Better use oriented bouding box for collision indeed (actually LE3 don't have car physics) ,and call functions like PhysicsSetPosition, PhysicsSetRotation, or AddForce, AddTorque.

Character controller as it's name says it , it's for standard character based games, not vehicles.

Stop toying and make games

Link to comment
Share on other sites

Thanks for the answers.

Ok, my Idea is to parent 2 boxes, one on the Frontside and one on the backside from the tank.

Then I can check the height difference between the two boxes and calculate the Rotation Angel.

 

What I need is a Pick Y Command on the box to check the Y Coordinate.

Which command is the best for this?

And second the Rotation Angel, i think ATAN2 is right?

Link to comment
Share on other sites

I think what dude is saying is to just make 1 physics box/shape that is your tanks body. When you apply force to it, it'll then move the way you want. It'll go up hills and rotate along the x to pitch up or down. Just play with the friction, mass, and where you apply the force and you should be able to move the physics box (tank) around and get the effect you want.

Link to comment
Share on other sites

Oh sorry, I am working on an little Tank RTS Game.

I use the Navmesh to navigate the Tanks on the map.

 

With a Character Controller it works very good. But the problem are hills.

The Tanks rotate only on the y axis (Character Controller).

What i need is a rotation upward/downward for the tanks, see first picture.

Link to comment
Share on other sites

So you really need Navmesh, so character controller.

 

Some solution perhaps :

1) Use some invisible model with character controller : "virtual tank" using navmesh

2) Use Real tank model with simple box physics and uses Physics command to each loop follow the position of your "virtual tank"

Stop toying and make games

Link to comment
Share on other sites

It's a bummer that the path that is found isn't exposed to Lua. I know in 3.0 C++ you get actually get the path points and just use those without having to do anything with the character controller. That would be really handy and maybe make a suggestion that Josh expose this to Lua?

  • Upvote 1
Link to comment
Share on other sites

I agree to rick. It would be nice if the path would be accessible.

But another idea:

Can't we use PickInfo.triangle and

entity:AlignToVector or something like that to align it to the ground? In my testing it looked like it might work but i would have to play with it a bit more.

Link to comment
Share on other sites

Ok, I thing it is Time for some Code (C++).

 

Here I have write a little example with 3 Methods to Navigate a Character to a specific Position.

All three Methods has his own problems.

You can switch the Method with this lines:

 

// Set Method

int method = 1;

 

#include "App.h"

using namespace Leadwerks;

App::App() : window(NULL), context(NULL), world(NULL), camera(NULL) {}

App::~App() { delete world; delete window; }

Vec3 camerarotation;
#if defined (PLATFORM_WINDOWS) || defined (PLATFORM_MACOS)
bool freelookmode=true;
#else
bool freelookmode=false;
#endif

Model* pickSphere;
Entity* characterController;
Entity* characterMesh;
PickInfo pickinfo;

NavMesh* navMesh;
NavPath* path;

Model* box;
list<Model*> models;
list<Model*>::iterator modelsIt;

int pointCounter = 1;

// ####################### Character Move Methods ########################
// Set Method
int method = 1;

//method 1 = Standard Character Move Method ( only on xy Axis while SetPhysicsMode(Entity::CharacterPhysics))
//method 2 = Character Contoller is only a Pivot. The Charcter Model Follow this Pivot by SetPhysicPosition and Rotation (Problem the Model Collides with the Pivot and looks ver bad!)
//method 3 = Calculate the Path Manuel and move and rotate the Model. (The Rotation is Bad and sometimes the Model collides with a wall)

bool App::Start()
{
//Create a window
window = Window::Create("RTS_Movement");

//Create a context
context = Context::Create(window);

//Create a world
world = World::Create();

//Create a camera
camera = Camera::Create();
camera->SetFOV(40.0f);
camera->SetRotation(45,0,0);
camera->Move(0,0,-35);

//Create a light
Light* light = DirectionalLight::Create();
light->SetRotation(35,35,0);

//Build a Map
//Create the ground
Model* ground1 = Model::Box(44.75,0.25,62.5);
ground1->SetPosition(8.875,-0.125,-0.25);
ground1->SetColor(0.0,0.25,0.0);
//Ground Shape
Shape* groundShape1 = Shape::Box(0,0,0, 0,0,0, 44.75,0.25,62.5);
ground1->SetShape(groundShape1);
groundShape1->Release();

Model* ground2 = Model::Box(44.75,0.25,28.5);
ground2->SetPosition(-35.875,-0.125,16.75);
ground2->SetColor(0.0,0.25,0.0);
//Ground Shape
Shape* groundShape2 = Shape::Box(0,0,0, 0,0,0, 44.75,0.25,28.5);
ground2->SetShape(groundShape2);
groundShape2->Release();

Model* ground3 = Model::Box(44.75,0.25,25.0);
ground3->SetPosition(-35.875,-0.125,-19.0);
ground3->SetColor(0.0,0.25,0.0);
//Ground Shape
Shape* groundShape3 = Shape::Box(0,0,0, 0,0,0, 44.75,0.25,25.0);
ground3->SetShape(groundShape3);
groundShape3->Release();

Model* ground4 = Model::Box(16.48,0.25,9.0);
ground4->SetPosition(-21.51001,-0.875,-2.0);
ground4->SetRotation(0,0,5.0);
ground4->SetColor(0.0,0.25,0.0);
//Ground Shape
Shape* groundShape4 = Shape::Box(0,0,0, 0,0,0, 16.48,0.25,9.0);
ground4->SetShape(groundShape4);
groundShape4->Release();

Model* ground5 = Model::Box(28.75,0.25,9.0);
ground5->SetPosition(-43.875,-1.625,-2.0);
ground5->SetColor(0.0,0.25,0.0);
//Ground Shape
Shape* groundShape5 = Shape::Box(0,0,0, 0,0,0, 28.75,0.25,9.0);
ground5->SetShape(groundShape5);
groundShape5->Release();

Model* ground6 = Model::Box(0.75,2.75,8.5);
ground6->SetPosition(5.625,1.125,11.5);
ground6->SetColor(0.0,0.80,0.0);
//Ground Shape
Shape* groundShape6 = Shape::Box(0,0,0, 0,0,0, 0.75,2.75,8.5);
ground6->SetShape(groundShape6);
groundShape6->Release();

Model* ground7 = Model::Box(0.75,2.75,8.5);
ground7->SetPosition(-5.125,1.125,11.5);
ground7->SetColor(0.0,0.80,0.0);
//Ground Shape
Shape* groundShape7 = Shape::Box(0,0,0, 0,0,0, 0.75,2.75,8.5);
ground7->SetShape(groundShape7);
groundShape7->Release();

//Enable navigation obstacles
ground1->SetNavigationMode(true);
ground2->SetNavigationMode(true);
ground3->SetNavigationMode(true);
ground4->SetNavigationMode(true);
ground5->SetNavigationMode(true);
ground6->SetNavigationMode(true);
ground7->SetNavigationMode(true);

//Build the navigation mesh
world->BuildNavMesh();

//picksphere
pickSphere = Model::Sphere(12);
pickSphere->SetScale(0.5);
pickSphere->Hide();


if(method == 1)
{
//#############-- Create a Character --##################
//Create a character controller
characterController = Pivot::Create();
characterController->SetPosition(0,0,0);

characterMesh = Model::Box(1.0,0.2,1.5,characterController);
characterMesh->SetScale(1,2,1);
characterMesh->SetPosition(0,0,0);

characterController->SetMass(1);
characterController->SetPhysicsMode(Entity::CharacterPhysics);

//#######################################################
}

if(method == 2)
{
//#############-- Create a Character --##################
//Create a character controller
characterController = Pivot::Create();
characterController->SetPosition(0,0,0);

characterController->SetMass(1);
characterController->SetPhysicsMode(Entity::CharacterPhysics);

//Create the Mesh
characterMesh = Model::Box(1.0,0.2,1.5);
characterMesh->SetScale(1,2,1);
characterMesh->SetPosition(0,0,0);
characterMesh->SetMass(1);

//Set Shape
Shape* characterShape = Shape::Box(0,0,0, 0,0,0, 1.0,0.2,1.5);
characterMesh->SetShape(characterShape);
characterShape->Release();
//#######################################################
}

if(method == 3)
{
navMesh = world->navmesh;
path = new NavPath(); // Create a new Instance
path->navmesh = navMesh;

//init list
models = list<Model*>();
//#############-- Create a Character --##################
//Create the Mesh
characterMesh = Model::Box(1.0,0.2,1.5);
characterMesh->SetScale(1,2,1);
characterMesh->SetPosition(0,0,0);
characterMesh->SetMass(1);

//Set Shape
Shape* characterShape = Shape::Box(0,0,0, 0,0,0, 1.0,0.2,1.5);
characterMesh->SetShape(characterShape);
characterShape->Release(); //#######################################################

}




//Move the mouse to the center of the screen
window->SetMousePosition(context->GetWidth()/2,context->GetHeight()/2);

return true;
}

bool App::Loop()
{
//Close the window to end the program
if (window->Closed() || window->KeyDown(Key::Escape)) return false;

// Show Physics
if(window->KeyHit(Key:)) camera->drawphysicsmode = !camera->drawphysicsmode;

//Enable/Disable navmesh debugging
if(window->KeyHit(Key::N))
{
if (camera->GetDebugNavigationMode() == false) {camera->SetDebugNavigationMode(true);} else {camera->SetDebugNavigationMode(false);}
}


//RTS Camera Movement
if(!window->MouseDown(2))
{
float strafe = (window->KeyDown(Key:) - window->KeyDown(Key::A))*Time::GetSpeed() * 0.1;
float move = (window->KeyDown(Key::W) - window->KeyDown(Key::S))*Time::GetSpeed() * 0.1;
camera->Move(strafe,move,move);
}

//Temp Camera Movement
if(window->MouseDown(2))
{
float strafe = (window->KeyDown(Key:) - window->KeyDown(Key::A))*Time::GetSpeed() * 0.1;
float move = (window->KeyDown(Key::W) - window->KeyDown(Key::S))*Time::GetSpeed() * 0.1;
camera->Move(strafe,0,move);

//Get the mouse movement
float sx = context->GetWidth()/2;
float sy = context->GetHeight()/2;
Vec3 mouseposition = window->GetMousePosition();
float dx = mouseposition.x - sx;
float dy = mouseposition.y - sy;

//Adjust and set the camera rotation
camerarotation.x += dy / 10.0;
camerarotation.y += dx / 10.0;
camera->SetRotation(camerarotation);

//Move the mouse to the center of the screen
window->SetMousePosition(sx,sy);
}


if(method == 1)
{
//#############-- Character Movment --##################
//Place a new target position for our npcewa
if (window->MouseHit(1))
{
Vec3 p = window->GetMousePosition();
if (camera->Pick(p.x,p.y,pickinfo,0.5,true))
{
pickSphere->Show();
pickSphere->SetPosition(pickinfo.position);
}
}

//Move Character to Pick Position
characterController->GoToPoint(pickinfo.position,3.0f,6.0f);
//######################################################
}


if(method == 2)
{
//#############-- Character Movment --##################
//Place a new target position for our npcewa
if (window->MouseHit(1))
{
Vec3 p = window->GetMousePosition();
if (camera->Pick(p.x,p.y,pickinfo,0.5,true))
{
pickSphere->Show();
pickSphere->SetPosition(pickinfo.position);
}
}
//Move Character to Pick Position
characterController->GoToPoint(pickinfo.position,3.0f,6.0f);

// Use the Physics to Position and Rotate The Mesh
characterMesh->PhysicsSetRotation(characterController->GetRotation().x,characterController->GetRotation().y,characterController->GetRotation().z,0.005);
characterMesh->PhysicsSetPosition(characterController->GetPosition().x,characterController->GetPosition().y,characterController->GetPosition().z,0.005);
//######################################################
}

if(method == 3)
{
//#############-- Character Movment --##################
//Place a new target position for our npcewa
if (window->MouseHit(1))
{
Vec3 p = window->GetMousePosition();
if (camera->Pick(p.x,p.y,pickinfo,0.5,true))
{
pickSphere->Show();
pickSphere->SetPosition(pickinfo.position);
}

// Create a new Path
pointCounter = 1;
path->points.clear(); // Clear the old Points
path = path->navmesh->FindPath(characterMesh->GetPosition(true), pickinfo.position);

// Place Boxes to see the Path Points
//Cleat the old Models
for(modelsIt = models.begin() ; modelsIt != models.end() ; modelsIt++ )
{
delete (*modelsIt);
}
models.clear();
// Set new Path Models
for (int i = 0; i < path->points.size(); i++)
{
box = Model::Box(0.1,0.1,0.1);
box->SetColor(1.0,0.0,0.0);
box->SetPosition(path->points.at(i).x,path->points.at(i).y,path->points.at(i).z);
models.push_back(box);
cout << i << ": " << path->points.at(i).x << ", " << path->points.at(i).y << ", " << path->points.at(i).z << endl;
}
} //end MouseHit

if(path->points.size() > 0 )
{
for (int i = 0; i < path->points.size(); i++)
{
if(i == pointCounter)
{
// Rotate the Character to the Points
float targetX = path->points.at(i).x;
float targetY = path->points.at(i).y;
float meshPosX = characterMesh->GetPosition(true).x;
float meshPosY = characterMesh->GetPosition(true).y;

float angle = Math::ATan2(targetY - meshPosY,targetX - meshPosY);
characterMesh->SetRotation(0,angle,0);
}
}

if(characterMesh->GetPosition(true).x < path->points.at(pointCounter).x && characterMesh->GetPosition(true).y < path->points.at(pointCounter).y)
{
characterMesh->Move(0.005,0,0);
}
if(characterMesh->GetPosition(true).x >= path->points.at(pointCounter).x && characterMesh->GetPosition(true).y >= path->points.at(pointCounter).y)
{
pointCounter++;;
}

}




//Now lets Move the Character

//######################################################
}

Time::Update();
world->Update();
world->Render();

// 2d Stuff ###########################################

// Camera Projection
if(characterController)
{
Vec3 p = camera->Project(characterController->GetPosition());

std::string text = "Here are the Pivot";
Leadwerks::Font* font = Leadwerks::Context::GetCurrent()->GetFont();
p.x -= font->GetTextWidth(text)/2;
p.y -= font->GetHeight()/2;
p.y += -50;

Leadwerks::Context::GetCurrent()->SetBlendMode(Leadwerks::Blend::Alpha);
Leadwerks::Context::GetCurrent()->SetColor(0.0,1.0,0.0);
Leadwerks::Context::GetCurrent()->DrawText(text,p.x,p.y);
Leadwerks::Context::GetCurrent()->SetColor(1.0,1.0,1.0);
}

context->Sync(false);

return true;
}

 

Maybe we'll find a solution together.

I think that this is also interesting for others, too.

Link to comment
Share on other sites

i don't use C++ at the moment.

 

i think something like this should work:

local world = World:GetCurrent()
local pickinfo = PickInfo()
local rayStart = self.entity:GetPosition()
local rayEnd = Vec3(rayStart.x, rayStart.y-50, rayStart.z)
if (world:Pick(rayStart,rayEnd,pickinfo,0,true,Collision.Scene)) then
 self.entity:AlignToVector(pickinfo.normal,1)
end

however i just get a flickering rotation.

Maybe the GoToPoint method overwrites the rotation?

Link to comment
Share on other sites

Hello, i got it half working now. smile.png

 

here is the script:

function Script:Start()
 -- create pivot that is the real controller
 self.pivot = Pivot:Create()
 self.pivot:SetPosition(self.entity:GetPosition(true), true)
 self.pivot:SetMass(1)
 self.pivot:SetPhysicsMode(Entity.CharacterPhysics)
 self.pivot:SetCollisionType(Collision.Character)
end
function Script:UpdateWorld()
 -- set model position to pivot position
 self.entity:SetPosition(self.pivot:GetPosition(true), true)
 -- disable model picking
 self.entity:SetPickMode(0)

 local world = World:GetCurrent()
 local pickinfo = PickInfo()
 local rayStart = self.pivot:GetPosition()
 local rayEnd = Vec3(rayStart.x, rayStart.y-50, rayStart.z)
 -- pick the ground normal for rotation
 if (world:Pick(rayStart,rayEnd,pickinfo,0,true,Collision.Scene)) then
  local v = Vec3(pickinfo.normal.x,pickinfo.normal.y,pickinfo.normal.z)
  -- align to ground normal
  if (pickinfo.normal) then
   self.entity:AlignToVector(v,1,0.3)
  end
  System:Print("entityPick normal.x:"..pickinfo.normal.x)
  System:Print("entityPick normal.y:"..pickinfo.normal.y)
  System:Print("entityPick normal.z:"..pickinfo.normal.z)
 end

 local pivotRotation = self.pivot:GetRotation(true)
 local modelRotation = self.entity:GetRotation(true)
 -- overwrite driving direction rotation with pivot rotation
 self.entity:SetRotation(modelRotation.x, pivotRotation.y, pivotRotation.z, true)
 -- reenable model picking
 self.entity:SetPickMode(Entity.SpherePick)
end

 

However it only works on one side of a hill. the other side of a hill still rotates the model but in the wrong direction.

I need to somehow invert the rotation when on the other side.

 

Anyone an idea?

Link to comment
Share on other sites

Hello,

 

i just saw some code from Ogre3D that looked to me like almost the same commands as Leadwerks has, so i ported it over:

local terrainNormal = pickinfo.normal
 local localY = self.entity:GetRotation(true)
 local weight = 0.10
 local newNormal = localY * ( 1 - weight ) + terrainNormal * weight
 local inclinationAngle = Math:ACos(localY:Dot(newNormal))

 if (inclinationAngle ~= 0.0) then
  local inclinationAxis = Vec3( localY:Cross( newNormal) ).Normalize()
  --local inclination = Vec3( inclinationAngle, inclinationAxis ) --not exactly sure how to create a Quaternion
  local inclination = Quat( inclinationAngle, inclinationAxis )
  self.entity:SetRotation(inclination)
 end

 

but beside that i am not sure how a quaternion is now exactly represented in LE and that it seems it crashes on the :Cross() function from a Vector i had no luck.

Link to comment
Share on other sites

Hello,

Yes SetRotation accepts a Quad.

 

I think i got it working:

--Private values
Script.minTargetDistance = 1.0
function Script:Start()
 self.targetPos = self.entity:GetPosition()
 -- create pivot that is the real controller
 self.pivot = Pivot:Create()
 self.pivot:SetPosition(self.entity:GetPosition(true), true)
 self.pivot:SetMass(1)
 self.pivot:SetPhysicsMode(Entity.CharacterPhysics)
 self.pivot:SetCollisionType(Collision.Character)

 self.pivot:SetPickMode(0)
 self.entity:SetPickMode(0)
 self.entity:SetNavigationMode(true, true)
 self.originalInclinationQuat = Quat()
end
function Script:GoToPosition( pos )
 self.targetPos = Vec3(pos.x, pos.y, pos.z)
 if self.pivot:GoToPoint(pos, self.speed, self.acceleration) then
  --System:Print("unit "..self.entity:GetKeyValue("name", "").." responded. ")
 else
  self.pivot:Stop()
  --System:Print("unit "..self.entity:GetKeyValue("name", "").." cannot go there. ")
 end
end
function Script:UpdateWorld()
 -- set model position to pivot position
 self.entity:SetPosition(self.pivot:GetPosition(true), true)
 -- disable model picking
 self.entity:SetPickMode(0)

 local world = World:GetCurrent()
 local pickinfo = PickInfo()
 local pivotPos = self.pivot:GetPosition()
 local rayStart = Vec3(pivotPos.x, pivotPos.y+1, pivotPos.z)
 local rayEnd = Vec3(rayStart.x, rayStart.y-50, rayStart.z)
 -- pick the ground normal for rotation
 if (world:Pick(rayStart,rayEnd,pickinfo,0.1,true,Collision.Scene)) then
  local interpolateSpeed = 0.07

  local terrainNormal = pickinfo.normal
  local localYRel = terrainNormal.y
  local localY = Vec3( 0, localYRel, 0 )
  local weight = 0.1
  local newNormal = localY * ( 1 - weight ) + terrainNormal * weight
  local inclinationAngle = Math:ACos(localY:Dot(newNormal))

  local newNormalCross = localY:Cross( newNormal )
  local inclinationAxis = newNormalCross:Normalize()
  inclinationAxis = inclinationAxis:Inverse() --not exactly sure why
  local inclination = Quat( inclinationAngle, inclinationAxis )
  local inclinationSlerp = self.originalInclinationQuat:Slerp( inclination, interpolateSpeed / Time:GetSpeed() )
  self.entity:SetRotation(inclinationSlerp)
  self.originalInclinationQuat = inclinationSlerp -- save interpolated quaternion
  --turn model to rotation of controller
  local pivotRotation = self.pivot:GetRotation(true)
  self.entity:Turn(0,pivotRotation.y,0)
 end
 -- reenable model picking
 self.entity:SetPickMode(Entity.SpherePick)
 local selfPosition = self.entity:GetPosition(true)
 -- is entity near destination stop pathfinding
 if selfPosition:DistanceToPoint(self.targetPos) < self.minTargetDistance then
  self.pivot:Stop()
  --System:Print("unit "..self.entity:GetKeyValue("name", "").." reached destination. ")
 end
end

 

It is by no means perfect but it gets the job done for me until a better way is found by someone who is better than me which should not be hard. smile.png

post-60-0-42867500-1391882000_thumb.jpg

 

 

//Edit: added interpolation to terrain alignment

Edited by beo6
  • Upvote 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...