Jump to content

Worth looking into NetImmerse script for...


makzombie

Recommended Posts

Posted

I'm currently making a mod that moves an object around the player based on their camera and was wondering if it was worth looking at the netimmerse scripts that move nodes and whether the object might be more responsive to camera movements rather than using the translateto/moveto functions.

 

It's difficult to get any sort of fast response from papyrus so anything that would work a little faster would be helpful..

 

Posted

I'm currently making a mod that moves an object around the player based on their camera and was wondering if it was worth looking at the netimmerse scripts that move nodes and whether the object might be more responsive to camera movements rather than using the translateto/moveto functions.

 

It's difficult to get any sort of fast response from papyrus so anything that would work a little faster would be helpful..

 

I honestly have no idea about any of it, but I wonder if it might help to ask docclox. He's done some work on getting objects to move about. I think he's just used papyrus, not NI, but he might have some pointers...

Posted

MoveTo is absolutely the faster one.

NetImmerse funtions are OK to move single points, not the whole object.

 

Of course MoveTo will immediately move something.

So, can I ask WHEN you wish to move objects? From time to time? When you cast a spell? Continuously inside a script?

Quick reference:

* if you do it once, then do it right. Use SplineTranslateTo.

* if you do it constantly (for example while the camera is moving) then just use MoveTo. The movements will be too fast to smooth them with the various TranslateTo.

 

 

Posted

I'm using a constantly script that triggers on update where 0.01 seconds, I've used moveto already and it seems the most rough. Also I dislike the fact it fades the object in and out as it moves and using a proxy object that moves then translating too it only increases the lag when moving. I've managed to smooth it a bit with transform to by using the distance from its goal as the speed, but getting the distance struggles with the same input lag as the other functions do. For example I set up a hot key to check the distance. If I move the mouse left then press it almost instantly, the distance with show as 0, so the getposition function doesn't accurately give the correct position at that time. 

 

Posted

I'm using a constantly script that triggers on update where 0.01 seconds, I've used moveto already and it seems the most rough. Also I dislike the fact it fades the object in and out as it moves and using a proxy object that moves then translating too it only increases the lag when moving. I've managed to smooth it a bit with transform to by using the distance from its goal as the speed, but getting the distance struggles with the same input lag as the other functions do. For example I set up a hot key to check the distance. If I move the mouse left then press it almost instantly, the distance with show as 0, so the getposition function doesn't accurately give the correct position at that time. 

 

getPosition() gives you the position of the item when the function is called. But the update queue may have up to 4 frames to be rendered.

Now. 0.01 seconds is way beyond the max refresh rate for Skyrim, that is 60 FPS, so the minimum time should be about 1sec/60 = 1.01666 so try to set it to 0.017 and probably you will increase the quality (but if the actual FPS you have is less this will just make it worst. So try also 0.025 thay is a reasonable FPS rate pretty much every time.)

Posted

 

I'm using a constantly script that triggers on update where 0.01 seconds, I've used moveto already and it seems the most rough. Also I dislike the fact it fades the object in and out as it moves and using a proxy object that moves then translating too it only increases the lag when moving. I've managed to smooth it a bit with transform to by using the distance from its goal as the speed, but getting the distance struggles with the same input lag as the other functions do. For example I set up a hot key to check the distance. If I move the mouse left then press it almost instantly, the distance with show as 0, so the getposition function doesn't accurately give the correct position at that time. 

 

getPosition() gives you the position of the item when the function is called. But the update queue may have up to 4 frames to be rendered.

Now. 0.01 seconds is way beyond the max refresh rate for Skyrim, that is 60 FPS, so the minimum time should be about 1sec/60 = 1.01666 so try to set it to 0.017 and probably you will increase the quality (but if the actual FPS you have is less this will just make it worst. So try also 0.025 thay is a reasonable FPS rate pretty much every time.)

 

 

Not sure if the change looks smoother, but the input lag is still present, would there be no way around that?

Posted

Without looking at the code (and probably executing some profiling) I cannot really help more.

 

Posted


Scriptname _mz_FM_TranslateObjectRef extends ObjectReference

import Math
import Debug
import Game

actor PlayerRef

int TransMode
float TransDistance
float TSBase
float TSMultiplier
float UpdateTime
float[] property TranslateObjectZOffset auto
float[] XPosition
float[] YPosition
float[] ZPosition

