Include details about your goal:
So first of all, my goal is to make the points rotations of a cube aroud X, Y, and Z axis to rotate the cube itself.
Describe expected:
I expect to have that after an 17.18° rotation around X axis:
I expect to have that after an 17.18° rotation around Z axis:
Actual results:
Black shape is the default cube with no rotations
White shape is the rotated cube.
My actual result after an 17.18° rotation around X axis with my formula:
My actual result after an 17.18° rotation around Z axis with my formula:
Show what you’ve tried and tell us what you found (on this site or elsewhere) and why it didn’t meet your needs. You can get better answers when you provide research.
I have saw a few site that describe exactly what I want:
https://www.desmos.com/calculator/imazvy40oz?lang=fr
https://fr.khanacademy.org/computer-programming/cube-rotating-with-user-interaction/5953495622746112
Show some code
First of all i am using Java because my problem is my Minecraft virtually shape don't meet with the real one;
Rotation methods
public void rotateX() {
for(int i = 0; i < points.size(); i++) {
Vector vector = points.get(i);
double sinTheta = Math.sin(eulerAngle.getX());
double cosTheta = Math.cos(eulerAngle.getX());
double y = vector.getY();
double z = vector.getZ();
vector.setY(y * cosTheta - z * sinTheta);
vector.setZ(z * cosTheta + y * sinTheta);
}
}
public void rotateY() {
for(int i = 0; i < points.size(); i++) {
Vector vector = points.get(i);
double sinTheta = Math.sin(eulerAngle.getY());
double cosTheta = Math.cos(eulerAngle.getY());
double x = vector.getX();
double z = vector.getZ();
vector.setX(x * cosTheta - z * sinTheta);
vector.setZ(z * cosTheta + x * sinTheta);
}
}
public void rotateZ() {
for(int i = 0; i < points.size(); i++) {
Vector vector = points.get(i);
double sinTheta = Math.sin(eulerAngle.getZ());
double cosTheta = Math.cos(eulerAngle.getZ());
double x = vector.getX();
double y = vector.getY();
vector.setX(x * cosTheta - y * sinTheta);
vector.setY(y * cosTheta + x * sinTheta);
}
}
My setup method
public void setupPoints() {
ArrayList<Vector> points = new ArrayList<Vector>();
points.add(getA());
points.add(getB());
points.add(getC());
points.add(getD());
points.add(getE());
points.add(getF());
points.add(getG());
points.add(getH());
this.points = points;
rotateZ();
rotateY();
rotateX();
}
My points locations are (i know its not an exact cube):
My enviroment:
note: Only Y rotation works perfectly, i noticed that the rotation on the Y axis corresponds to that of the Z axis in a coordinate system where Y would be the "height", its the first time that i work on 3d space plan so i am learning. Thanks if you read until here.
Your rotation methods are correct, but they rotate around axes that pass through the origin.
You are expecting them to rotate around an axis that passes through the center of the object. You don't see the problem with the rotation around Y axis because it happens to pass through the center of the cube.
You can fix this by "moving" the object to the origin before rotating, and moving it back after rotating. For example, for the X rotation:
double y = vector.getY() - objectCenterY;
double z = vector.getZ() - objectCenterZ;
vector.setY(y * cosTheta - z * sinTheta + objectCenterY);
vector.setZ(z * cosTheta + y * sinTheta + objectCenterZ);
Related
I have a color circle where the user can choose a color from. The color is calculated with this method
public int getColorForPoint(int x, int y, float[] hsv) {
x -= fullCircleRadius;
y -= fullCircleRadius;
double centerDist = Math.sqrt(x * x + y * y);
hsv[0] = (float) (Math.atan2(y, x) / Math.PI * 180f) + 180;
hsv[1] = Math.max(0f, Math.min(1f, (float) (centerDist / innerCircleRadius)));
return Color.HSVToColor(hsv);
}
Now I need the reversed method to calculate the x and y coordinate by a given color (hsv array).
To be more specific: The user can save a color and the indicator in the color circle should "jump" to the saved color on the circle.
But I'm quite lost with this mathematics.
Looking at the way you calculate centerDist - I can tell your circle centre is at the origin (0,0).
Basically HSV is a polar co ordinate, all you need is to convert a polar co ordinate to cartesian co ordinate. which is done as follows.
public double[] getHSVtoCartesian(double[] hsv) {
double [] xy;
double theta = hsv[0];
double r = hsv[1];
xy[0] = r * Math.cos(theta);
xy[1] = r * Math.sin(theta);
return xy;
}
I have a 3D model and I need to rotate its vertices around the Y axis (The axis going straight up in my case). For example lets say i have the vert
(3,2,3)(x,y,z) and when i rotate around the Y axis only the x and z's will change. how could I implement this in java using degrees? Thanks in advance!
(FYI) this is for rotating the points on my hitbox. Each "box" is just a triangle but wrapped in a cube so i can just check if a point is in the cube. This is done per triangle per model. This works perfectly because im able to walk through meshes with holes in them and everything. However, if any rotation is applied weird things start to happen.
Edit: here is my code using Andys method
public static boolean checkPointCollision(Vector3f pos){
boolean hit=false;
float px=Math.round(pos.x);
float py=Math.round(pos.y);
float pz=Math.round(pos.z);
px=pos.x;
py=pos.y;
pz=pos.z;
long startTime=System.currentTimeMillis();
float xmin,ymin,zmin,xmax,ymax,zmax,scale,rot;
//Cube Collisions
for (Entity entity : entities) {
int colID=entity.getCollisionIndex();
boolean entHasHitbox = entity.hasHitbox();
if(colID!=-1 && hit==false && entHasHitbox){
//Gets the entitys variables
scale = entity.getScale();
rot = entity.getRotY();
//Converts to radians
rot = (float) Math.toRadians(rot);
xmin = 0;
ymin = 0;
zmin = 0;
xmax = 0;
ymax = 0;
zmax = 0;
switch(entity.getCollisionType()){
case 1:
if(entHasHitbox){
//Gets the entities hitbox
List<Vector3f> hitboxMins = entity.getHitboxMin();
List<Vector3f> hitboxMaxs = entity.getHitboxMax();
for (int i = 0; i < hitboxMins.size(); i++) {
//Gets the entities hitbox points
Vector3f min = hitboxMins.get(i);
Vector3f max = hitboxMaxs.get(i);
//Sets all local position vars to the hitboxes mins and maxes
xmin = min.x;
ymin = min.y;
zmin = min.z;
xmax = max.x;
ymax = max.y;
zmax = max.z;
//Applies the models scale
xmin *=scale;
ymin *=scale;
zmin *=scale;
xmax *=scale;
ymax *=scale;
zmax *=scale;
//Rotates points
float nxmin = (float) (Math.cos(rot) * xmin - Math.sin(rot) * zmin);
float nzmin = (float) (Math.sin(rot) * xmin + Math.cos(rot) * zmin);
float nxmax = (float) (Math.cos(rot) * xmax - Math.sin(rot) * zmax);
float nzmax = (float) (Math.sin(rot) * xmax + Math.cos(rot) * zmax);
//Sets old points to new ones
xmin = nxmin;
zmin = nzmin;
xmax = nxmax;
zmax = nzmax;
//Increase local points to the entitys world position
xmin += entity.getPosition().x;
xmax += entity.getPosition().x;
ymin += entity.getPosition().y;
ymax += entity.getPosition().y;
zmin += entity.getPosition().z;
zmax += entity.getPosition().z;
//Debug
if(entities.get(17)==entity){//entities.get(17).increaseRotation(0, 10, 0);
System.out.println(xmin+","+ymin+","+zmin);
}
//Check if point is in the hitbox
if(px>=xmin && px<=xmax
&& py>=ymin && py<=ymax
&& pz>=zmin && pz<=zmax)
{
hit=true;
//Ends to loop
i=hitboxMins.size();
}
}
}
break;
}
}
}
long endTime = System.currentTimeMillis()-startTime;
if(endTime>10){
System.out.println("Delay in Point Collision");
}
return hit;
}
Multiply your points by the following matrix:
[ c 0 -s ]
[ 0 1 0 ]
[ s 0 c ]
i.e.
[newx] [ c 0 -s ] [x]
[newy] = [ 0 1 0 ] [y]
[newz] [ s 0 c ] [z]
where (x, y, z) are your original coordinates, (newx, newy, newz) are your rotated coordinates, and c = cos(angle) and s = sin(angle). Note that Java's trig functions take their parameters as radians, so you need to convert the angle in degrees appropriately.
If you've not used matrices before, this is equivalent to the following three expressions:
newx = c * x - s * z
newy = y
newz = s * x + c * z
I'm working on a game where you are a spaceship. This spaceship has to be able to rotate. The rectangle has two arrays x[], y[] containing all the corners positions of the rectangle. But when I apply the rotation formula, I get a rather wierd rotation. To try to explain it, it looks like it's rotating the bottom left of the screen.
To make these corner arrays i take in an x position, y position, width and height.
Making of the corner-arrays
public Vertex2f(float x, float y, float w, float h){
this.x[0] = x;
this.y[0] = y;
this.x[1] = x+w;
this.y[1] = y;
this.x[2] = x+w;
this.y[2] = y+h;
this.x[3] = x;
this.y[3] = y+h;
}
My rotation function
public void rotate(float angle){
this.rotation = angle;
double cos = Math.cos(rotation);
double sin = Math.sin(rotation);
for(int i = 0; i < x.length; i++){
x[i] = (float)(cos * x[i] - sin * y[i]);
y[i] = (float)(sin * x[i] + cos * y[i]);
}
}
If it helps I am using LWJGL/OpenGL in java for all the graphics and Slick2d to load and init the sprites I am using.
Try this one:
public void rotate(float angle){
this.rotation = angle;
double cos = Math.cos(rotation);
double sin = Math.sin(rotation);
double xOffset = (x[0]+x[2])/2;
double yOffset = (y[0]+y[2])/2;
for(int i = 0; i < 3; i++){
x[i] = (float)(cos * (x[i]-xOffset) - sin * (y[i]-yOffset)) + xOffset;
y[i] = (float)(sin * (x[i]-xOffset) + cos * (y[i]-yOffset)) + yOffset;
}
}
you have to rotate around center of your rectangle. Otherwise center is in x=0 and y=0
edited:
public void rotate(float angle){
this.rotation = angle;
double cos = Math.cos(rotation);
double sin = Math.sin(rotation);
double xOffset = (x[0]+x[2])/2;
double yOffset = (y[0]+y[2])/2;
for(int i = 0; i < 3; i++){
double newX = (float)(cos * (x[i]-xOffset) - sin * (y[i]-yOffset)) + xOffset;
double newY = (float)(sin * (x[i]-xOffset) + cos * (y[i]-yOffset)) + yOffset;
x[i] = newX;
y[i] = newY;
}
}
see other thread
The problem with the formulas
x[i] = (float)(cos * x[i] - sin * y[i]);
y[i] = (float)(sin * x[i] + cos * y[i]);
apart from the missing rotation center is that you change x[i] in the first formula but expect to use the original value in the second formula. Thus you need to use local variables lx, ly as in
float lx = x[i] - xcenter;
float ly = y[i] - ycenter;
x[i] = xcenter + (float)(cos * lx - sin * ly);
y[i] = ycenter + (float)(sin * lx + cos * ly);
If the object already is rotated with an angle of rotation, then this code adds the angle angle to the total rotation angle. If instead the given argument angle is to be the new total rotation angle, then the sin and cos values need to be computed with the angle difference. That is, start the procedure with, for instance,
public void rotate(float angle){
double cos = Math.cos(angle - rotation);
double sin = Math.sin(angle - rotation);
this.rotation = angle;
Ok, I have a little problem: I'm trying to code an engine capable of rendering 3d lines onto a 2d plane, but I'm having some trouble with it.
I have a point3d class, which takes x y and z coords, a line3d class, which takes two point3d endpoints, and I have a world object containing an arraylist of line3d's. I also have point2d and line2d, which are just like their 3d counterparts, except that they lack a z coordinate.
Here's the render method:
public void render(){
for(Line3d line : world.lines){ //for every 3d line in the world
panel.l3d(line, world.main); //render that line
}
panel.repaint(); //repaint the graphic
}
Which calls upon the l3d method:
public void l3d(Line3d line, Camera view){
Point2d start = p3Top2(line.start, view), end = p3Top2(line.end, view); //convert 3d points to 2d points
if(start==null || end==null)return; //if either is null, return
lineAbs(new Line2d(start, end)); //draw the line
}
Which calls upon p3Top2:
public Point2d p3Top2(Point3d point, Camera view){ //convert 3d point to 2d point on screen
int relativeZed = point.z - view.z; //difference in z values between camera and point
if(relativeZed <= 0)return null; //if it's behind the camera, return
int sx, sy, ex, ey, tx, ty; //begin declaring rectangle formed from extending camera angle to the z coord of the point(angle of 1 = 90 degrees)
sx = (int) (view.x - (width / 2) - relativeZed * (width * view.angle)); //starting x of rectangle
ex = (int) (view.x + (width / 2) + relativeZed * (width * view.angle)); //ending x
sy = (int) (view.y - (height / 2) - relativeZed * (height * view.angle)); //starting y
ey = (int) (view.y + (height / 2) + relativeZed * (height * view.angle)); //ending y
tx = point.x - sx; //difference between point's x and start of rectangle
ty = point.y - sy; //same for y
float px = (float)tx / (float)(ex - sx), py = (float)ty / (float)(ey - sy); //px and py are the ratios of the point's x/y coords compared to the x/y of the rectangle their in
return new Point2d((int)(px * width), (int)(py * height)); //multiply it by the width and height to get positions on screen
}
And also on lineAbs:
public void lineAbs(Line2d line){
Point2d start = line.start;
Point2d end = line.end;
if(start.x>end.x){
start = line.end;
end = line.start;
}
int y = start.y; //starting y point
int white = 0xffffff;
for(int x = start.x; x<end.x; x++){ //for each x in the line
if(x < 0 || y < 0 || x > canvas.getWidth() || y > canvas.getHeight())continue; //if the point is outside of the screen, continue
y += line.getSlope().slope; //increment y by the slope
canvas.setRGB(x, y, white); //draw the point to the canvas
}
}
'canvas' is a BufferedImage being drawn to the screen. With an arbitrary camera and angle of 1, as well as a few arbitrary lines thrown in, I do see each line, but they don't appear to be rendered properly. For example, when I have three point3d's as vertices, and three lines, each with a different combination of two of the points, the lines don't appear to meet at all, although each one is visible.
I suspect the issue is in my p3Top2, but I'm not sure where, can you tell?
Now i draw pictures in circle by formula :
float x = CIRCLE_RADIUS * (float) Math.sin(2f * Math.PI * drawSquareIndex / ITEMS_COUNT + angle) * 1.75f;
where x - is a X point of circle item.
And i have a circle.
but i want to draw pictures on ellipse. What the formula i need to use?
How i can do that?
P.S. sorry about quality. Make a question from phone.
You can use parametric ellipse equaition (a = b is a case of cirle):
x = a * cos(t)
y = b * sin(t)
t = 0..2*PI
In your case
// Pseudo code
for (double t = 0; t < 2 * PI; t += 0.001) { // <- or different step
double x = RadiusX * Math.Cos(t);
double y = RadiusY * Math.Sin(t);
Paint(x, y);
}