Create an orientated Quad in Eigen C++ library - c++

I'm a newbie that is driving nuts with a really simple problem :\ How to define a quad that has its center at position x=10 y=11 z=12 with side 5 and it is facing at camera.
My naive implementation:
Eigen::Vector3f quadPosition(10, 11, 12);
Eigen::Vector3f camPos(10, 5, 12);
float sideLength = 5;
Eigen::Affine3f transform = Eigen::Translation3f(position) * Eigen::AngleAxisf(3.141595, (camPos - quadPosition).normalized());
Eigen::Vector3f v0 = transform * Eigen::Vector3f(-sideLength / 2, -sideLength / 2, 0);
Eigen::Vector3f v1 = transform * Eigen::Vector3f(sideLength / 2, -sideLength / 2, 0);
Eigen::Vector3f v2 = transform * Eigen::Vector3f(sideLength / 2, sideLength / 2, 0);
Eigen::Vector3f v3 = transform * Eigen::Vector3f(-sideLength / 2, sideLength / 2, 0);
Eigen::MatrixXd verts;
verts.resize(4, 3);
verts(0, 0) = v0(0);
verts(0, 1) = v0(1);
verts(0, 2) = v0(2);
verts(1, 0) = v1(0);
verts(1, 1) = v1(1);
verts(1, 2) = v1(2);
verts(2, 0) = v2(0);
verts(2, 1) = v2(1);
verts(2, 2) = v2(2);
verts(3, 0) = v3(0);
verts(3, 1) = v3(1);
verts(3, 2) = v3(2);
Eigen::MatrixXi faces;
faces.resize(2, 3);
faces(0, 0) = 0;
faces(0, 1) = 1;
faces(0, 2) = 2;
faces(1, 0) = 0;
faces(1, 1) = 2;
faces(1, 2) = 3;
Any idea? Thank you in advance!

One common approach is to define the quad in terms of two opposed corners like: [0,0,0] and [1,1,1]. Now you know that anything in between 0 and 1 in X, Y and Z axis belong to the box ... as long as there is no rotation. Otherwise, you could also add it.

Related

Converting for loop in R to Rcpp

