How do I position an image using Magick++? - c++

I know this is a very simple question, but I have been simply unable to find an answer. As a workaround, I've been using roll, but this is not ideal. I would like to be able to move the contents of my images without them rolling over to the other side using the Magick++ libary (not convert!).

Using Magick::Image.distort() is the method you need --- as pointed out by fmw42 in the comments.
Here's an example using -distort Affine, but SRT would give you more control.
#include <Magick++.h>
int main() {
Magick::Image img("wizard:");
size_t numberOfArguments = 4;
double * listOfArguments = new double[numberOfArguments];
listOfArguments[0] = 0.0;
listOfArguments[1] = 0.0;
listOfArguments[2] = img.rows() / 4.0;
listOfArguments[3] = img.columns() / 4.0;
bool bestFit = Magick::MagickFalse;
img.distort(Magick::AffineDistortion,
numberOfArguments,
listOfArguments,
bestFit);
img.write("output.png");
}
Remember that the number of arguments alter between distortion methods, and each method interprets the order of arguments differently based on argument count.
For example, with SRT the order would be mapped as ...
=============== ========================================
Total Arguments Argument Order
--------------- ----------------------------------------
1 Angle
2 Scale, Angle
3 X, Y, Angle
4 X, Y, Scale, Angle
5 X, Y, ScaleX, ScaleY, Angle
6 X, Y, Scale, Angle, NewX, NewY
7 X, Y, ScaleX, ScaleY, Angle, NewX, NewY
=============== ========================================

Related

How to rotate a point every second

I have a point that I want to rotate that corresponds to every second in time like a second hand in a clock, it should rotate 6 degrees every second but i tried timing it and it does not take a minute to make a full rotation, here is the code
void rotate(const float& ox, const float& oy, float &x, float &y, const float& rotation) {
float tx = x-ox;
float ty = y-oy;
float nx = tx*cos(rotation) - ty*sin(rotation);
float ny = tx*sin(rotation) + ty*cos(rotation);
x = nx+ox;
y = ny+oy;
}
float origx = 1280/2, origy = 720/2, pntx = origx, pnty = origy-300, rotation=6; // variables
rotate(origx, origy, pntx, pnty, rotation*timer.delta); // update point, timer is an object that gets the delta time between frames of the main loop
Need to update the values for your variables like:
your origx should be 90 deg which is 0.5π rad
your origy should also be 90 deg which is 0.5π rad
every second step (rotation) is 6 deg which is 0.033333333333π rad
For sin and cos takes radians in the argument and not degrees.

Radian or Degrees?

When I create matrix of rotation from Euler angles, Should I convert a degrees(Euler angles) to radians, and then count matrix of rotation for OpenGL?
But what should I do with a quaternions?
Should I do following:
void setQuaternionsFromEuler(float bank, float heading, float attitude)
{
float DegreeToRadian = 3.14f/180.0f;
double c1 = cos(heading/2*DegreeToRadian);
double c2 = cos(attitude/2*DegreeToRadian);
//...
double s3 = sin(bank/2*DegreeToRadian);
this.w = c1*c2*c3 - s1*s2*s3;
//...
}
And,
void setMatrixFromEuler(float x, float y, float z)
{
float DegreeToRadian = 3.14f/180.0f;
x *= DegreeToRadian;
y *= DegreeToRadian;
//...
}
Or not?
It depends on how you define your input.
The trig functions of C++ take radian exclusively, so you need to convert to radian eventually but that may be done before the data even enters your program (such that the angle values in the resources are all in radian)
Rotation matricies don't have angles anymore, so it's not really related with OpenGL, but the trigonometric functions you use from the standard library in C or C++ are defined on radians, so if your user-facing API works with degrees, then yes you should convert to take the cos/sin.

How do I manually apply an OpenGL translation matrix to a vertex?

