Rotating a shape vertically around the x-axis
Absent a clear question, a simple animation using your coordinate arrays is shown below. In general you can transform the graphics context (g2d
) or the polygonal Shape
itself (p3
); the example shows both. Resize the window to see the effect of each.
Note the last-specified-first-applied order of the transformations in at
. First, a suitable point on p3
is translated to the origin, then p3
is scaled, and then p3
is translated to the center of the panel. The + 10
fudge factor applied to p3
is an artifact of having no symmetric rotation point. It may be easier to define your polygons relative to the origin, as shown in this example.
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import javax.swing.*;
/** @see http://stackoverflow.com/questions/3405799 */
public class AffineTest extends JPanel implements ActionListener {
private static final double DELTA_THETA = Math.PI / 45; // 4°
private static final double DELTA_SCALE = 0.1;
private int[] p1x = {200, 200, 240, 240, 220, 220, 200};
private int[] p1y = {200, 260, 260, 240, 240, 200, 200};
private int[] p2x = {600, 600, 620, 620, 640, 640, 660, 660, 600};
private int[] p2y = {400, 420, 420, 460, 460, 420, 420, 400, 400};
private int[] p3x = {400, 400, 460, 460, 440, 440, 420, 420, 400};
private int[] p3y = {400, 460, 460, 400, 400, 440, 440, 400, 400};
private Polygon p1 = new Polygon(p1x, p1y, p1x.length);
private Polygon p2 = new Polygon(p2x, p2y, p2x.length);
private Polygon p3 = new Polygon(p3x, p3y, p3x.length);
private AffineTransform at = new AffineTransform();
private double dt = DELTA_THETA;
private double theta;
private double ds = DELTA_SCALE;
private double scale = 1;
private Timer timer = new Timer(100, this);
public AffineTest() {
this.setPreferredSize(new Dimension(700, 700));
this.setBackground(Color.white);
p1.translate(-50, +100);
p2.translate(-100, -100);
}
@Override
public void actionPerformed(ActionEvent event) {
theta += dt;
scale += ds;
if (scale < .5 || scale > 4) {
ds = -ds;
}
repaint();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int w = this.getWidth();
int h = this.getHeight();
g2d.drawLine(w / 2, 0, w / 2, h);
g2d.drawLine(0, h / 2, w, h / 2);
g2d.rotate(theta, w / 2, h / 2);
g2d.drawPolygon(p1);
g2d.drawPolygon(p2);
at.setToIdentity();
at.translate(w / 2, h / 2);
at.scale(scale, scale);
at.translate(-p3x[5] + 10, -p3y[5]);
g2d.setPaint(Color.blue);
g2d.fill(at.createTransformedShape(p3));
}
public void start() {
timer.start();
}
public static void main(String[] args) {
JFrame frame = new JFrame("Affine Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
AffineTest sl = new AffineTest();
frame.add(sl);
frame.pack();
frame.setVisible(true);
sl.start();
}
}
Rotating a polygon around x and y axis
In addition to refactoring and changing magic numbers, consider using a Path2D.Double object instead of a Polygon.
The object's size changes with rotating it around an axis in OpenGL
This looks normal to me.
As you're not using a view matrix, the result of your transform (and thus, the vertex coordinates that you'll see on screen, after projection) will show a triangle that heavily distorts (getting bigger in the Y direction) as it rotates towards you, and the other way around, getting smaller when it rotates away from you.
If you want to make sure your transform is correct, add a view matrix :
glm::mat4 viewMatrix = glm::lookAt(glm::vec3(5.0), glm::vec3(0.0), glm::vec3(0.0, 1.0, 0.0));
You can send it as a uniform to your shader and make it look like this :
gl_Position = projectionMatrix*viewMatrix*rotationMatrix*translationMatrix* vec4(vertexPosition_modelspace,1.0f);
If you can still see the distortion effect, then the problem actually exists, but from your code, my guess is that it's already all working well :)
Rotating and object from left/right and up/down movements
I found a way to make this work. It feels a bit clunky, and I still don't understand why the original method didn't work. If someone has a better solution, I'm still all ears!
This is how I did it:
- Display the shape in its natural orientation.
- Every time the user rotates it, add that rotation (using scene axes) to a list of rotations. (Optimise for multiple movements in one direction.)
- When drawing, apply each of the rotations in turn, in reverse order.
So for example if the user rotates the shape right, up, right, right, down, we store a list:
- Right = rotate around Y axis 90deg
- Up = rotate around X axis 90deg
- Right, Right = rotate around Y axis 180 deg
- Down = rotate around X axis -90deg
On drawing, glRotatef these in reverse order.
It seems inefficient and I feel there ought to be a better way. I'm sure there is. However it works fine.
Rotate Sphere x Axis Based on Mouse Position in three.js
Possibly, you can achieve the same thing, using THREE.OrbtiControls()
with some modifications.
Just an option with moving the camera over the rotating globe.
r96
var scene = new THREE.Scene();var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);camera.position.z = 10;var renderer = new THREE.WebGLRenderer();renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);
var globe = new THREE.Mesh(new THREE.SphereGeometry(4, 32, 16), new THREE.MeshBasicMaterial({ map: new THREE.TextureLoader().load("https://c1.staticflickr.com/3/2521/3884071286_edb50f8137_b.jpg")}));scene.add(globe);
window.addEventListener("mousemove", onMouseMove, false);
function onMouseMove(event) { camera.position.setFromSphericalCoords(10, Math.PI * -event.clientY / window.innerHeight, 0); camera.lookAt(globe.position);}
render();
function render() { requestAnimationFrame(render); globe.rotation.y -= 0.005; renderer.render(scene, camera);}
body { overflow: hidden; margin: 0;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
Related Topics
Countdowntimer in Minutes and Seconds
Firebase Firestore Get Data from Collection
I Would Like to Set My Variables at the Top of My Class Instead of in the Method
How Do Jps, Jinfo, Jstat, Jmap and Jstack Get Information About Local Java Processes
How to Find Java Heap Size and Memory Used (Linux)
What Happens When I Throw a C++ Exception from a Native Java Method
What Is the Jasperrepots-Fonts Jar for and How to Use It
How to View Visual Gc in Visualvm
Opening a Shell and Interacting with Its I/O in Java
How to Close Rmiregistry Running on Particular Port
Garbage Collector Log (Loggc) File Rotation with Logrotate Does Not Work Properly
Log4J Does Not Recreate Files on Deletion
Namenode: Java.Net.Bindexception
Why Does My Java Gui "Jump" When Moving It the First Time
Moving from Jdk 1.7 to Jdk 1.8 on Ubuntu
Why Does My Eclipse Luna 4.4 Crash on Debian Wheezy 7.4 with Oracle Jdk8 64Bit