I've been playing around with using more efficient data structures and parallel processing and a few other things. I've made good progress getting a script from running in ~60 seconds down to running in about ~9 seconds.
The one thing I can't for the life of me get my head around though is writing a loop in Rcpp. Specifically, a loop that calculates line-by-line depending on previous-line results and updates the data as it goes.
Wondering if someone could convert my code into Rcpp that way I can back-engineer and figure out, with an example that I'm very familiar with, how its done.
It's a loop that calculates the result of 3 variables at each line. Line 1 has to be calculated separately, and then line 2 onwards calculates based on values from the current and previous lines.
This example code is just 6 lines long but my original code is many thousands:
temp <- matrix(c(0, 0, 0, 2.211, 2.345, 0, 0.8978, 1.0452, 1.1524, 0.4154,
0.7102, 0.8576, 0, 0, 0, 1.7956, 1.6348, 0,
rep(NA, 18)), ncol=6, nrow=6)
const1 <- 0.938
for (p in 1:nrow(temp)) {
if (p==1) {
temp[p, 4] <- max(min(temp[p, 2],
temp[p, 1]),
0)
temp[p, 5] <- max(temp[p, 3] + (0 - const1),
0)
temp[p, 6] <- temp[p, 1] - temp[p, 4] - temp[p, 5]
}
if (p>1) {
temp[p, 4] <- max(min(temp[p, 2],
temp[p, 1] + temp[p-1, 6]),
0)
temp[p, 5] <- max(temp[p, 3] + (temp[p-1, 6] - const1),
0)
temp[p, 6] <- temp[p-1, 6] + temp[p, 1] - temp[p, 4] - temp[p, 5]
}
}
Thanks in advance, hopefully this takes someone with Rcpp skills just a minute or two!
Here is an the sample Rcpp equivalent code:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericMatrix getResult(NumericMatrix x, double const1){
for (int p = 0; p < x.nrow(); p++){
if (p == 0){
x(p, 3) = std::max(std::min(x(p, 1), x(p, 0)), 0.0);
x(p, 4) = std::max(x(p, 2) + (0.0 - const1), 0.0);
x(p, 5) = x(p, 0) - x(p, 3) - x(p, 4);
}
if (p > 0){
x(p, 3) = std::max(std::min(x(p, 1), x(p, 0) + x(p - 1, 5)), 0.0);
x(p, 4) = std::max(x(p, 2) + (x(p - 1, 5) - const1), 0.0);
x(p, 5) = x(p - 1, 5) + x(p, 0) - x(p, 3) - x(p, 4);
}
}
return x;
}
A few notes:
Save this in a file and do Rcpp::sourceCpp("myCode.cpp") in your session to compile it and make it available within the session.
We use NumericMatrix here to represent the matrix.
You'll see that we call std::max and std::min respectively. These functions require two common data types, i.e. if we do max(x, y), both x and y must be of the same type. Numeric matrix entries are double (I believe), so you need to provide a double; hence, the change from 0 (an int in C++) to 0.0 (a double)
In C++, indexing starts from 0 instead of 1. As such, you convert R code like temp[1, 4] to temp(0, 3)
Have a look at http://adv-r.had.co.nz/Rcpp.html for more information to support your development
Update: If x was a list of vectors, here's an approach:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
List getResult(List x, double const1){
// Create a new list from x called `res`
Rcpp::List res(x);
for (int p = 0; p < x.size(); p++){
// Initiate a NumericVector `curr` with the contents of `res[p]`
Rcpp::NumericVector curr(res[p]);
if (p == 0){
curr(3) = std::max(std::min(curr(1), curr(0)), 0.0);
curr(4) = std::max(curr(2) + (0.0 - const1), 0.0);
curr(5) = curr(0) - curr(3) - curr(4);
}
if (p > 0){
// Initiate a NumericVector `prev` with the contents of `res[p-1]`
Rcpp::NumericVector prev(res[p-1]);
curr(3) = std::max(std::min(curr(1), curr(0) + prev(5)), 0.0);
curr(4) = std::max(curr(2) + (prev(5) - const1), 0.0);
curr(5) = prev(5) + curr(0) - curr(3) - curr(4);
}
}
return x;
}
So I tried both jav's answers, and did a little bit of reading. Looks to me like Lists are a R-kinda-thing and Rcpp seems to prefer simple vectors and matrices and whatnot.
So I decided to pass my vectors from the list directly into the Rcpp script. The whole thing works wonders. My ~70 second script which I got down to about ~5 seconds with parallel processing is now running in 0.3 seconds. So Rcpp is pretty awesome at this as I had read.
Here's the code I went with:
(temp is a list of 3 vectors that feed into the calculation of the other 3 vectors, and that const 1 is a constant defined earlier in the code)
R code that calls the script:
temp <- getResult(zero=temp[[i]][, 1],
one=temp[[i]][, 2],
two=temp[[i]][, 3],
const1=constant, rows=(as.double(rowslength)))
Output is a matrix with 3 columns calculated by the following Rcpp script:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericMatrix AWBMgetResult(NumericVector zero, NumericVector one,
NumericVector two, double const1, double rows){
// create numericmatrix x
Rcpp::NumericMatrix x(rows, 3);
// compute loop
for (int p = 0; p < rows; p++){
if (p == 0){
x(p, 0) = std::max(std::min(one(p), zero(p)), 0.0);
x(p, 1) = std::max(two(p) + (0.0 - const1), 0.0);
x(p, 2) = zero(p) - x(p, 0) - x(p, 1);
}
else{
x(p, 0) = std::max(std::min(one(p), zero(p) + x(p - 1, 2)), 0.0);
x(p, 1) = std::max(two(p) + (x(p - 1, 2) - const1), 0.0);
x(p, 2) = x(p - 1, 2) + zero(p) - x(p, 0) - x(p, 1);
}
}
return x;
}
I went with if else in the Rcpp code because I couldn't find out how to do 2 loops in a row, 1 of for (p in 1:1) and 1 of for (p in 2:rowslength). But it doesn't seem to matter from a speed point of view. I assumed an if else would still be quicker than an if = 1, if > 1 (since that is checking the value of p at every row)

How do I get correct answers using my code with the barycentric formula?

