Spherical coordinate system and rotation transformation. in c

96 views Asked by At

I'm trying to apply a normal map to my texture. I want to find the rotation angles, theta and phi(spherical cooridnate), for each vector in the normal map. I plan to rotate the normal vectors of the existing object by those angles accordingly.

I've created a function to rotate vectors by theta and phi angles. However, it's not working as expected."

below function that takes parameters for the vector to be rotated, the rotation angles (theta and phi), and returns the vector after rotation."

#include <stdio.h>
#include <math.h>

typedef struct {
    double x;
    double y;
    double z;
} t_p3;

void print_p3(const char *prefix, const t_p3 *p) {
    printf("%s [%lf, %lf, %lf]\n", prefix, p->x, p->y, p->z);
}

t_p3 rotate_vector(const t_p3 *vector, double theta, double phi) {

    t_p3 result;

    double r = sqrt(vector->x * vector->x + vector->y * vector->y + vector->z * vector->z);
    double current_theta = atan2(vector->y, vector->x);
    double current_phi = acos(vector->z / r);
    double new_theta = current_theta + theta;

    double new_phi = current_phi + phi;

    result.x = r * sin(new_theta) * cos(new_phi);
    result.y = r * sin(new_theta) * sin(new_phi);
    result.z = r * cos(new_theta);
    
    return result;
}



int main() {
    t_p3 original_vector = {1, 1, 0};
    
  
    double theta = 0.0;
    double phi = 0.0;

    t_p3 rotated_vector = rotate_vector(&original_vector, theta, phi);

    print_p3("Original Vector: ",&original_vector);
    print_p3("Rotated Vector: ", &rotated_vector);
    
    return 0;
}

Original Vector: [1.000000, 1.000000, 0.000000]

Rotated Vector: [0.000000, 1.000000, 1.000000]

Even when both theta and phi are set to 0, I expected the result to be the same as the original vector, but it's not the case. Also, rotations at other angles don't produce the expected results.

Please help me identify what I might be missing.

Wishing everyone who reads this a Happy New Year!"

2

There are 2 answers

2
Weather Vane On BEST ANSWER

You have new_phi and new_theta usage reversed in function rotate_vector().

The current_theta is the angle with the x-axis and current_phi with the z-axis.

Swapping them, it should be

result.x = r * sin(new_phi) * cos(new_theta);
result.y = r * sin(new_phi) * sin(new_theta);
result.z = r * cos(new_phi);

The program output is then

Original Vector:  [1.000000, 1.000000, 0.000000]
Rotated Vector:  [1.000000, 1.000000, 0.000000]
0
chux - Reinstate Monica On

Note that acos(vector->z / r); is risky.

  • r may be 0. This readily occurs if all vector component magnitudes are are less than sqrt(DBL_TRUE_MIN).

  • fabs(vector->z / r) may be slightly above 1.0 due to computational issues that differ from expected math and leading to NAN from acos(slightly more than 1).

Some mitigation:

//double current_phi = acos(vector->z / r);
double current_phi;
if (r == 0.0) {
  current_phi = 0.0;
} else {
  double ratio = vector->z / r;
  if (fabs(ratio > 1.0)) {
    ratio = copysign(1.0, vector->z);
  }
  current_phi = acos(ratio);
}