C# Lerping from position to position - c#

I need to make a picture box to lerp from position to position (like you can do that in unity).
How can I do that , is there a built-in function?
thanks :)

Linear interpolation (lerp) is actually a pretty easy function to implement. The equation is
float Lerp(float firstFloat, float secondFloat, float by)
{
return firstFloat * (1 - by) + secondFloat * by;
}
A higher order Lerp just wraps lower order lerps:
Vector2 Lerp(Vector2 firstVector, Vector2 secondVector, float by)
{
float retX = Lerp(firstVector.x, secondVector.x, by);
float retY = Lerp(firstVector.y, secondVector.y, by);
return new Vector2(retX, retY);
}
The DirectX SDK has all manner of math functions like Unity, but that's a lot of overhead to bring in just for Lerp. You're probably best off just implementing your own.

Greg Bahm wrote inverted lerp equation firstFloat * by + secondFloat * (1 - by), where firstFloat is the secondFloat and secondFloat is the firstFloat.
In fact, corrent lerp equation is:
firstFloat * (1 - by) + secondFloat * by
But the fastest way to linear interpolation is:
firstFloat + (secondFloat - firstFloat) * by
That's 2 additions/subtractions and 1 multiplication instead of 2 addition/subtractions and 2 multiplications.
Lerp for Vector2 is correct.
Also, the fastest way is less precise (thank you, cid):
Imprecise method, which does not guarantee v = v1 when t = 1, due to floating-point arithmetic error. This method is monotonic
This form may be used when the hardware has a native fused multiply-add instruction.
https://en.wikipedia.org/wiki/Linear_interpolation#Programming_language_support

Try this instead
float Lerp(float a, float b, float t)
{
//return firstFloat * by + secondFloat * (1 - by);
return (1f - t) * a + t * b;
}
PointF Lerp(PointF a, PointF b, float t)
{
float retX = Lerp(a.X, b.X, t);
float retY = Lerp(a.Y, b.Y, t);
return new PointF(retX, retY);
}

public static float CubicInterpolation(float v0, float v1, float v2, float v3, float t) {
//var v01 = Lerp( v0, v1, t );
//var v12 = Lerp( v1, v2, t );
//var v23 = Lerp( v2, v3, t );
//var v012 = Lerp( v01, v12, t );
//var v123 = Lerp( v12, v23, t );
//return Lerp( v012, v123, t );
var p = (v3 - v2) - (v0 - v1);
var q = (v0 - v1) - p;
var r = v2 - v0;
var s = v1;
return (p * t * 3) + (q * t * 2) + (r * t) + s;
//var r = 1f - t;
//var f0 = r * r * r;
//var f1 = r * r * t * 3;
//var f2 = r * t * t * 3;
//var f3 = t * t * t;
//return (v0 * f0) + (v1 * f1) + (v2 * f2) + (v3 * f3);
}
public static float QuadraticInterpolation(float v0, float v1, float v2, float t) {
var v01 = Lerp( v0, v1, t );
var v12 = Lerp( v1, v2, t );
return Lerp( v01, v12, t );
}
public static float Lerp(float v1, float v2, float t) {
return v1 + ((v2 - v1) * t);
}
public static float CosInterpolation(float t) {
t = (float) -Math.Cos( t * Math.PI ); // [-1, 1]
return (t + 1) / 2; // [0, 1]
}
public static float PerlinSmoothStep(float t) {
// Ken Perlin's version
return t * t * t * ((t * ((6 * t) - 15)) + 10);
}
public static float SmoothStep(float t) {
return t * t * (3 - (2 * t));
}

Related

3d Trilateration in C#

