Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

smooth motion without physics

Zuzu Fassbinder
Little Miss No Tomorrow
Join date: 17 Sep 2004
Posts: 2,048
08-29-2005 09:21
I wrote a script to make a fish swim around in a tank using a random walk, but I had to resort to making the object (fish) physical in order to get good smooth turning and movement. At first I tried just using rotates and move-to, but the motions were too fast. I tried slowing them down by subdividing the motion into small steps, but that was jerky and used a lot of waits and calls to the move command, which I wasn't happy about.

Any ideas? I searched thru the Wiki site, but couldnt come up with anything that fit.

Zuzu
_____________________
From: Bud
I don't want no commies in my car. No Christians either.
Angus Kuhr
Dwarf with a Hammer
Join date: 17 Jul 2005
Posts: 43
08-29-2005 21:55
I don't think you could do that with non-physical prims.

I do think, however, that particles could achieve that effect if you tinker with the right.
Zuzu Fassbinder
Little Miss No Tomorrow
Join date: 17 Sep 2004
Posts: 2,048
08-31-2005 09:25
hmm, i've done stuff like that with particles before, but I forsee two problems:
-maximum life on the particle
-my object is not just a texture

My first attempt was very similar to the move and turn scripts in this post but I had trouble making the motion smooth. But hearing of the success with the vehicle script, I may take another stab at it.

My real motivation is to produce as little lag as possible from my fishtank or koi pond
_____________________
From: Bud
I don't want no commies in my car. No Christians either.
Dustin Widget
Script Monkey for hire
Join date: 15 Feb 2006
Posts: 101
03-09-2006 23:30
i really need a look into this as well
Eloise Pasteur
Curious Individual
Join date: 14 Jul 2004
Posts: 1,952
03-10-2006 03:33
I've seen people use llApplyImpulse or llApplyImpulseAndTorque for this too - making sure the numbers are small enough that the movement is realistically slow.

I think llMoveToTarget() with suitably large tau values (5s+) might also work, fast rotations work reasonably well with most fish I think?

Non-physical movement can, with llTargetOmega(), produce reasonably smooth rotations (and that can include rotations in planes other than xy, xz or yz) but translations in non-physical movement will always be jerky since they are, in essence, teleporting the object around.
Ordinal Malaprop
really very ordinary
Join date: 9 Sep 2005
Posts: 4,607
03-10-2006 04:10
The smooth movement that I've had with small physical objects has been achieved using timers that set llSetForce with a drag parameter. You can set the drag coeefficient and the force to keep the object at a desired constant velocity.

e.g. for an object that you want moving at a fixed target velocity - and this is just off the top of my head here so might have a bug or two but illustrates the point...

CODE
vector gTargetVel = <1.0, 0.0, 0.0>;
float gDragC = 0.0;
float gAcceln = 1.0;
float gMass = 0.0;
vector gForce = ZERO_VECTOR;

default
{
state_entry()
{
gMass = llGetMass();
gDragC = 1 / llPow(llVecMag(gTargetVel), 2);
gForce = (llVecNorm(gTargetVel) * gAcceln + <0.0, 0.0, 9.8>) * gMass;
llSetTimerEvent(0.1);
}

timer()
{
vector vel = llGetVel();
llSetForce(gForce - (llVecNorm(vel) * llPow(llVecMag(vel), 2) * gDragC), FALSE);
}
}
Plastic Spoonhammer
Registered User
Join date: 9 Feb 2006
Posts: 20
03-10-2006 09:46
Jesrad Seraph has recently posted a script which moves non-physical objects smoothly - it's meant for vehicles, but should be adaptable. Since llSetPos incurs a 1/5th second delay and makes for jerky movement, his solution is to use two 'mover' scripts running concurrently and offset by a tenth of a second to achieve 10 updates per second, which gives a reasonably convincing motion provided the sim isn't under heavy load.

There are various reasons for wanting to simulate movement with non-physical objects, but in your case it seems like enabling physics for your fish would be much simpler. Is there a reason you'd prefer they stay non-physical?

- P. Spoonhammer
Rickard Roentgen
Renaissance Punk
Join date: 4 Apr 2004
Posts: 1,869
03-10-2006 11:32
for smooth rotations you can use carefully timed TargetOmega and get a pretty good effect. I've done it for wagging avatar tails. Not sure how this will work with lLSetPos though. might reset the Omega.
_____________________
Naryu Yue
Interrupted?
Join date: 23 Jul 2007
Posts: 15
08-28-2007 13:07
hehe i recently researched and achieved to overcome that problem \o/

in my case, i was moving a large boat, which could not be made physical, cuz it had 50+ prims.

what i did was code a command queue, and timely flush the queue tyo produce the smooth movement. if you issue a new command,m it will be flushed and executed in the next Timer() event, meaning it gets delayed, but i asure that every command in the queue is executed. If you dont issue a new command, it just keeps doing the last executed one, meaning it keeps going in a certain direction, until you tell it to go another direction, or stop.

The way i chose to issue commands was to send them in a channel (llSay()) by a another script, which I called autopilot.

it works pretty much like any FIFO kind socket communication channel ;)

CODE

//Smooth Movement Script by Naryu Yue
//Do not Change any settings unless youre pretty sure what youre doing!
//Feel free to use and distribute, making sure to keep the credits, thx!

list commands = ["forward","back","left","right","stop"];
list queue;

string currCommand;

float delay = 0.1;
float strength = 10;
float damping = 0.1;

vector AXIS_UP = <0,0,1>;
vector AXIS_LEFT = <0,1,0>;
vector AXIS_RIGHT = <0,-1,0>;
vector AXIS_FWD = <1,0,0>;
vector AXIS_BACK = <-1,0,0>;

queueCommand(string command)
{
queue = queue + [command];
}

string flushCommand()
{
string Command = llList2String(queue, 0);
queue = llDeleteSubList(queue, 0,0);

if (Command == "forward") forward();
if (Command == "back") back();
if (Command == "left") left();
if (Command == "right") right();
if (Command == "stop") stop();

Command = llList2String(queue, llGetListLength(queue)-1);

return Command;
}

forward()
{
llSetPos(llGetPos()+((0.1*AXIS_FWD)*llGetRot()));
}

back()
{
llSetPos(llGetPos()+((0.1*AXIS_BACK)*llGetRot()));
}

left()
{
llSetRot(llGetRot()*llEuler2Rot(DEG_TO_RAD*<0,0,1>));
llSetPos(llGetPos()+((0.1*AXIS_FWD)*llGetRot()*llAxisAngle2Rot(AXIS_UP, DEG_TO_RAD*10)));
}

right()
{
llSetRot(llGetRot()*llEuler2Rot(DEG_TO_RAD*<0,0,-1>));
llSetPos(llGetPos()+((0.1*AXIS_FWD)*llGetRot()*llAxisAngle2Rot(AXIS_UP, DEG_TO_RAD*10)));
}

stop()
{
llSay(0,"stopping all movement");
queue = [];
}

rotation getRotToPointAxisAt(vector axis, vector target) {
return llGetRot() * llRotBetween(llVecNorm(axis * llGetRot()), llVecNorm(target - llGetPos()));
}

default
{
state_entry()
{
llListen(90,"",NULL_KEY,"");
llSetTimerEvent(delay);
}

listen(integer channel, string name, key who, string msg)
{
integer index = llListFindList(commands, [msg]);
if (index != -1)
{
queueCommand(msg);
}
else
{
llSay(0,msg+": Invalid Command");
}
}

timer()
{
string lastCommand = flushCommand();
queueCommand(lastCommand);
}

}