My function getHeightOfTerrain() is calling a barycentric formula function that is not returning the correct height for the one set test height in : heightMapFromArray[][].
I've tried watching OpenGL JAVA Game tutorials 14,21, 22, by "thin matrix" and I am confused on how to use my array: heightMapforBaryCentric in both of the supplied functions, and how to set the arguments that are passed to the baryCentic() function in some sort of manner so that I can solve the problem.
int creaateTerrain(int height, int width)
{
float holderY[6] = { 0.f ,0.f,0.f,0.f,0.f,0.f };
float scaleit = 1.5f;
float holder[6] = { 0.f,0.f,0.f,0.f,0.f,0.f };
for (int z = 0, z2 =0; z < iterationofHeightMap;z2++)
{
//each loop is two iterations and creates one quad (two triangles)
//however because each iteration is by two (i.e. : x=x+2) om bottom
//the amount of triangles is half the x value
//
//number of vertices : 80 x 80 x 6.
//column
for (int x = 0, x2 = 0; x < iterationofHeightMap;x2++)
{
//relevant - A : first triangle - on left triangle
//[row] [colum[]
holder[0] = heightMapFromArray[z][x];
//holder[0] = (float)imageData[(z / 2 * MAP_Z + (x / 2)) * 3];
//holder[0] = holder[0] / 255;// *scaleit;
vertices.push_back(glm::vec3(x, holder[0], z));
//match height map with online barycentric use
heightMapforBaryCentric[x2][z2] = holder[0];
holder[1] = heightMapFromArray[z+2][x];
//holder[1] = (float)imageData[(((z + 2) / 2 * MAP_Z + ((x) / 2))) * 3];
//holder[1] = holder[1] / 255;// 6 * scaleit;
vertices.push_back(glm::vec3(x, holder[1], z + 2));
//match height map with online barycentric use
heightMapforBaryCentric[x2][z2+1] = holder[1];
holder[2] = heightMapFromArray[z+2][x+2];
//holder[2] = (float)imageData[(((z + 2) / 2 * MAP_Z + ((x + 2) / 2))) * 3];
//holder[2] = holder[2] / 255;// *scaleit;
vertices.push_back(glm::vec3(x + 2, holder[2], z + 2));
////match height map with online barycentric use
heightMapforBaryCentric[x2+1][z2+1] = holder[2];
//relevant - B - second triangle (on right side)
holder[3] = heightMapFromArray[z][x];
//holder[3] = (float)imageData[((z / 2)*MAP_Z + (x / 2)) * 3];
//holder[3] = holder[3] / 255;// 256 * scaleit;
vertices.push_back(glm::vec3(x, holder[3], z));
holder[4] = heightMapFromArray[x+2][z+2];
//holder[4] = (float)imageData[(((z + 2) / 2 * MAP_Z + ((x + 2) / 2))) * 3];
//holder[4] = holder[4] / 255;// *scaleit;
vertices.push_back(glm::vec3(x + 2, holder[4], z + 2));
holder[5] = heightMapFromArray[x+2][z];
//holder[5] = (float)imageData[((z / 2)*MAP_Z + ((x + 2) / 2)) * 3];
//holder[5] = holder[5] / 255;// *scaleit;
vertices.push_back(glm::vec3(x + 2, holder[5], z));
x = x + 2;
}
z = z + 2;
}
return(1);
}
float getHeightOfTerrain(float worldX, float worldZ) {
float terrainX = worldX;
float terrainZ = worldZ;
int gridSquareSize = 2.0f;
gridX = (int)floor(terrainX / gridSquareSize);
gridZ = (int)floor(terrainZ / gridSquareSize);
xCoord = ((float)(fmod(terrainX, gridSquareSize)) / (float)gridSquareSize);
zCoord = ((float)(fmod(terrainZ, gridSquareSize)) / (float)gridSquareSize);
if (xCoord <= (1 - zCoord))
{
answer = baryCentric(
//left triangle
glm::vec3(0.0f, heightMapforBaryCentric[gridX][gridZ], 0.0f),
glm::vec3(0.0f, heightMapforBaryCentric[gridX][gridZ+1], 1.0f),
glm::vec3(1.0f, heightMapforBaryCentric[gridX+1][gridZ+1], 1.0f),
glm::vec2(xCoord, zCoord));
// if (answer != 1)
// {
// fprintf(stderr, "Z:gridx: %d gridz: %d answer: %f\n", gridX, gridZ,answer);
//
// }
}
else
{
//right triangle
answer = baryCentric(glm::vec3(0, heightMapforBaryCentric[gridX][gridZ], 0),
glm::vec3(1,heightMapforBaryCentric[gridX+1][gridZ+1], 1),
glm::vec3(1,heightMapforBaryCentric[gridX+1][gridZ], 0),
glm::vec2(xCoord, zCoord));
}
if (answer == 1)
{
answer = 0;
}
//answer = abs(answer - 1);
return(answer);
}
float baryCentric(glm::vec3 p1, glm::vec3 p2, glm::vec3 p3 , glm::vec2 pos) {
float det = (p2.z - p3.z) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.z - p3.z);
float l1 = ((p2.z - p3.z) * (pos.x - p3.x) + (p3.x - p2.x) * (pos.y - p3.z)) / det;
float l2 = ((p3.z - p1.z) * (pos.x - p3.x) + (p1.x - p3.x) * (pos.y - p3.z)) / det;
float l3 = 1.0f - l1 - l2;
return (l1 * p1.y + l2 * p2.y + l3 * p3.y);
}
My expected results were that the center of the test grid's height to be the set value .5 and gradually less as the heights declined. My results were the heights being all the same, varied, or increasing. Usually these heights were under the value of one.