globalVariable property _mz_TranslateSpeed auto ;default value 5
globalVariable property _mz_TranslateSpeedMultiplier auto ; default value 3
globalVariable property _mz_TranslateDistance auto ;default value 200
globalVariable property _mz_TranslateMode auto ;default value 1
globalVariable property _mz_UpdateTime auto ;default value 0.01

formlist property _mz_TransformObjectFL auto
formlist property _mz_PlaceObjectFL auto

bool bKeepUpdating = True

Event OnInit()
SetModMenuValues()
RegisterforKey(45)
XPosition = new float[2]
YPosition = new float[2]
ZPosition = new float[2]
PlayerRef = GetPlayer()
RegisterforSingleUpdate(UpdateTime)
EndEvent
Event OnKeyDown(int KeyCode)
if KeyCode == 45
;Debug script
;notification(Distance as string)
endif
endevent

Event OnMenuClose(String MenuName)
SetModMenuValues()
endEvent

Event OnActivate(ObjectReference akActionRef)
int iIndex = _mz_TransformObjectFL.Find(GetBaseObject())
float ZOffset = TranslateObjectZOffset[iIndex]
ObjectReference CreatedContainer = Placeatme(_mz_PlaceObjectFL.GetAt(iIndex))
CreatedContainer.SetPosition(X,Y,Z-ZOffset)
CreatedContainer.SetAngle(GetAngleX(),GetAngleY(),GetAngleZ())
bKeepUpdating = false
UnregisterForUpdate()
self.disable()
self.deleteWhenAble()
EndEvent

Event OnUpdate()
if bKeepUpdating == True
float PlayerAngleX = PlayerRef.GetAngleX()
float PlayerAngleZ = PlayerRef.GetAngleZ()
float PlayerHeight = PlayerRef.GetHeight()

;Translate Mode 0: Orbit player around the X and Y Axis, and only move verticly when looking up/down.
XPosition[0] = TransDistance * Sin(PlayerAngleZ)
YPosition[0] = TransDistance * Cos(PlayerAngleZ)
ZPosition[0] = PlayerHeight +- (GetHeight()/2) + -TransDistance * Tan(PlayerAngleX)

;Translate Mode 1: Orbit the Player in all axis used by camera.
XPosition[1] = (TransDistance * Cos(PlayerAngleX)) * Sin(PlayerAngleZ)
YPosition[1] = (TransDistance * Cos(PlayerAngleX)) * Cos(PlayerAngleZ)
ZPosition[1] = PlayerHeight +- (GetHeight()/2) + -TransDistance * Sin(PlayerAngleX)

;Get distance between objects current position and its goal.
float Distance = GetDistanceBetweenPoints(X,Y,Z, PlayerRef.X + XPosition[TransMode], PlayerRef.Y + YPosition[TransMode], PlayerRef.Z + ZPosition[TransMode])

TranslateTo(PlayerRef.X + XPosition[TransMode], PlayerRef.Y + YPosition[TransMode], PlayerRef.Z + ZPosition[TransMode], 0, 0, PlayerAngleZ,TSBase + Distance * TSMultiplier, 0)
registerForSingleUpdate(UpdateTime)
else
UnregisterForUpdate()
endif
EndEvent

float Function GetDistanceBetweenPoints(float x1,float y1, float z1, float x2, float y2, float z2)
return (sqrt(pow((x1-x2), 2) + pow((y1-y2), 2) + pow((z1-z2), 2)))
EndFunction

Function SetModMenuValues()
notification("Update Variables")
UpdateTime = _mz_UpdateTime.GetValueInt()
TransMode = _mz_TranslateMode.GetValueInt()
TransDistance = _mz_TranslateDistance.GetValue()
TSBase = _mz_TranslateSpeed.GetValue()
TSMultiplier = _mz_TranslateSpeedMultiplier.GetValue()
EndFunction

 

Posted

The code is already pretty good. Use this one to skip some trigonometric calculations (that are heavy), and because you are using only one "TransMode" at time, you can avoid to always calculate the two and then use only one.
And you can try to simplify the distance formula by removing the pow and use a normal multiplication (more efficient).
Or better, avoid to use a function to calculate it, and put the code inline. In scripting languages calling a function has a huge performance impact when there are many parameters.
 

float PlayerAngleX = PlayerRef.GetAngleX()
float PlayerAngleZ = PlayerRef.GetAngleZ()
float PlayerHeight = PlayerRef.GetHeight()
float plSinZ = Sin(PlayerAngleZ)
float plCosZ = Cos(PlayerAngleZ)
 