I have a specific need to apply a stored openGL matrix to a vertex by hand. I admit a weak spot with regards to matrix math, but I have read through all the documentation I can find and I'm reasonably sure I'm doing this correctly, but I'm getting an unexpected result. What am I missing?
(Note that this may be a math question, but I suspect I'm actually misunderstanding how to apply the translation matrix, so I thought I'd try here)
In the code snippet below, #1 works fine, #2 fails...
float x=1;
float y=1;
float z=1;
float w=1;
float x2=0;
float y2=0;
float z2=0;
float w2=1;
// 1 THIS WORKS:
glLoadIdentity();
// Convert from NSArray to C float
float modelMatrix[16];
for(int x=0;x<16;x++){modelMatrix[x]=[[cs.modelView objectAtIndex:x] floatValue];}
// Load the matrix the openGL way
glLoadMatrixf(modelMatrix);
// Custom function takes two coordinates and draws a box
[self drawBoxFromX:x FromY:y FromZ:z ToX:x2 ToY:y2 ToZ:z2];
//2 THIS DOES NOT WORK: Apply the matrix by hand
glLoadIdentity();
float new_x = (x*modelMatrix[0])+(y*modelMatrix[4])+(z*modelMatrix[8])+(w*modelMatrix[12]);
float new_y = (x*modelMatrix[1])+(y*modelMatrix[5])+(z*modelMatrix[9])+(w*modelMatrix[13]);
float new_z = (x*modelMatrix[2])+(y*modelMatrix[6])+(z*modelMatrix[10])+(w*modelMatrix[14]);
float new_x2 = (x2*modelMatrix[0])+(y2*modelMatrix[4])+(z2*modelMatrix[8])+(w2*modelMatrix[12]);
float new_y2 = (x2*modelMatrix[1])+(y2*modelMatrix[5])+(z2*modelMatrix[9])+(w2*modelMatrix[13]);
float new_z2 = (x2*modelMatrix[2])+(y2*modelMatrix[6])+(z2*modelMatrix[10])+(w2*modelMatrix[14]);
// Should draw a box identical to above, but gives strange result)
[self drawBoxFromX:new_x FromY:new_y FromZ:new_z ToX:new_x2 ToY:new_y2 ToZ:new_z2];
Update:
Based on a helpful comment below I realized I was only rotating two of the vertexes rather than all 8 of the cube. The following code works as expected, posting here for anyone who runs into a similar problem wrapping their head around 3d/opengl stuff. (Note: In case it is not obvious, this is not production code. There are many more efficient and less manual ways multiply matrices and describe cubes (see comments). The purpose of this code is simply to explicitly illustrate a behavior.)
struct Cube myCube;
myCube.a1.x=-1;
myCube.a1.y=-1;
myCube.a1.z=-1;
myCube.b1.x=-1;
myCube.b1.y=-1;
myCube.b1.z=1;
myCube.c1.x=1;
myCube.c1.y=-1;
myCube.c1.z=1;
myCube.d1.x=1;
myCube.d1.y=-1;
myCube.d1.z=-1;
myCube.a2.x=-1;
myCube.a2.y=1;
myCube.a2.z=-1;
myCube.b2.x=-1;
myCube.b2.y=1;
myCube.b2.z=1;
myCube.c2.x=1;
myCube.c2.y=1;
myCube.c2.z=1;
myCube.d2.x=1;
myCube.d2.y=1;
myCube.d2.z=-1;
//1 Load modelview and draw a box (this works fine)
glLoadIdentity();
float modelMatrix[16];
for(int x=0;x<16;x++){modelMatrix[x]=[[cs.modelView objectAtIndex:x] floatValue];}
glLoadMatrixf(modelMatrix);
[self drawCube:myCube];
//2 Load the matrix by hand (identical to above)
glLoadIdentity();
float w=1;
float new_Ax = (myCube.a1.x*modelMatrix[0])+(myCube.a1.y*modelMatrix[4])+(myCube.a1.z*modelMatrix[8])+(w*modelMatrix[12]);
float new_Ay = (myCube.a1.x*modelMatrix[1])+(myCube.a1.y*modelMatrix[5])+(myCube.a1.z*modelMatrix[9])+(w*modelMatrix[13]);
float new_Az = (myCube.a1.x*modelMatrix[2])+(myCube.a1.y*modelMatrix[6])+(myCube.a1.z*modelMatrix[10])+(w*modelMatrix[14]);
float new_Bx = (myCube.b1.x*modelMatrix[0])+(myCube.b1.y*modelMatrix[4])+(myCube.b1.z*modelMatrix[8])+(w*modelMatrix[12]);
float new_By = (myCube.b1.x*modelMatrix[1])+(myCube.b1.y*modelMatrix[5])+(myCube.b1.z*modelMatrix[9])+(w*modelMatrix[13]);
float new_Bz = (myCube.b1.x*modelMatrix[2])+(myCube.b1.y*modelMatrix[6])+(myCube.b1.z*modelMatrix[10])+(w*modelMatrix[14]);
float new_Cx = (myCube.c1.x*modelMatrix[0])+(myCube.c1.y*modelMatrix[4])+(myCube.c1.z*modelMatrix[8])+(w*modelMatrix[12]);
float new_Cy = (myCube.c1.x*modelMatrix[1])+(myCube.c1.y*modelMatrix[5])+(myCube.c1.z*modelMatrix[9])+(w*modelMatrix[13]);
float new_Cz = (myCube.c1.x*modelMatrix[2])+(myCube.c1.y*modelMatrix[6])+(myCube.c1.z*modelMatrix[10])+(w*modelMatrix[14]);
float new_Dx = (myCube.d1.x*modelMatrix[0])+(myCube.d1.y*modelMatrix[4])+(myCube.d1.z*modelMatrix[8])+(w*modelMatrix[12]);
float new_Dy = (myCube.d1.x*modelMatrix[1])+(myCube.d1.y*modelMatrix[5])+(myCube.d1.z*modelMatrix[9])+(w*modelMatrix[13]);
float new_Dz = (myCube.d1.x*modelMatrix[2])+(myCube.d1.y*modelMatrix[6])+(myCube.d1.z*modelMatrix[10])+(w*modelMatrix[14]);
float new_A2x = (myCube.a2.x*modelMatrix[0])+(myCube.a2.y*modelMatrix[4])+(myCube.a2.z*modelMatrix[8])+(w*modelMatrix[12]);
float new_A2y = (myCube.a2.x*modelMatrix[1])+(myCube.a2.y*modelMatrix[5])+(myCube.a2.z*modelMatrix[9])+(w*modelMatrix[13]);
float new_A2z = (myCube.a2.x*modelMatrix[2])+(myCube.a2.y*modelMatrix[6])+(myCube.a2.z*modelMatrix[10])+(w*modelMatrix[14]);
float new_B2x = (myCube.b2.x*modelMatrix[0])+(myCube.b2.y*modelMatrix[4])+(myCube.b2.z*modelMatrix[8])+(w*modelMatrix[12]);
float new_B2y = (myCube.b2.x*modelMatrix[1])+(myCube.b2.y*modelMatrix[5])+(myCube.b2.z*modelMatrix[9])+(w*modelMatrix[13]);
float new_B2z = (myCube.b2.x*modelMatrix[2])+(myCube.b2.y*modelMatrix[6])+(myCube.b2.z*modelMatrix[10])+(w*modelMatrix[14]);
float new_C2x = (myCube.c2.x*modelMatrix[0])+(myCube.c2.y*modelMatrix[4])+(myCube.c2.z*modelMatrix[8])+(w*modelMatrix[12]);
float new_C2y = (myCube.c2.x*modelMatrix[1])+(myCube.c2.y*modelMatrix[5])+(myCube.c2.z*modelMatrix[9])+(w*modelMatrix[13]);
float new_C2z = (myCube.c2.x*modelMatrix[2])+(myCube.c2.y*modelMatrix[6])+(myCube.c2.z*modelMatrix[10])+(w*modelMatrix[14]);
float new_D2x = (myCube.d2.x*modelMatrix[0])+(myCube.d2.y*modelMatrix[4])+(myCube.d2.z*modelMatrix[8])+(w*modelMatrix[12]);
float new_D2y = (myCube.d2.x*modelMatrix[1])+(myCube.d2.y*modelMatrix[5])+(myCube.d2.z*modelMatrix[9])+(w*modelMatrix[13]);
float new_D2z = (myCube.d2.x*modelMatrix[2])+(myCube.d2.y*modelMatrix[6])+(myCube.d2.z*modelMatrix[10])+(w*modelMatrix[14]);
myCube.a1.x=new_Ax;
myCube.a1.y=new_Ay;
myCube.a1.z=new_Az;
myCube.b1.x=new_Bx;
myCube.b1.y=new_By;
myCube.b1.z=new_Bz;
myCube.c1.x=new_Cx;
myCube.c1.y=new_Cy;
myCube.c1.z=new_Cz;
myCube.d1.x=new_Dx;
myCube.d1.y=new_Dy;
myCube.d1.z=new_Dz;
myCube.a2.x=new_A2x;
myCube.a2.y=new_A2y;
myCube.a2.z=new_A2z;
myCube.b2.x=new_B2x;
myCube.b2.y=new_B2y;
myCube.b2.z=new_B2z;
myCube.c2.x=new_C2x;
myCube.c2.y=new_C2y;
myCube.c2.z=new_C2z;
myCube.d2.x=new_D2x;
myCube.d2.y=new_D2y;
myCube.d2.z=new_D2z;
[self drawCube:myCube];
Drawing a rotated box is not the same as rotating two of the box corners and then drawing an axis-parallel box. The simplest way to draw a transformed 3D box is to transform all 8 vertices.