how to control Eigen Precision

I'm trying to convert an Eigen 3x3 rotation matrix to a quaternion using this code:
//m_labelMatrix : raw data of vtk4x4 matrix4d.
//m_transformationMatrix : Eigen4x4 matrix4d.
m_transformationMatrix = Eigen::Map<Eigen::Matrix4d>(m_labelMatrix);
m_transformationMatrix.transposeInPlace();
//m_affinedMatrix : affine3d matrix.
m_affinedMatrix = m_transformationMatrix;
auto label_pos = m_affinedMatrix.translation();
auto rotationMatrix = m_affinedMatrix.linear();
auto scaleX = rotationMatrix.col(0).norm();
auto scaleY = rotationMatrix.col(1).norm();
auto scaleZ = rotationMatrix.col(2).norm();
// Make my rotation matrix orthogonal.
rotationMatrix.col(0).normalize();
rotationMatrix.col(1).normalize();
rotationMatrix.col(2) = rotationMatrix.col(0).cross(rotationMatrix.col(1));
rotationMatrix.col(2).normalize();
rotationMatrix.col(0) = rotationMatrix.col(1).cross(rotationMatrix.col(2));
rotationMatrix.col(0).normalize();
Eigen::Quaterniond q(rotationMatrix);
But, when I try to convert back to rotation matrix i get the same matrix with some different values(I think it is an Eigen rounding problem):
rotationMatrix = q.normalized().matrix();
/*3.02303 0.484642 -0.124911
-0.559522 2.94976 -0.217941
0.259569 0.71415 0.984962 */
There is a method for conversion the rotation matrix with noise
https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#Conversion_to_and_from_the_matrix_representation
"Fitting quaternions"
with Eigen , it will look like
Eigen::Matrix<Scalar, 4, 4> c;
c(0, 0) = xx - yy - zz; c(0, 1) = yx + xy; c(0, 2) = zx + xz; c(0, 3) = yz - zy;
c(1, 0) = yx + xy; c(1, 1) = yy - xx - zz; c(1, 2) = zy + yz; c(1, 3) = zx - xz;
c(2, 0) = zx + xz; c(2, 1) = zy + yz; c(2, 2) = zz - xx - yy; c(2, 3) = xy - yx;
c(3, 0) = yz - zy; c(3, 1) = zx - xz; c(3, 2) = xy - yx; c(3, 3) = xx + yy + zz;
c /= 3.0;
Eigen::SelfAdjointEigenSolver<Matrix44> es(c);
typename Vector4::Index maxIdx;
es.eigenvalues().maxCoeff(&maxIdx);
Vector4 xyzw = es.eigenvectors().col(maxIdx);

C++ Points of Vertices in Cuboid (Bitwise AND)

I'm trying to calculate the points in a cuboid given its centre (which is a Vector3) and the lengths of the sides along the x, y and z axis. I found the following on math.stackexchange.com: https://math.stackexchange.com/questions/107778/simplest-equation-for-drawing-a-cube-based-on-its-center-and-or-other-vertices which says I can use the following formulae:
The constructor for the World class is:
World::World(Vector3 o, float d1, float d2, float d3) : origin(o)
{
// If we consider an edge length to be d, we need to find r such that
// 2r = d in order to calculate the positions of each vertex in the world.
float r1 = d1 / 2,
r2 = d2 / 2,
r3 = d3 / 2;
for (int i = 0; i < 8; i++)
{
/* Sets up the vertices of the cube.
*
* #see http://bit.ly/1cc2RPG
*/
float x = o.getX() + (std::pow(-1, i&1) * r1),
y = o.getY() + (std::pow(-1, i&2) * r2),
z = o.getZ() + (std::pow(-1, i&4) * r3);
points[i] = Vector3(x, y, z);
std::cout << points[i] << "\n";
}
}
And I passing the following parameters to the constructor:
Vector3 o(0, 0, 0);
World w(o, 100.f, 100.f, 100.f);
The coordinates being output for all 8 vertices are:
(50, 50, 50)
(-50, 50, 50)
(50, 50, 50)
(-50, 50, 50)
(50, 50, 50)
(-50, 50, 50)
(50, 50, 50)
(-50, 50, 50)
Which cannot be correct. Any guidance would be very much appreciated!
The problem lies in the bitwise & inside your pow calls:
In the y and z components, they always return 0 and 2 or 4, respectively. -1^2 = -1^4 = 1, which is why the sign of these components is always positive. You could try (i&2)!=0 or (i&2) >> 1 for the y component instead. The same goes for the z component.
Change this:
float x = o.getX() + (std::pow(-1, i&1) * r1),
y = o.getY() + (std::pow(-1, i&2) * r2),
z = o.getZ() + (std::pow(-1, i&4) * r3);
To this:
float x = o.getX() + (std::pow(-1, (i ) & 1) * r1), // pow(-1, 0) == 1, pow(-1, 1) == -1
y = o.getY() + (std::pow(-1, (i >> 1) & 1) * r2), // pow(-1, 0) == 1, pow(-1, 1) == -1
z = o.getZ() + (std::pow(-1, (i >> 2) & 1) * r3); // pow(-1, 0) == 1, pow(-1, 1) == -1
Or even to this:
float x = o.getX() + (std::pow(-1, (i )) * r1), // pow(-1, {0, 2, 4, 6}) == 1, pow(-1, {1, 3, 5, 7}) == -1
y = o.getY() + (std::pow(-1, (i >> 1)) * r2), // pow(-1, {0, 2}) == 1, pow(-1, {1, 3}) == -1
z = o.getZ() + (std::pow(-1, (i >> 2)) * r3); // pow(-1, 0) == 1, pow(-1, 1) == -1
The problem is that as written even though the values you mask out identify weather or not the lengths need to be negated. They are not in the correct place value to get the desired properties from the exponentiation of -1.
Rewriting the code as I have above will solve this issue, however it would be more readable and in general more permanent just to unroll the loop and manually write if each one is an addition or subtraction without using the pow function.

