Wednesday, March 18, 2020

digital image processing practice

Recently I'm working from home and doing digital image processing.
Especially I'm using latest MFC and really surprised! Every fancy UIs were almost free to use now :) it wasn't easy to make this kind of UIs when I was using MFC.



Monday, March 9, 2020

Path Smoothing

Very simple implementation of path smoothing algorithm.



private void GenerateSmoothedPaths()
{
    smoothedPaths.Clear();       
    smoothedPaths.Add(paths[0].transform.position);

    int index = 1;
    while(index < paths.Length-1)
    {
        Vector3 fromPos = smoothedPaths[smoothedPaths.Count - 1];
        Vector3 toPos = paths[index].transform.position;

        Ray ray = new Ray(fromPos, (toPos - fromPos).normalized);
        RaycastHit hitInfo;
        if ( Physics.Raycast(ray, out hitInfo, Vector3.Distance(fromPos, toPos)) )
        {  
            smoothedPaths.Add(paths[index-1].transform.position);
        }
           
        index++;
    }

    smoothedPaths.Add(paths[paths.Length-1].transform.position);
}


Tuesday, March 3, 2020

Quaternion Exponentiation

For instance I have 45 degree rotation quaternion p. and if I take p ^ (1/3) then I'll get 15 degree rotation quaternion. This is geometric interpretation of quaternion exponentiation use case.

Let say I have q^(1/3) which is 1/3 power of quaternion q.

Mathematically we can define

log q = [0 alpha*n], n is the rotation axis.

exp q = [cos(alpha) n*sin(alpha)], alpha is the rotation angle.


Quaternion Exponentiation is defined down below.

q^(t) = exp(t log q)



Quaternion QuaternionExp(Quaternion q, float t)
{
    Quaternion newQ = q;

    float currentAngle = Mathf.Acos(newQ.w);

    // At the moment newQ's x, y, z has normal and already applied sin(w)

    // q' = exp(t * log q)
    // log q = [0 alpha*n]
    // exp p = [cos(alpha) n*sin(alpha)]

    float newAngle = currentAngle * t; // cos(alpha) term
       
    // what / Mathf.Sin(currentAngle) does is extract normal vector from the appllied nx, ny, nz
    float newX = newQ.x / Mathf.Sin(currentAngle) * Mathf.Sin(newAngle);
    float newY = newQ.y / Mathf.Sin(currentAngle) * Mathf.Sin(newAngle);
    float newZ = newQ.z / Mathf.Sin(currentAngle) * Mathf.Sin(newAngle);
       
    newQ.x = newX;
    newQ.y = newY;
    newQ.z = newZ;
    newQ.w = Mathf.Cos(newAngle);

    return newQ;
}

QuaternionExp is the implementation of Quaternion Exponentiation in C#.

Like I mentioned that we have 45 degree rotation quaternion q.

Quaternion q = Quaternion.Euler(0, 45, 0);

and 1/3 degree of 45 is 15 degree so if I take q^(1/3) then I'll have 15 degree rotation quaternion and I can apply it to gameobject.



Quaternion q = Quaternion.Euler(0, 45, 0);

// q is the 45 degree rotation.
// q^(1/3) will be 15 degree rotation.       
q = QuaternionExp(q, 1.0f / 3.0f);
       
this.transform.localRotation = q;




Last thing I want to describe is why we took / Mathf.Sin(currentAngle) when we calculate newX, newY, newZ.

This is because newQ's x, y, z values are already applied sin(theta) which we needed to extract from the value. so we divide Sin(currentAngle) from all of the newQ's x, y, z and apply Sin(newAngle).

That's all!



Monday, March 2, 2020

Visibility in Unity

There are different ways to implement visibility such as generating polygons and ray tracing. The implementation I used here is using Ray Marching.



Sunday, March 1, 2020

Ray Marching


Ray Marching
2020-02-24
Kiyoung Moon

Basics
Ray Marching is a kind of ray tracing algorithm. I couldn’t see any case where it is used without SDF(Signed Distance Function).

SDF(Signed Distance Function) is a distance function which means we represent shapes with the function instead of vertices data. For instance, we have sphere, which has radius ‘r’.


If we define ‘e’ is a position of camera, we can define sphere like below.


If the function f(x,y,z) is positive then camera ‘e’ is outside of the sphere.
If the function f(x,y,z) is 0 then camera ‘e’ is on the surface of the sphere.
If the function f(x,y,z) is negative then camera ‘e’ is inside of the sphere.

We can use this value in the Ray Marching algorithm.


Ray Marching
Like I said, Ray Marching works with SDF. It will not test (collision test) with the mesh data which is vertices.

Every shapes in the Ray Marching uses SDF shapes. You can see some of primitive SDF shapes down below.



There are many primitive SDF shapes that people already discovered. You can visit iq’s website. (https://www.iquilezles.org/index.html)

What is ray marching?
First, we need a Ray. We shoot the Ray into the screen and then checks whether there are any shapes that is collide or not. Instead of using traditional collision detection logic, we can use SDF. Assume we have E which is the position of the Ray.



The start position of Ray is E. and we can check whether it is collided with sphere or not. If not then we can go forward. How much? Can we go 0.001 more? 0.01 More?
Of course, we can go 0.00000001, which is small step. It is working. Do we have any problem here? Yes. It is slow!

Now we can use SDF and can save our time. As you can see, there are three spheres and we can get the distances using this equation.






As use can see, red line is the shortest distance.



‘r’ is the radius of sphere 3(see the number inside of sphere). If we take ‘D – r’, this is the safe distance that Ray Marching algorithm can use for their step. What is the means of safe distance?

Like I shown that we could take small step which is 0.0001 for Ray but it is too slow and it is useless to check whether collision happen or not. If we take safe distance then we can move Ray quickly.

After we use safe distance for the Ray’s step then next Ray position is going to be Blue point on the Ray’s direction like below image.



Ray Marching algorithm keep moving forward until it reaches sphere or end of maximum ray distance. If Ray reaches to the end of maximum ray distance then it means there is no collision happen so pixel color will be black.

If we found collision then we can use this color of sphere.


float4 CalculateScene(float3 eye)
{
        float globalDst = maxDst;
        float3 colour = float3(0,1,0);

        // iterate all the shapes to check the distance.
        for (int i = 0; i < numShapes; ++i)
        {
               Shape shape = shapes[i];
               float distance = GetShapeDistance(shape, eye);

               // closer
               if (distance < globalDst)
               {
                       colour = shape.colour;
                       globalDst = distance;
               }
        }

        return float4(colour, globalDst); // w is the distance      
}


while (rayDst < maxDst) {
        marchSteps++;
        float4 sceneInfo = CalculateScene(ray.origin);
        float dst = sceneInfo.w;

        if (dst <= epsilon) {                
               Result[id.xy] = float4(sceneInfo.xyz, 1);
               break;
        }

        ray.origin += ray.direction * dst;
        rayDst += dst;
}

This is the result image.




Task in UnrealEngine

 https://www.youtube.com/watch?v=1lBadANnJaw