I'm trying to move the camera in jogl but my code doesn't seem to do anything. How do you move the camera with keyboard input? I'm drawing a rotating hexagon and I want to move the camera but I can't seem to get it working. This is my code:
import javax.media.opengl.*;
import javax.media.opengl.awt.*;
import com.sun.opengl.util.*;
import com.sun.opengl.util.gl2.GLUT;
import javax.media.opengl.glu.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class Rotation2 extends JFrame implements GLEventListener, KeyListener
{
GLCanvas canvas;
Animator an;
public Rotation2()
{
canvas=new GLCanvas();
an=new Animator(canvas);
add(canvas);
canvas.addGLEventListener(this);
canvas.addKeyListener(this);
setSize(600,400);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
an.start();
}
double eyeX = 0;
double eyeY = 0;
double eyeZ = 0;
public void init(GLAutoDrawable drawable)
{
GL2 gl=drawable.getGL().getGL2();
GLU glu = new GLU();
gl.glClearColor(0.0f,0.0f,0.0f,0.0f);
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glOrtho(-300,300,-200,200,200,-200);
//gl.glLoadIdentity();
gl.glMatrixMode(GL2.GL_MODELVIEW);
//glu.gluLookAt(5, 5, 5,0, 0, 0, 1, 100, 0);
gl.glClearDepth(1.0f); // Set background depth to farthest
gl.glEnable(GL2.GL_DEPTH_TEST); // Enable depth testing for z-culling
gl.glDepthFunc(GL2.GL_LEQUAL); // Set the type of depth-test
}
double x=0;
public void display(GLAutoDrawable drawable)
{
GL2 gl=drawable.getGL().getGL2();
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
gl.glEnable(GL2.GL_DEPTH_TEST);
gl.glLoadIdentity();
GLU glu=new GLU();
//gl.glPushMatrix();
gl.glScaled(2,2,2);
gl.glRotated(x,1,1,1);
x+=.05;
glu.gluLookAt(eyeX, eyeY, 2,0, 0, 0, 1, 100, 0);
gl.glColor3f(0,1f,0);
// front
gl.glBegin(GL2.GL_POLYGON);
gl.glVertex3d(25,50,25);
gl.glVertex3d(-25,50,25);
gl.glVertex3d(-50,0,25);
gl.glVertex3d(-25,-50,25);
gl.glVertex3d(25,-50,25);
gl.glVertex3d(50,0,25);
gl.glEnd();
//left
gl.glColor3f(1f,1f,0);
gl.glBegin(GL2.GL_POLYGON);
gl.glVertex3d(25,50,-25);
gl.glVertex3d(-25,50,-25);
gl.glVertex3d(-50,0,-25);
gl.glVertex3d(-25,-50,-25);
gl.glVertex3d(25,-50,-25);
gl.glVertex3d(50,0,-25);
gl.glEnd();
gl.glColor3f(1f,0f,0);
gl.glBegin(GL2.GL_POLYGON);
gl.glVertex3d(25,50,25);
gl.glVertex3d(25,50,-25);
gl.glVertex3d(-25,50,-25);
gl.glVertex3d(-25,50,25);
gl.glEnd();
gl.glColor3f(0f,0f,1f);
gl.glBegin(GL2.GL_POLYGON);
gl.glVertex3d(-25,50,25);
gl.glVertex3d(-25,50,-25);
gl.glVertex3d(-50,0,-25);
gl.glVertex3d(-50,0,25);
gl.glEnd();
gl.glColor3f(1f,1f,1f);
gl.glBegin(GL2.GL_POLYGON);
gl.glVertex3d(-50,0,25);
gl.glVertex3d(-50,0,-25);
gl.glVertex3d(-25,-50,-25);
gl.glVertex3d(-25,-50,25);
gl.glEnd();
gl.glColor3f(0,1f,1f);
gl.glBegin(GL2.GL_POLYGON);
gl.glVertex3d(-25,-50,25);
gl.glVertex3d(-25,-50,-25);
gl.glVertex3d(25,-50,-25);
gl.glVertex3d(25,-50,25);
gl.glEnd();
gl.glColor3f(1,0f,1f);
gl.glBegin(GL2.GL_POLYGON);
gl.glVertex3d(25,-50,25);
gl.glVertex3d(25,-50,-25);
gl.glVertex3d(50,0,-25);
gl.glVertex3d(50,0,25);
gl.glEnd();
gl.glColor3f(.2f,1f,.2f);
gl.glBegin(GL2.GL_POLYGON);
gl.glVertex3d(50,0,25);
gl.glVertex3d(50,0,-25);
gl.glVertex3d(25,50,-25);
gl.glVertex3d(25,50,25);
gl.glEnd();
//gl.glPopMatrix();
}
public void reshape(GLAutoDrawable drawable,int x,int y,int width,int height)
{}
public void dispose(GLAutoDrawable drawable)
{}
public static void main(String[] ar)
{
new Rotation2();
}
#Override
public void keyTyped(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_X) {
eyeX++;
}
else if (e.getKeyCode() == KeyEvent.VK_Y) {
eyeY++;
}
else if(e.getKeyCode() == KeyEvent.VK_Z) {
eyeZ++;
}
else {
}
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
}
that's deprecated opengl, forget it.
You are also using a very old jogl, update it, go on jogamp.org, under "Builds / Download" click on "zip", then download jogamp-all-platforms.7z extract it and set jogl as explained here
Take this Hello Triangle.
It uses already the keyListener, just copy the code you wrote for the keyTyped and paste it under keyPressed (you have to use the jogamp keyListener, what you use in your sample is instead the java awt one).
Let us know if you have any problem :)
Related
I have a simple custom Canvas
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.util.awt.TextRenderer;
import java.awt.*;
public class MyCanvas extends GLCanvas implements GLEventListener {
private GLU glu;
public MyCanvas() {
this.addGLEventListener(this);
}
TextRenderer renderer;
#Override
public void init(GLAutoDrawable drawable) {
renderer = new TextRenderer(new Font("SansSerif", Font.BOLD, 16));
GL2 gl = drawable.getGL().getGL2();
glu = new GLU();
gl.glClearColor(1f, 1f, 1f, 1f);
gl.glClearDepth(1.0f);
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glDepthFunc(GL.GL_LEQUAL);
gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
gl.glShadeModel(GL2.GL_SMOOTH);
}
#Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
GL2 gl = drawable.getGL().getGL2();
if (height == 0) height = 1;
float aspect = (float)width / height;
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(45.0, aspect, 0.1, 100.0);
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
}
#Override
public void display(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -50f);
gl.glColor3f(0.5f, 0.5f, 0.5f);
gl.glBegin(GL2.GL_TRIANGLES);
gl.glVertex3f(0.0f, 1.0f, 0.0f);
gl.glVertex3f(-1.0f, -1.0f, 0.0f);
gl.glVertex3f(1.0f, -1.0f, 0.0f);
gl.glEnd();
String text = "Text";
renderer.setColor(Color.BLACK);
renderer.begin3DRendering();
gl.glPushMatrix();
gl.glTranslated(0, 0, 0);
renderer.draw(text, 0, 0);
renderer.flush();
gl.glPopMatrix();
renderer.end3DRendering();
}
#Override
public void dispose(GLAutoDrawable drawable) { }
}
And I have a simple JFrame for displaying this canvas.
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.FPSAnimator;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class App extends JFrame {
private static final int CANVAS_WIDTH = 640;
private static final int CANVAS_HEIGHT = 480;
private static final int FPS = 60;
public App() {
GLCanvas canvas = new MyCanvas();
canvas.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
final FPSAnimator animator = new FPSAnimator(canvas, FPS, true);
this.getContentPane().add(canvas);
this.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
new Thread() {
#Override
public void run() {
if (animator.isStarted()) animator.stop();
System.exit(0);
}
}.start();
}
});
this.setTitle("JOGL (GLCanvas)");
this.pack();
this.setVisible(true);
animator.start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(App::new);
}
}
When I run programm I see very blurry text.
And when I reduce text size, then text became is more and more blurry. What should I do to get a clear text?
The text is blurry, because the font size doesn't match the rendered size on screen and bi-linear interpolation is used to magnify the font/font-texture.
The problem might happen because you are mixing 2D and 3D text rendering functions. You should either use begin3DRendering, draw3D and end3DRendering, where you can control the actual size of the text with the scaling parameter, or you use beginRendering, draw and endRendering where a orthographic projection is used to map pixels from the font to the screen.
I am currently in the process of developing an app, that needs the functionality to select screen area. I've come up with creating a transparent, undecorated, fullscreen JFrame, and adding a translucent, non-opaque JPanel inside of it, where a half-translucent dark background, as well as the selection is painted.
And while the idea (and the code) runs fine on Windows, its not the same story on linux, where the background of the JPanel does not seem to be cleared upon calling repaint() (even though i tell it to via various methods) - upon each repaint method, the background and the component get darker and darker, etc.
Here's the MVCE:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ExampleFrame extends JFrame{
private ExamplePanel selectionPane;
public ExampleFrame(){
this.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
ExampleFrame.this.dispatchEvent(new WindowEvent(ExampleFrame.this, WindowEvent.WINDOW_CLOSING));
}
}
});
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
this.setSize(screenSize);
this.setUndecorated(true);
this.setBackground(new Color(255, 255, 255, 0));
populate();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setType(Window.Type.UTILITY);
this.setVisible(true);
}
private void populate(){
this.selectionPane = new ExamplePanel();
this.setContentPane(selectionPane);
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new ExampleFrame();
}
});
}
public static class ExamplePanel extends JPanel{
private static Color bg = new Color(0,0,0,0.5f);
private int sx = -1, sy = -1, ex = -1, ey = -1;
public ExamplePanel(){
MouseAdapter mouseAdapter = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
sx = sy = ex = ey = -1;
sx = e.getX();
sy = e.getY();
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
ex = e.getX();
ey = e.getY();
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
ex = e.getX();
ey = e.getY();
repaint();
}
};
this.addMouseListener(mouseAdapter);
this.addMouseMotionListener(mouseAdapter);
this.setDoubleBuffered(false);
this.setOpaque(false);
this.setBackground(bg);
}
#Override
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D)g.create();
g2.setComposite(AlphaComposite.Clear);
g2.setBackground(new Color(255, 255, 255, 0));
g2.fillRect(0, 0, getWidth(), getHeight());
//g2.clearRect(0, 0, getWidth(), getHeight()); //neither of them work
g2.setComposite(AlphaComposite.Src.derive(.5f));
g2.setPaint(getBackground());
g2.fillRect(0, 0, getWidth(), getHeight());
g2.setComposite(AlphaComposite.Src.derive(1f));
g2.setPaint(Color.WHITE);
g2.drawString("Press Escape to exit", 10, 20);
if(!(sx == -1 || sy == -1 || ex == -1 || ey == -1)){
int asx = Math.min(sx, ex);
int asy = Math.min(sy, ey);
int w = Math.abs(ex - sx);
int h = Math.abs(ey - sy);
g2.setComposite(AlphaComposite.Src);
g2.setPaint(new Color(255, 255, 255, 0));
g2.fillRect(asx, asy, w, h);
g2.setPaint(new Color(0, 0, 0, 1));
g2.fillRect(asx, asy, w, h);
g2.setComposite(AlphaComposite.SrcOver);
g2.setStroke(new BasicStroke(2));
g2.setPaint(new Color(1, 1, 1, 0.15f));
g2.drawRect(asx-1,asy-1, w+2, h+2);
}
}
}
}
Any ideas as to what might cause this? Or maybe this is a bug with Java on linux? I had tested this under Windows 10, and Ubuntu 14.04 LTS as well as unknown version of Arch Linux running with KDE gui (tested by a friend)
EDIT: also tested under OSX (Yosemite & El capitan), both worked fine.
this.setBackground(new Color(255, 255, 255, 0));
If you want a component completely transparent then just use:
component.setOpaque( false );
This tells Swing to look for the parent component and paint it first so you don't get the painting artifacts.
private static Color bg = new Color(0,0,0,0.5f);
If you want semi-transparent backgrounds then need to do custom coding since Swing doesn't support this.
Check out Backgrounds With Transparency for more information on this topic and a couple of solutions.
One is to do your own custom painting with code like:
JPanel panel = new JPanel()
{
protected void paintComponent(Graphics g)
{
g.setColor( getBackground() );
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
};
The other solution is a reusable class that can be used with any component so you don't need to customize every component.
panel.setOpaque(false); // background of parent will be painted first
panel.setBackground( new Color(255, 0, 0, 20) );
frame.add(panel);
It's difficult to know the exact cause of the problem without been able to replicate it. There are a number of areas of concern within the code...
Not honouring the paint call chain by not calling super.paintComponent
The use of setDoubleBuffered(false)
The use of this.setBackground(bg); on a JPanel and passing an alpha based color to it
The extensive use of AlphaComposite and it's scrupulous use to try and clear the Graphics context
The basic course of action would be to simplify the paint process until such a time as you can identify the action or combination of actions which are causing the issues.
Or take another approach. Rather than using a combination of different AlphaComposite settings, you might consider just using a Area and subtract the area you want exposed from it....
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.geom.Area;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ExampleFrame extends JFrame {
private ExamplePanel selectionPane;
public ExampleFrame() {
this.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
ExampleFrame.this.dispatchEvent(new WindowEvent(ExampleFrame.this, WindowEvent.WINDOW_CLOSING));
}
}
});
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
this.setSize(screenSize);
this.setUndecorated(true);
this.setBackground(new Color(255, 255, 255, 0));
populate();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setType(Window.Type.UTILITY);
this.setVisible(true);
}
private void populate() {
this.selectionPane = new ExamplePanel();
this.setContentPane(selectionPane);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new ExampleFrame();
}
});
}
public static class ExamplePanel extends JPanel {
private static Color bg = new Color(0, 0, 0);
private int sx = -1, sy = -1, ex = -1, ey = -1;
public ExamplePanel() {
MouseAdapter mouseAdapter = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
sx = sy = ex = ey = -1;
sx = e.getX();
sy = e.getY();
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
ex = e.getX();
ey = e.getY();
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
ex = e.getX();
ey = e.getY();
repaint();
}
};
this.addMouseListener(mouseAdapter);
this.addMouseMotionListener(mouseAdapter);
this.setOpaque(false);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
Area area = new Area(new Rectangle(0, 0, getWidth(), getHeight()));
if (!(sx == -1 || sy == -1 || ex == -1 || ey == -1)) {
int asx = Math.min(sx, ex);
int asy = Math.min(sy, ey);
int w = Math.abs(ex - sx);
int h = Math.abs(ey - sy);
area.subtract(new Area(new Rectangle(asx - 1, asy - 1, w + 2, h + 2)));
}
g2.setComposite(AlphaComposite.Src.derive(.25f));
g2.setPaint(bg);
g2.fill(area);
g2.setComposite(AlphaComposite.Src.derive(1f));
g2.setPaint(Color.WHITE);
g2.drawString("Press Escape to exit", 10, 20);
g2.dispose();
}
}
}
Be sure to call super.paintComponent() if you want to clear the background.
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g.create();
I have two graphics objects. Each object is made up of tens of thousands of triangle primitives. For the sake of this example, let`s just consider the two objects as triangles - blue triangle and orange triangles.
I want to draw the blue triangle once in the background, and use the animator to over lay the several orange triangles over the blue. Think about the blue triangle as a canvas and the orange triangles are drawn over them in a pattern. Now the canvas and the orange triangles are rotated as a whole. Also, how can I scale the whole set up and rotate them around a different axes?
In this example, I want all the orange triangles to over lay on the blue.
Here is the SSCCE. If you see in the example, the blue triangles over lay on the orange. I want all the orange triangles to be on top of blue.
Also, how do I clear the canvas from an external event like a button click and completely start redrawing the scene?
import java.awt.EventQueue;
import javax.swing.JFrame;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.Animator;
import javax.swing.JButton;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class MainWin implements GLEventListener {
private JFrame frame;
private int iter = 0;
private float rotAng = 0;
private GLProfile profile;
private GLCapabilities capabilities;
private GLCanvas canvas;
private Animator animator;
private int totIter = 15;
private float scaleFac = 1f;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainWin window = new MainWin();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public MainWin() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 600, 450);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btnZoom = new JButton("Zoom");
btnZoom.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
zoomObj();
}
private void zoomObj() {
canvas.invalidate();
scaleFac -= 0.5f;
}
});
frame.getContentPane().add(btnZoom, BorderLayout.NORTH);
// Initilaize graphics profile, capabilites, canvas and animator
profile = GLProfile.get(GLProfile.GL2);
capabilities = new GLCapabilities(profile);
capabilities.setNumSamples(2);
capabilities.setSampleBuffers(true);
canvas = new GLCanvas(capabilities);
canvas.addGLEventListener(this);
canvas.requestFocusInWindow();
animator = new Animator();
animator.add(canvas);
animator.start();
frame.getContentPane().add(canvas); // add to the frame
}
#Override
public void display(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
gl.glRotatef(15, 0, 1, 0); // rotate both blue and orange objects around Y axis
gl.glScalef(scaleFac, scaleFac, scaleFac);
//blue object
gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL);
gl.glEnable(GL2.GL_MULTISAMPLE);
gl.glPushMatrix();
gl.glCallList(2);
gl.glPopMatrix();
gl.glDisable(GL2.GL_MULTISAMPLE);
// orange object
gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE);
if (iter < totIter) {
iter++;
rotAng = 5;
gl.glRotatef((float) rotAng, 0, 0, 1); // rotate each iter by 5 aroung Z. Only the orange.
gl.glEnable(GL2.GL_MULTISAMPLE);
gl.glPushMatrix();
gl.glCallList(1);
gl.glPopMatrix();
gl.glDisable(GL2.GL_MULTISAMPLE);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (iter == totIter - 1) {
animator.stop();
}
gl.glFlush();
}
#Override
public void dispose(GLAutoDrawable drawable) {
}
#Override
public void init(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
gl.glClearColor(.0f, .0f, .2f, 0.9f);
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
// buffers for multisampling
int buf[] = new int[1];
int sbuf[] = new int[1];
gl.glGetIntegerv(GL2.GL_SAMPLE_BUFFERS, buf, 0);
gl.glGetIntegerv(GL2.GL_SAMPLES, sbuf, 0);
initObj1(gl); // Orange
initObj2(gl); // Blue
}
/**
* Blue triangle. In actual code, this is a complicated 3D object made up of atleast a few tens of thousands of
* primitives in a mesh.
*
* #param gl
*/
private void initObj2(GL2 gl) {
gl.glNewList(2, GL2.GL_COMPILE);
gl.glColorMaterial(GL2.GL_FRONT, GL2.GL_DIFFUSE);
gl.glEnable(GL2.GL_COLOR_MATERIAL);
gl.glBegin(GL2.GL_TRIANGLES);
gl.glColor4f(.2f, .5f, 0.8f, 0.5f);
gl.glVertex3f(-0.5f, 0, 0);
gl.glVertex3f(0.5f, 0, 0);
gl.glVertex3f(0, 0.5f, 0);
gl.glEnd();
gl.glEndList();
}
/**
* Orange Triangle. In actual code, this is a complicated 3D object made up of atleast a few tens of thousands of
* primitives in a mesh.
*
* #param gl
*/
private void initObj1(GL2 gl) {
gl.glNewList(1, GL2.GL_COMPILE);
gl.glColorMaterial(GL2.GL_FRONT, GL2.GL_DIFFUSE);
gl.glEnable(GL2.GL_COLOR_MATERIAL);
gl.glBegin(GL2.GL_TRIANGLES);
gl.glColor4f(.95f, .45f, 0.15f, 0.5f);
gl.glVertex3f(-1, 0, 0);
gl.glVertex3f(1, 0, 0);
gl.glVertex3f(0, 1, 0);
gl.glEnd();
gl.glEndList();
}
#Override
public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) {
}
}
I'm writing a program to transform, rotate and scale a 2d square. I have the transformation and rotation working but I need help with the scaling. I can't seem to find any help on the internet to help since I have to use a math equation and I can't find the equation needed. Just so you know I don't want to use gl.glScaled(). I need to use a math equation but I can't figure it out.
package lab2;
public class Square {
public double [][] vertices = new double[4][2];
public Square(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
{
vertices[0][0]=x1;
vertices[0][1]=y1;
vertices[1][0]=x2;
vertices[1][1]=y2;
vertices[2][0]=x3;
vertices[2][1]=y3;
vertices[3][0]=x4;
vertices[3][1]=y4;
}
public double area()
{
return (vertices[1][0]-vertices[0][0])*(vertices[1][0]-vertices[0][0])+(vertices[1][1]-vertices[0][1])*(vertices[1][1]-vertices[0][1]);
}
public void translate(double tx, double ty)
{
for(int i=0;i<vertices.length;i++)
{
vertices[i][0]+=tx;
vertices[i][1]+=ty;
}
}
public void rotate(double theta)
{
//double x =0;
double x = (vertices[0][0]+vertices[2][0])/2;
double y = (vertices[0][1]+vertices[2][1])/2;
double oldX;
int i;
for(i = 0; i < 4; i++){
oldX = vertices[i][0];
vertices[i][0] = x + (vertices[i][0]-x)*Math.cos(theta*0.0174532925199)-(vertices[i][1]- y)*Math.sin(theta*0.0174532925199);
vertices[i][1] = y + (oldX-x)*Math.sin(theta*0.0174532925199)+(vertices[i][1]-y)*Math.cos(theta*0.0174532925199);
}
}
public void scale(double sx, double sy)
{
}
}
Then I also have this SquareControl.java so that I can control how I want it to work so for this program I'll be using key events
package lab2;
import java.awt.Frame;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.media.opengl.*;
import javax.media.opengl.awt.GLCanvas;
import com.sun.opengl.util.Animator;
import com.sun.opengl.util.FPSAnimator;
public class Square_Control implements GLEventListener, KeyListener {
Square square = new Square(100,100,200,100,200,200,100,200);
boolean rotating = false;
boolean scaling = false;
boolean enlarge = true;
double theta = 1;
double sx = 1.01, sy = 1.01;
GLProfile glp;
GLCapabilities caps;
GLCanvas canvas;
public Square_Control()
{
glp = GLProfile.getDefault();
caps = new GLCapabilities(glp);
canvas = new GLCanvas(caps);
Frame frame = new Frame("AWT Window Test");
frame.setSize(300, 300);
frame.add(canvas);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
canvas.addGLEventListener(this);
canvas.addKeyListener(this);
canvas.requestFocus();
Animator animator = new FPSAnimator(canvas,60);
animator.add(canvas);
animator.start();
}
public static void main(String[] args) {
Square_Control sqc = new Square_Control();
}
public void update()
{
if (rotating)
square.rotate(theta);
if (scaling)
{
square.scale(1, 1);
}
}
#Override
public void display(GLAutoDrawable drawable) {
update();
GL2 gl = drawable.getGL().getGL2();
gl.glClear(GL.GL_COLOR_BUFFER_BIT);
gl.glColor3f(1, 0, 0);
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex2d(square.vertices[0][0], square.vertices[0][1]);
gl.glVertex2d(square.vertices[1][0], square.vertices[1][1]);
gl.glVertex2d(square.vertices[2][0], square.vertices[2][1]);
gl.glVertex2d(square.vertices[3][0], square.vertices[3][1]);
gl.glEnd();
}
#Override
public void dispose(GLAutoDrawable drawable) {
// TODO Auto-generated method stub
}
#Override
public void init(GLAutoDrawable drawable) {
// TODO Auto-generated method stub
GL2 gl = drawable.getGL().getGL2();
gl.glMatrixMode(gl.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrtho(0, 300, 0, 300, -1, 1);
gl.glViewport(0, 0, 300, 300);
}
#Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent arg0) {
if (arg0.getKeyCode() == KeyEvent.VK_RIGHT)
square.translate(4, 0);
else if (arg0.getKeyCode() == KeyEvent.VK_LEFT)
square.translate(-4, 0);
else if (arg0.getKeyCode() == KeyEvent.VK_UP)
square.translate(0, 4);
else if (arg0.getKeyCode() == KeyEvent.VK_DOWN)
square.translate(0, -4);
//also add code to toggle rotation/scaling
if(arg0.getKeyCode() == KeyEvent.VK_R)
{
rotating = !rotating;
}
if(arg0.getKeyCode() == KeyEvent.VK_S)
{
scaling = !scaling;
}
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
To scale an object, you simply have to multiply each vertex by your scaling factor. A scaling factor of 1.0 will do nothing while a scaling factor of 2.0 will double de position of each vertex, hence scaling it AND probably translating it.
If you want the object to stay in place, you'll have to first translate it to your object's center, scale, then translate back to it's original position.
That is if you want to do the job software.
You should consider using Matrix functions. glRotatef, glTranslatef and glScalef.
Okay, I'm using Java and JoGL. I'm trying to load and display a texture, but the texture isn't showing up at all. I'm not getting any errors at all, so I don't know what the problem could be.
import javax.media.opengl.*;
import javax.media.opengl.glu.*;
import com.sun.opengl.util.*;
import com.sun.opengl.util.j2d.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import java.net.*;
import java.nio.*;
import javax.imageio.*;
import javax.swing.*;
public class chartest extends JFrame implements GLEventListener, KeyListener
{
private int texture;
public void display(GLAutoDrawable gLDrawable)
{
final GL gl = gLDrawable.getGL();
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glColor3f(1.0f, 1.0f, 1.0f);
gl.glBindTexture(GL.GL_TEXTURE_2D, texture);
gl.glBegin(GL.GL_QUADS); // Draw A Quad
gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f(-12.0f, -19.0f, -15.0f);
gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f( 12.0f, -19.0f, -15.0f);
gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f( 12.0f, 19.0f, -15.0f);
gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f(-12.0f, 19.0f, -15.0f);
gl.glEnd(); // Done Drawing The Quad
gl.glFlush();
}
public void displayChanged(GLAutoDrawable g, boolean b, boolean b2){}
public void init(GLAutoDrawable gLDrawable)
{
final GL gl = gLDrawable.getGL();
gl.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
gl.glShadeModel(GL.GL_FLAT);
gl.glEnable(GL.GL_TEXTURE_2D);
texture = genTexture(gl);
gl.glBindTexture(GL.GL_TEXTURE_2D, texture);
URL url = this.getClass().getResource("test.png");
try
{
BufferedImage img = ImageIO.read(url);
makeRGBTexture(gl, new GLU(), img, GL.GL_TEXTURE_2D, false);
}
catch(Exception e)
{
e.printStackTrace();
}
gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR);
}
public void reshape(GLAutoDrawable gLDrawable, int x, int y, int width, int height)
{
final GL gl = gLDrawable.getGL();
final GLU glu = new GLU();
if (height <= 0) // avoid a divide by zero error!
height = 1;
final float h = (float)width / (float)height;
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(45.0f, h, 1.0, 20.0);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
}
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_ESCAPE)
System.exit(0);
}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
public static void main(String[] args) {
chartest c = new chartest();
GLCanvas canvas = new GLCanvas(new GLCapabilities());
canvas.addGLEventListener(c);
c.add(canvas);
c.setSize(640, 480);
canvas.addKeyListener(c);
c.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
c.setVisible(true);
canvas.requestFocus();
}
//-----------------------
private void makeRGBTexture(GL gl, GLU glu, BufferedImage img, int target, boolean mipmapped)
{
ByteBuffer dest = null;
switch (img.getType())
{
case BufferedImage.TYPE_3BYTE_BGR:
case BufferedImage.TYPE_CUSTOM:
{
System.out.println("Custom");
byte[] data = ((DataBufferByte) img.getRaster().getDataBuffer()).getData();
dest = ByteBuffer.allocateDirect(99999);
dest.order(ByteOrder.nativeOrder());
dest.put(data, 0, data.length);
break;
}
case BufferedImage.TYPE_INT_RGB:
{
int[] data = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
dest = ByteBuffer.allocateDirect(data.length * BufferUtil.SIZEOF_INT);
dest.order(ByteOrder.nativeOrder());
dest.asIntBuffer().put(data, 0, data.length);
break;
}
default:
throw new RuntimeException("Unsupported image type " + img.getType());
}
if (mipmapped)
{
glu.gluBuild2DMipmaps(target, GL.GL_RGB8, img.getWidth(), img.getHeight(), GL.GL_RGB, GL.GL_UNSIGNED_BYTE, dest);
}
else
{
gl.glTexImage2D(target, 0, GL.GL_RGB, img.getWidth(), img.getHeight(), 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, dest);
}
}
private int genTexture(GL gl)
{
final int[] tmp = new int[1];
gl.glGenTextures(1, tmp, 0);
return tmp[0];
}
}
I don't see that you check for any OpenGL-errors. JOGL provides an easy way to do this. Just place glDrawable.setGL(new DebugGL(glDrawable.getGL())); at the beginning of your init method.
If that doesn't help I would check the image data and texture variable if they are non-zero.
I managed to get a texture loaded by using com.sun.opengl.util.texture.Texture and the tutorial I found here.