Elegant way the find the Vertices of a Cube

Nearly every OpenGL tutorial lets you implement drawing a cube. Therefore the vertices of the cube are needed. In the example code I saw a long list defining every vertex. But I would like to compute the vertices of a cube rather that using a overlong list of precomputed coordinates.
A cube is made of eight vertices and twelve triangles. Vertices are defined by x, y, and z. Triangles are defined each by the indexes of three vertices.
Is there an elegant way to compute the vertices and the element indexes of a cube?
When i was "porting" the csg.js project to Java I've found some cute code which generated cube with selected center point and radius. (I know it's JS, but anyway)
// Construct an axis-aligned solid cuboid. Optional parameters are `center` and
// `radius`, which default to `[0, 0, 0]` and `[1, 1, 1]`. The radius can be
// specified using a single number or a list of three numbers, one for each axis.
//
// Example code:
//
// var cube = CSG.cube({
// center: [0, 0, 0],
// radius: 1
// });
CSG.cube = function(options) {
options = options || {};
var c = new CSG.Vector(options.center || [0, 0, 0]);
var r = !options.radius ? [1, 1, 1] : options.radius.length ?
options.radius : [options.radius, options.radius, options.radius];
return CSG.fromPolygons([
[[0, 4, 6, 2], [-1, 0, 0]],
[[1, 3, 7, 5], [+1, 0, 0]],
[[0, 1, 5, 4], [0, -1, 0]],
[[2, 6, 7, 3], [0, +1, 0]],
[[0, 2, 3, 1], [0, 0, -1]],
[[4, 5, 7, 6], [0, 0, +1]]
].map(function(info) {
return new CSG.Polygon(info[0].map(function(i) {
var pos = new CSG.Vector(
c.x + r[0] * (2 * !!(i & 1) - 1),
c.y + r[1] * (2 * !!(i & 2) - 1),
c.z + r[2] * (2 * !!(i & 4) - 1)
);
return new CSG.Vertex(pos, new CSG.Vector(info[1]));
}));
}));
};
I solved this problem with this piece code (C#):
public CubeShape(Coord3 startPos, int size) {
int l = size / 2;
verts = new Coord3[8];
for (int i = 0; i < 8; i++) {
verts[i] = new Coord3(
(i & 4) != 0 ? l : -l,
(i & 2) != 0 ? l : -l,
(i & 1) != 0 ? l : -l) + startPos;
}
tris = new Tris[12];
int vertCount = 0;
void AddVert(int one, int two, int three) =>
tris[vertCount++] = new Tris(verts[one], verts[two], verts[three]);
for (int i = 0; i < 3; i++) {
int v1 = 1 << i;
int v2 = v1 == 4 ? 1 : v1 << 1;
AddVert(0, v1, v2);
AddVert(v1 + v2, v2, v1);
AddVert(7, 7 - v2, 7 - v1);
AddVert(7 - (v1 + v2), 7 - v1, 7 - v2);
}
}
If you want to understand more of what is going on, you can check out the github page I wrote that explains it.