How to make the GPS algorithm to get a point based on three known points and their distances?
It is made in Unity, so it uses the Vector3 and Mathf classes, but it would be easy to remove those dependencies using a 3-sized array for each point and the standart Math class.
static float sqr(float a)
{
return a * a;
}
static float norm(Vector3 a)
{
return Mathf.Sqrt(sqr(a.x) + sqr(a.y) + sqr(a.z));
}
static float dot(Vector3 a, Vector3 b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
static Vector3 vector_cross(Vector3 a, Vector3 b)
{
return new Vector3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
}
public static Vector3[] Trilaterate(Vector3 p1, float r1, Vector3 p2, float r2, Vector3 p3, float r3)
{
Vector3 ex = (p2 - p1) / norm(p2 - p1);
float i = dot(ex, (p3 - p1));
Vector3 a = ((p3 - p1) - (ex * i));
Vector3 ey = (a / norm(a));
Vector3 ez = vector_cross(ex, ey);
float d = norm(p2 - p1);
float j = dot(ey, p3 - p1);
float x = (sqr(r1) - sqr(r2) + sqr(d)) / (2 * d);
float y = (sqr(r1) - sqr(r3) + sqr(i) + sqr(j)) / (2 * j) - (i / j) * x;
float b = sqr(r1) - sqr(x) - sqr(y);
// floating point math flaw in IEEE 754 standard
// see https://github.com/gheja/trilateration.js/issues/2
if (Mathf.Abs(b) < 0.0000000001)
{
b = 0;
}
float z = Mathf.Sqrt(b);
// no solution found
if (float.IsNaN(z))
{
return new Vector3[] { Vector3.zero };
}
Vector3 aa = p1 + ((ex * x) + (ey * y));
Vector3 p4a = (aa + (ez * z));
Vector3 p4b = (aa - (ez * z));
return new Vector3[] { p4a, p4b };
}
It is a direct translation of the JS version from gheja, all credits to them: https://github.com/gheja/trilateration.js/blob/master/trilateration.js

Aizawa attractor tending towards zero/no movement

Hello I am trying to visualize an Aizawa attractor and it's seems to work at first but then just stabilizes at zero/stops moving. I have looked at several implementations online and mine seems to be the same but I don't know why it stops moving.
Here's the code which takes in a point and returns the new point:
public class Aizawa
{
private const float a = 0.95f;
private const float b = 0.7f;
private const float c = 0.6f;
private const float d = 3.5f;
private const float e = 0.25f;
private const float f = 0.1f;
public static void Iterate(float x, float y, float z, out float dX, out float dY, out float dZ)
{
dX = ((z - b) * x - d * y);
dY = (d * x + (z - b) * y);
dZ = (c + a * z - ((z * z * z) / 3f) - (x * x + y * y) * (1f + e * z) + f * z * x * x * x);
}
}
After this I just set the point as follows:
_xPos += dX * time;
_yPos += dY * time;
_zPos += dZ * time;
I'm using unity to visualize it and here is the result so far:
screenshot
I have no idea where to go from here! Any help would be appreciated
Cheers

Quaternion vector roation

My quaternion math is a bit rusty, and I'm trying to figure out which of the following implementations is more correct...
Looking here you can see Microsoft's version of transforming a vector by a quaternion: https://referencesource.microsoft.com/#System.Numerics/System/Numerics/Vector3.cs,347
Here is the code, and it has clearly been optimized:
public static Vector3 Transform(Vector3 value, Quaternion rotation)
{
float x2 = rotation.X + rotation.X;
float y2 = rotation.Y + rotation.Y;
float z2 = rotation.Z + rotation.Z;
float wx2 = rotation.W * x2;
float wy2 = rotation.W * y2;
float wz2 = rotation.W * z2;
float xx2 = rotation.X * x2;
float xy2 = rotation.X * y2;
float xz2 = rotation.X * z2;
float yy2 = rotation.Y * y2;
float yz2 = rotation.Y * z2;
float zz2 = rotation.Z * z2;
return new Vector3(
value.X * (1.0f - yy2 - zz2) + value.Y * (xy2 - wz2) + value.Z * (xz2 + wy2),
value.X * (xy2 + wz2) + value.Y * (1.0f - xx2 - zz2) + value.Z * (yz2 - wx2),
value.X * (xz2 - wy2) + value.Y * (yz2 + wx2) + value.Z * (1.0f - xx2 - yy2));
}
However, this gives different results to my own (less optimized) implementation:
public static Vector3 Transform(this Vector3 value, Quaternion rotation)
{
var q = new Quaternion(value.X, value.Y, value.Z, 0.0f);
var res = rotation.Conjugate() * q * rotation;
return new Vector3(res.X, res.Y, res.Z);
}
public static Quaternion operator *(Quaternion value1, Quaternion value2)
{
// 9 muls, 27 adds
var tmp_00 = (value1.Z - value1.Y) * (value2.Y - value2.Z);
var tmp_01 = (value1.W + value1.X) * (value2.W + value2.X);
var tmp_02 = (value1.W - value1.X) * (value2.Y + value2.Z);
var tmp_03 = (value1.Y + value1.Z) * (value2.W - value2.X);
var tmp_04 = (value1.Z - value1.X) * (value2.X - value2.Y);
var tmp_05 = (value1.Z + value1.X) * (value2.X + value2.Y);
var tmp_06 = (value1.W + value1.Y) * (value2.W - value2.Z);
var tmp_07 = (value1.W - value1.Y) * (value2.W + value2.Z);
var tmp_08 = tmp_05 + tmp_06 + tmp_07;
var tmp_09 = (tmp_04 + tmp_08) * 0.5f;
return new Quaternion(
tmp_01 + tmp_09 - tmp_08,
tmp_02 + tmp_09 - tmp_07,
tmp_03 + tmp_09 - tmp_06,
tmp_00 + tmp_09 - tmp_05
);
}
Since these do not give the same results, one of them must be wrong, but which one is it and why?
My own implementation seems to work in the cases that I'm trying to use it in, and the MS implementation seems to be broken, but I would be surprised if it were actually incorrect, since I think it is very widely used...
Thanks! :)
There are two different conventions for rotating a vector via a quaternion, left chain and right chain. E.g.,
vnew = q * v * conjugate(q) <-- This is left chain (successive rotations stack up on the left)
vnew = conjugate(q) * v * q <-- This is right chain (successive rotations stack up on the right)
Left chain convention is typically used for active rotations, where the quaternion is being used to rotate a vector within a coordinate frame. I.e., v and vnew are two different vectors coordinatized within the same coordinate frame.
Right chain convention is typically used for passive rotations, e.g. quaternions that represent coordinate system transformations. I.e., v and vnew are actually the same vector, just coordinatized in two different coordinate frames.
The MS code you show above is a left chain convention, but your code is a right chain convention. Hence the different results.
Both conventions are valid and have their uses, but you need to be very careful when pulling code from online sources. You need to verify what the convention used by the code is in order to use it correctly. And you need to ensure the convention matches how you are using the quaternions in your particular application.