Wave vector in 2 dimensions

So I'm trying to make the player shoot a bullet that goes towards the mouse in a wavey pattern. I can get the bullet to move in a wavey pattern (albeit not really how I predicted), but not towards the mouse.
Vector2 BulletFun::sine(Vector2 vec) {
float w = (2 * PI) / 1000; // Where 1000 is the period
float waveNum = (2 * PI) / 5; // Where 5 is the wavelength
Vector2 k(0.0F, waveNum);
float t = k.dot(vec) - (w * _time);
float x = 5 * cos(t); // Where 5 is the amplitude
float y = 5 * sin(t);
Vector2 result(x, y);
return result;
}
Right now the speed isn't much of a concern, that shouldn't be too much of a problem once I have this figured out. I do get some angle change, but it seems to be reversed and only 1/8th a circle.
I'm probably miscalculating something somewhere. I just kind of learned about wave vectors.
I've tried a few other things, such as 1 dimensional travelling waves and another thing involving adjusting a normal sine wave by vec. Which had more or less the same result.
Thanks!
EDIT:
vec is the displacement from the player's location to the mouse click location. The return is a new vector that is adjusted to follow a wave pattern, BulletFun::sine is called each time the bullet receives and update.
The setup is something like this:
void Bullet::update() {
_velocity = BulletFun::sine(_displacement);
_location.add(_velocity); // add is a property of Tuple
// which Vector2 and Point2 inherit
}
In pseudocode, what you need to do is the following:
waveVector = Vector2(travelDistance,amplitude*cos(2*PI*frequency*travelDistance/unitDistance);
cosTheta = directionVector.norm().dot(waveVector.norm());
theta = acos(cosTheta);
waveVector.rotate(theta);
waveVector.translate(originPosition);
That should compute the wave vector in a traditional coordinate frame, and then rotate it to the local coordinate frame of the direction vector (where the direction vector is the local x-axis), and then translate the wave vector relative to your desired origin position of the wave beam or whatever...
This will result in a function very similar to
Vector2
BulletFun::sine(Bullet _bullet, float _amplitude, float _frequency, float _unitDistance)
{
float displacement = _bullet.getDisplacement();
float omega = 2.0f * PI * _frequency * _displacement / _unitDistance;
// Compute the wave coordinate on the traditional, untransformed
// Cartesian coordinate frame.
Vector2 wave(_displacement, _amplitude * cos(omega));
// The dot product of two unit vectors is the cosine of the
// angle between them.
float cosTheta = _bullet.getDirection().normalize().dot(wave.normalize());
float theta = acos(cosTheta);
// Translate and rotate the wave coordinate onto
// the direction vector.
wave.translate(_bullet.origin());
wave.rotate(theta);
}

Make Objects Follow Mouse

Other questions close to this topic don't seem to help me understand it very much. I'm just starting programming using Visual Studio and Direct2D and I'm having trouble understanding how to make two "eyes," which are ellipses inside of ellipses, follow my mouse.
Inside of the function void MainWindow::CalculateLayout() I'm using
const float radius3=radius/4;
const float radius3_2=radius/5;
const float x3=x-100;
const float y3=y-150;
ellipse3 = D2D1::Ellipse(D2D1::Point2F(x3, y3), radius3, radius3_2);
//left eye
const float radius4=radius/4;
const float radius4_2=radius/5;
const float x4=x+100;
const float y4=y-150;
ellipse4 = D2D1::Ellipse(D2D1::Point2F(x4, y4), radius4, radius4_2);
//right eye
const float radius5=radius/8;
const float radius5_2=radius5/2;
const float x5=x-100;
const float y5=y-150;
ellipse5 = D2D1::Ellipse(D2D1::Point2F(x5, y5), radius5, radius5_2);
// left eyeball
const float radius6=radius/8;
const float radius6_2=radius6/2;
const float x6=x+100;
const float y6=y-150;
ellipse6 = D2D1::Ellipse(D2D1::Point2F(x6, y6), radius6, radius6_2);
// right eyeball
to set up where the eyes and eyeballs are. I think that something along the line of this should be used to control where the mouse is. I am trying to do this from a blank project, not from a form. Is the solution to simply replace const float x5=x-100 with the X value of MouseMove?
You need to replace the definition of x5, but you need to do it with a formula which will bound it to stay within the eyeball.
Your formula will look something like this:
// compute the angle from the eyes to the mouse
angle = arctan( (mouseY - y) / (mouseX - x) );
// x-100 and y-150 are assumed to be the origins (center) of the eyeball
// eyeballRadius should be the radius of the eyeball, or slightly smaller (so the eyes do not extend outside of it)
x5 = (x-100) + cos(angle) * eyeballRadius;
y5 = (y-150) + sin(angle) * eyeballRadius;
Hope this helps.
To get the cross-eyed effect when the cursor is very near, you should have each eyeball compute its own angle, for example the left's would be leftAngle = arctan( (mouseY - (y-150)) / (mouseX - (x-100)) )