float theXPos = 0.0
float theYPos = 0.0
float theZPos = 0.0
 
if TransMode
  ;Translate Mode 1: Orbit the Player in all axis used by camera.
  float trDisPlCosX = TransDistance * Cos(PlayerAngleX)
  theXPos = trDisPlCosX * plSinZ
  theYPos = trDisPlCosX * plCosZ
  theZPos = PlayerHeight - (GetHeight()/2 + TransDistance * Sin(PlayerAngleX))
else
  ;Translate Mode 0: Orbit player around the X and Y Axis, and only move vertically when looking up/down.
  theXPos = TransDistance * plSinZ
  theYPos = TransDistance * plCosZ
  theZPos = PlayerHeight - (GetHeight()/2 + TransDistance * Tan(PlayerAngleX))
endIf
 
float plX = PlayerRef.X + theXPos
float plY = PlayerRef.Y + theYPos
float plZ = PlayerRef.Z + theZPos

float Distance = sqrt((X-plX)*(X-plX) + (Y-plY)*(Y-plY) + (Z-plZ)*(Z-plZ))
 
TranslateTo(plX, plY, plZ, 0, 0, PlayerAngleZ, TSBase + Distance * TSMultiplier, 0)

EDIT: I added the missing varaible, and I did another small optimization to avoid to have a negation and an addition of the same item. Usually a subtraction is more efficient because is a single operand.

Posted

Thank you =),  I will give it a try when I get home tonight 

 

Edit - wondering what trDisPlCosX is?

 

Oops. I forgot to add it:

 

float trDisPlCosX = TransDistance * Cos(PlayerAngleX)

 

Use it only for TransMode==0, it is not used in the other case, so no need to calculate it.

Posted

Once I needed to move five actors on a spiral upwards.

And so far I do not understand how to control the position of the actor by the parametric function, ie each frame. When the faster control then there is more C ++ errors .

To make the scene I had to overclock the processor. What's the problem with Papyrus?

 

How to control the object in the Game World each frame?

Posted

Once I needed to move five actors on a spiral upwards.

And so far I do not understand how to control the position of the actor by the parametric function, ie each frame. When the faster control then there is more C ++ errors . What's the problem with Papyrus?

 

The problem was some lagging.

The author of this post uses a cyclic script to constantly position one object relative to the player position.

I only optimized a little his code for performance.

 

For sure a SKSE plugin in C++ will be faster. But not too much, because the "heavy" functions are moveTo and translateTo. And those are internal.

Posted

 

Once I needed to move five actors on a spiral upwards.

And so far I do not understand how to control the position of the actor by the parametric function, ie each frame. When the faster control then there is more C ++ errors . What's the problem with Papyrus?

 

The problem was some lagging.

The author of this post uses a cyclic script to constantly position one object relative to the player position.

I only optimized a little his code for performance.

 

For sure a SKSE plugin in C++ will be faster. But not too much, because the "heavy" functions are moveTo and translateTo. And those are internal.

 

i mean too, a parametric function suggests cycles :)

https://en.wikipedia.org/wiki/Parametric_equation

 

 

But Why??? Skyrim soo slowww...

Posted

Movements looking pretty smooth now =) still nothing to be done about the input lag i'm assuming.

 

Please give me some clues about what the "Input Lag" is.

Posted

Just the time between moving the mouse left or right and the object starting to move.

 

OK.

 

You run your code to move the object using the OnUpdate.

OnUpdate has a low execution priority. First the game calculates the positions and the whole 3D scene, then checks for the internal events, then renders the scene (in a parallel task), then runs the scripts. Every rendered frame. Not parallel. Sequential.

Now, if there is not enough time, your script will be called not every frame but a little bit less.

So you will start noticing some lags.

 

Again, you cannot rely on a static number to predict when the next frame will be rendered. It is pretty much impossible to do it.

SKSE gives you some hint about the frame rate. You may wish to use them to calculate the amount of fraction of second you have to wait.

 

But still it will not be perfect.

 

To have a perfect result you need to handle this directly on the scene calculation pipeline. And this is not accessible through scripting.

Posted

I thought as much.. I'm happy with how its working anyway, just making sure there wasn't anything else to be done. Thank you very much for your help and your insight =)

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...