Bezier not working correctly

I'm trying to implement a simple bezier curve into my Unity game but it no seems to work.
here is a screenshot of how is being drawn:
The 4 green spheres are the Bezier's pivots, and the white spheres are the actual bezier being calculated. As you see, its kinda incorrect.
Here's my bezier code (i took it from Unity's forums):
using UnityEngine;
[System.Serializable]
public class Bezier : System.Object
{
public Vector3 p0;
public Vector3 p1;
public Vector3 p2;
public Vector3 p3;
public float ti = 0f;
private Vector3 b0 = Vector3.zero;
private Vector3 b1 = Vector3.zero;
private Vector3 b2 = Vector3.zero;
private Vector3 b3 = Vector3.zero;
private float Ax;
private float Ay;
private float Az;
private float Bx;
private float By;
private float Bz;
private float Cx;
private float Cy;
private float Cz;
// Init function v0 = 1st point, v1 = handle of the 1st point , v2 = handle of the 2nd point, v3 = 2nd point
// handle1 = v0 + v1
// handle2 = v3 + v2
public Bezier( Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3 )
{
this.p0 = v0;
this.p1 = v1;
this.p2 = v2;
this.p3 = v3;
}
// 0.0 >= t <= 1.0
public Vector3 GetPointAtTime( float t )
{
this.CheckConstant();
float t2 = t * t;
float t3 = t * t * t;
float x = this.Ax * t3 + this.Bx * t2 + this.Cx * t + p0.x;
float y = this.Ay * t3 + this.By * t2 + this.Cy * t + p0.y;
float z = this.Az * t3 + this.Bz * t2 + this.Cz * t + p0.z;
return new Vector3( x, y, z );
}
private void SetConstant()
{
this.Cx = 3f * ( ( this.p0.x + this.p1.x ) - this.p0.x );
this.Bx = 3f * ( ( this.p3.x + this.p2.x ) - ( this.p0.x + this.p1.x ) ) - this.Cx;
this.Ax = this.p3.x - this.p0.x - this.Cx - this.Bx;
this.Cy = 3f * ( ( this.p0.y + this.p1.y ) - this.p0.y );
this.By = 3f * ( ( this.p3.y + this.p2.y ) - ( this.p0.y + this.p1.y ) ) - this.Cy;
this.Ay = this.p3.y - this.p0.y - this.Cy - this.By;
this.Cz = 3f * ( ( this.p0.z + this.p1.z ) - this.p0.z );
this.Bz = 3f * ( ( this.p3.z + this.p2.z ) - ( this.p0.z + this.p1.z ) ) - this.Cz;
this.Az = this.p3.z - this.p0.z - this.Cz - this.Bz;
}
// Check if p0, p1, p2 or p3 have changed
private void CheckConstant()
{
if( this.p0 != this.b0 || this.p1 != this.b1 || this.p2 != this.b2 || this.p3 != this.b3 )
{
this.SetConstant();
this.b0 = this.p0;
this.b1 = this.p1;
this.b2 = this.p2;
this.b3 = this.p3;
}
}
}
And here is my implementation script (it's on a empty gameobject in the scene):
public class arrowPath : MonoBehaviour {
public Transform[] pontos=new Transform[4];
public Bezier bezier;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
bezier=new Bezier(pontos[0].position, pontos[1].position, pontos[2].position, pontos[3].position);
for(float u= 0.0f; u<=1.0f; u+=0.05f)
{
Graphics.DrawMesh(pontos[0].GetComponent<MeshFilter>().sharedMesh, bezier.GetPointAtTime(u), Quaternion.Euler(Vector3.zero), pontos[0].renderer.sharedMaterial, 0);
}
}
}
The "pontos" array is Transform array to save the spheres. I fill it via Unity's inspector.
I appreciate any help.
Thanks.
It looks very much like that GetPointAtTime is intended to generate the Bezier point. If that's the case, you're not evaluating the correct function at all: for a cubic Bezier, the function is:
a ‧ t³ + 3 ‧ b ‧ t² ‧ (1-t) + 3 ‧ c ‧ t ‧ (1-t)² + d ‧ (1-t)³
So your code isn't using binomials, it's simply using a straight polynomial of t which is going to generate really wrong things =)
So, changing your function:
public float ComputeBezierValue( float t, float a, float b, float c, float d )
{
float t2 = t * t,
t3 = t2 * t,
mt = 1 - t,
mt2 = mt * mt,
mt3 = mt2 * mt;
return a * t3 + 3 * b * t2 * mt + 3 * c * t * mt2 + d * mt3;
}
public Vector3 GetPointAtTime( float t )
{
this.CheckConstant();
float x = ComputeBezierValue(t, this.Ax, this.Bx, this.Cx, this.Dx);
float y = ComputeBezierValue(t, this.Ay, this.By, this.Cy, this.Dy);
float z = ComputeBezierValue(t, this.Az, this.Bz, this.Cz, this.Dz);
return new Vector3( x, y, z );
}
Also note I've written this to explicitly use four coordinates. Cubic Bezier curves need all four, Quadratic only use three (but are generally very poor for representing uniformly curving segments like circular/elliptical segments, as well as sinoids)

Collision response and elastic impulse in XNA 4.0

I know there are physic plugins for C# or XNA, but I want to create my own, so I can learn about the topic.
My problems are the following:
I try to apply an elastic impulse to my character with the right angle and velocity. The velocity is calculated the right way, the angle is not and distorts the results!
The next problem is, that my character gets into a shaking mode, though it should stand still. I know where the problem comes from, but I don't know how to fix it (edit: do I have to consider the penetration depth for that?)
The IPhysicsObject inherits the most important informations, the Vector2[] has the collisionPoint at index 0 and the penetration depth at index 1.
I have tried to work with this but yeah.. I don't know
public void ElasticImpulse(IPhysicsObject Object, Vector2[] _colPos)
{
//this function is down below
if (checkCollidingObjects(m_cCharacter, Object))
return;
//this List is like this declined:
//public static List<IPhysicsObject[]> CollidingObjects = new List<IPhysicsObject[]>();
//this list contains every pair of objects, that collided this frame, it is cleared after all physics and game logic is done.
CollidingObjects.Add(new IPhysicsObject[] { m_cCharacter, Object });
//deltavelocity is the velocity between two frames
Vector2 v1 = Velocity - DeltaVelocity;
float lv1 = (float)Math.Sqrt(v1.X * v1.X + v1.Y * v1.Y);
float m1 = Mass;
float k1 = Damping;
Vector2 v2 = Object.Physik.Velocity - Object.Physik.DeltaVelocity;
float lv2 = (float)Math.Sqrt(v2.X * v2.X + v2.Y * v2.Y);
float m2 = Object.Mass;
float k2 = Object.Physik.Damping;
Vector2 colDir1 = _colPos[0] - m_cCharacter.Position;
Vector2 colDir2 = _colPos[0] - Object.Position;
colDir1.Normalize();
colDir2.Normalize();
Vector2 colNorm1 = new Vector2(colDir1.Y, -colDir1.X);
Vector2 colNorm2 = new Vector2(colDir2.Y, -colDir2.X);
float ldir1 = (float)Math.Sqrt(colNorm1.X * colNorm1.X + colNorm1.Y * colNorm1.Y);
float ldir2 = (float)Math.Sqrt(colNorm2.X * colNorm2.X + colNorm2.Y * colNorm2.Y);
float pi = MathHelper.Pi;
//float angle1 = pi - ((v1.X * colNorm1.X + v2.Y * colNorm1.Y) / (lv1 * ldir1)) / v1.Length();
float angle1 = pi - (float)Math.Acos(((v1.X * colNorm1.X + v2.Y * colNorm1.Y) / (lv1 * ldir1)) / v1.Length());
angle1 = (float.IsNaN(angle1)) ? 0 : angle1;
//float angle2 = pi - ((v2.X * colNorm2.X + v2.Y * colNorm2.Y) / (lv2 * ldir1)) / v2.Length();
float angle2 = pi - (float)Math.Acos(((v2.X * colNorm2.X + v2.Y * colNorm2.Y) / (lv2 * ldir1)) / v2.Length());
angle2 = (float.IsNaN(angle2)) ? 0 : angle2;
//calculating the new velocities u 1/2. Got this formula out of the wiki link i posted above (took the german wiki version)
Vector2 u1 = (m1 * v1 + m2 * v2 - (m2 * (v1 - v2) * k2)) / (m1 + m2) - v1;
Vector2 u2 = (m1 * v1 + m2 * v2 - (m1 * (v2 - v1) * k1)) / (m1 + m2) - v2;
//transform the new velocities by the correct angle
Vector2 newV1 = new Vector2(
u1.X * (float)Math.Cos(angle1) - u1.Y * (float)Math.Sin(angle1),
u1.X * (float)Math.Sin(angle1) + u1.Y * (float)Math.Cos(angle1));
Vector2 newV2 = new Vector2(
u2.X * (float)Math.Cos(angle2) - u2.Y * (float)Math.Sin(angle2),
u2.X * (float)Math.Sin(angle2) + u2.Y * (float)Math.Cos(angle2));
newV1 = new Vector2(
(float.IsNaN(newV1.X)) ? 0 : newV1.X,
(float.IsNaN(newV1.Y)) ? 0 : newV1.Y);
newV2 = new Vector2(
(float.IsNaN(newV2.X)) ? 0 : newV2.X,
(float.IsNaN(newV2.Y)) ? 0 : newV2.Y);
AddForce(newV1);
Object.Physik.AddForce(newV2);
}
bool checkCollidingObjects(IPhysicsObject obj1, IPhysicsObject obj2)
{
if (CollidingObjects.Count > 0)
{
int a = CollidingObjects.FindIndex(x => (x[0] == obj1 && x[1] == obj2) ||
(x[1] == obj1 && x[0] == obj2));
return a != -1;
}
return false;
}

Categories