How to implement the main() method while using Processing in Java? - java

I tried to implement the following processing code in a JFrame in netbeans.
code was taken from http://www.geekmomprojects.com/mpu-6050-dmp-data-from-i2cdevlib/
However after running MyFrame.java the it only shows a still image in the frame.
It is not taking the serial readings.
MyProcessingSketch.java
`package testprocessing;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
import java.util.Arrays;
import processing.core.*;
import processing.serial.*;
import processing.opengl.*;
import toxi.geom.*;
import toxi.processing.*;
public class MyProcessingSketch extends PApplet {
ToxiclibsSupport gfx;
Serial port; // The serial port
char[] teapotPacket = new char[14]; // InvenSense Teapot packet
int serialCount = 0; // current packet byte position
int synced = 0;
int interval = 0;
float[] q = new float[4];
Quaternion quat = new Quaternion(1, 0, 0, 0);
float[] gravity = new float[3];
float[] euler = new float[3];
float[] ypr = new float[3];
#Override
public void setup() {
// 300px square viewport using OpenGL rendering
size(300, 300, OPENGL);
gfx = new ToxiclibsSupport(this);
// setup lights and antialiasing
lights();
smooth();
// display serial port list for debugging/clarity
System.out.println(Arrays.toString(Serial.list()));
// get the first available port (use EITHER this OR the specific port code below)
//String portName = Serial.list()[0];
// get a specific serial port (use EITHER this OR the first-available code above)
String portName = "COM10";
// open the serial port
port = new Serial(this, portName, 9600);
// send single character to trigger DMP init/start
// (expected by MPU6050_DMP6 example Arduino sketch)
port.write('r');
}
#Override
public void draw() {
if (millis() - interval > 1000) {
// resend single character to trigger DMP init/start
// in case the MPU is halted/reset while applet is running
port.write('r');
interval = millis();
}
// black background
background(0);
// translate everything to the middle of the viewport
pushMatrix();
translate(width / 2, height / 2);
// 3-step rotation from yaw/pitch/roll angles (gimbal lock!)
// ...and other weirdness I haven't figured out yet
//rotateY(-ypr[0]);
//rotateZ(-ypr[1]);
//rotateX(-ypr[2]);
// toxiclibs direct angle/axis rotation from quaternion (NO gimbal lock!)
// (axis order [1, 3, 2] and inversion [-1, +1, +1] is a consequence of
// different coordinate system orientation assumptions between Processing
// and InvenSense DMP)
float[] axis = quat.toAxisAngle();
rotate(axis[0], -axis[1], axis[3], axis[2]);
// draw main body in red
fill(255, 0, 0, 200);
box(10, 10, 200);
// draw front-facing tip in blue
fill(0, 0, 255, 200);
pushMatrix();
translate(0, 0, -120);
rotateX(PI/2);
drawCylinder(0, 20, 20, 8);
popMatrix();
// draw wings and tail fin in green
fill(0, 255, 0, 200);
beginShape(TRIANGLES);
vertex(-100, 2, 30); vertex(0, 2, -80); vertex(100, 2, 30); // wing top layer
vertex(-100, -2, 30); vertex(0, -2, -80); vertex(100, -2, 30); // wing bottom layer
vertex(-2, 0, 98); vertex(-2, -30, 98); vertex(-2, 0, 70); // tail left layer
vertex( 2, 0, 98); vertex( 2, -30, 98); vertex( 2, 0, 70); // tail right layer
endShape();
beginShape(QUADS);
vertex(-100, 2, 30); vertex(-100, -2, 30); vertex( 0, -2, -80); vertex( 0, 2, -80);
vertex( 100, 2, 30); vertex( 100, -2, 30); vertex( 0, -2, -80); vertex( 0, 2, -80);
vertex(-100, 2, 30); vertex(-100, -2, 30); vertex(100, -2, 30); vertex(100, 2, 30);
vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, -30, 98); vertex(-2, -30, 98);
vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, 0, 70); vertex(-2, 0, 70);
vertex(-2, -30, 98); vertex(2, -30, 98); vertex(2, 0, 70); vertex(-2, 0, 70);
endShape();
popMatrix();
}
void serialEvent(Serial port) {
interval = millis();
while (port.available() > 0) {
int ch = port.read();
if (synced == 0 && ch != '$') return; // initial synchronization - also used to resync/realign if needed
synced = 1;
print ((char)ch);
if ((serialCount == 1 && ch != 2)
|| (serialCount == 12 && ch != '\r')
|| (serialCount == 13 && ch != '\n')) {
serialCount = 0;
synced = 0;
return;
}
if (serialCount > 0 || ch == '$') {
teapotPacket[serialCount++] = (char)ch;
if (serialCount == 14) {
serialCount = 0; // restart packet byte position
// get quaternion from data packet
q[0] = ((teapotPacket[2] << 8) | teapotPacket[3]) / 16384.0f;
q[1] = ((teapotPacket[4] << 8) | teapotPacket[5]) / 16384.0f;
q[2] = ((teapotPacket[6] << 8) | teapotPacket[7]) / 16384.0f;
q[3] = ((teapotPacket[8] << 8) | teapotPacket[9]) / 16384.0f;
for (int i = 0; i < 4; i++) if (q[i] >= 2) q[i] = -4 + q[i];
// set our toxilibs quaternion to new data
quat.set(q[0], q[1], q[2], q[3]);
/*
// below calculations unnecessary for orientation only using toxilibs
// calculate gravity vector
gravity[0] = 2 * (q[1]*q[3] - q[0]*q[2]);
gravity[1] = 2 * (q[0]*q[1] + q[2]*q[3]);
gravity[2] = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3];
// calculate Euler angles
euler[0] = atan2(2*q[1]*q[2] - 2*q[0]*q[3], 2*q[0]*q[0] + 2*q[1]*q[1] - 1);
euler[1] = -asin(2*q[1]*q[3] + 2*q[0]*q[2]);
euler[2] = atan2(2*q[2]*q[3] - 2*q[0]*q[1], 2*q[0]*q[0] + 2*q[3]*q[3] - 1);
// calculate yaw/pitch/roll angles
ypr[0] = atan2(2*q[1]*q[2] - 2*q[0]*q[3], 2*q[0]*q[0] + 2*q[1]*q[1] - 1);
ypr[1] = atan(gravity[0] / sqrt(gravity[1]*gravity[1] + gravity[2]*gravity[2]));
ypr[2] = atan(gravity[1] / sqrt(gravity[0]*gravity[0] + gravity[2]*gravity[2]));
// output various components for debugging
//println("q:\t" + round(q[0]*100.0f)/100.0f + "\t" + round(q[1]*100.0f)/100.0f + "\t" + round(q[2]*100.0f)/100.0f + "\t" + round(q[3]*100.0f)/100.0f);
//println("euler:\t" + euler[0]*180.0f/PI + "\t" + euler[1]*180.0f/PI + "\t" + euler[2]*180.0f/PI);
//println("ypr:\t" + ypr[0]*180.0f/PI + "\t" + ypr[1]*180.0f/PI + "\t" + ypr[2]*180.0f/PI);
*/
}
}
}
}
void drawCylinder(float topRadius, float bottomRadius, float tall, int sides) {
float angle = 0;
float angleIncrement = TWO_PI / sides;
beginShape(QUAD_STRIP);
for (int i = 0; i < sides + 1; ++i) {
vertex(topRadius*cos(angle), 0, topRadius*sin(angle));
vertex(bottomRadius*cos(angle), tall, bottomRadius*sin(angle));
angle += angleIncrement;
}
endShape();
// If it is not a cone, draw the circular top cap
if (topRadius != 0) {
angle = 0;
beginShape(TRIANGLE_FAN);
// Center point
vertex(0, 0, 0);
for (int i = 0; i < sides + 1; i++) {
vertex(topRadius * cos(angle), 0, topRadius * sin(angle));
angle += angleIncrement;
}
endShape();
}
// If it is not a cone, draw the circular bottom cap
if (bottomRadius != 0) {
angle = 0;
beginShape(TRIANGLE_FAN);
// Center point
vertex(0, tall, 0);
for (int i = 0; i < sides + 1; i++) {
vertex(bottomRadius * cos(angle), tall, bottomRadius * sin(angle));
angle += angleIncrement;
}
endShape();
}
}
public static void main(String[] args) {
PApplet.main(new String[] { "--present", "MyProcessingSketch" });
}
}
`
MyFrame.java
package testprocessing;
import javax.swing.JFrame;
public class MyFrame extends JFrame{
private MyProcessingSketch mysketch;
public MyFrame() {
setTitle("IMU");
setDefaultCloseOperation(EXIT_ON_CLOSE);
mysketch = new MyProcessingSketch();
mysketch.init();
add(mysketch);
}
public static void main(String[] args) {
MyFrame frame = new MyFrame();
frame.pack();
frame.setVisible(true);
}
}

Related

How to write text or put image on top of 3D cube in OpenGL java in android (Object is used in Augmenting Purpose)

I'm developing an Augmented Reality based application using EasyAR SDK in android. It rendering cube on the top of image target by default. I want to print something on the top of that cube. So what should I do? I'm new to OpenGL, please help.
If I can put an image on top of that cube then it's also fine! I just want to display "Loading" on that cube, whether it is image or text, that doesn't really matter!
This is the current situation:
And I need something like this:
Here is my code that renders box on top of image target.
import android.opengl.GLES20;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import cn.easyar.Vec2F;
import cn.easyar.Matrix44F;
public class BoxRenderer {
private int program_box;
private int pos_coord_box;
private int pos_color_box;
private int pos_trans_box;
private int pos_proj_box;
private int vbo_coord_box;
private int vbo_color_box;
private int vbo_color_box_2;
private int vbo_faces_box;
private String box_vert = "uniform mat4 trans;\n"
+ "uniform mat4 proj;\n"
+ "attribute vec4 coord;\n"
+ "attribute vec4 color;\n"
+ "varying vec4 vcolor;\n"
+ "\n"
+ "void main(void)\n"
+ "{\n"
+ " vcolor = color;\n"
+ " gl_Position = proj*trans*coord;\n"
+ "}\n"
+ "\n";
private String box_frag = "#ifdef GL_ES\n"
+ "precision highp float;\n"
+ "#endif\n"
+ "varying vec4 vcolor;\n"
+ "\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_FragColor = vcolor;\n"
+ "}\n"
+ "\n";
private float[] flatten(float[][] a) {
int size = 0;
for (int k = 0; k < a.length; k += 1) {
size += a[k].length;
}
float[] l = new float[size];
int offset = 0;
for (int k = 0; k < a.length; k += 1) {
System.arraycopy(a[k], 0, l, offset, a[k].length);
offset += a[k].length;
}
return l;
}
private int[] flatten(int[][] a) {
int size = 0;
for (int k = 0; k < a.length; k += 1) {
size += a[k].length;
}
int[] l = new int[size];
int offset = 0;
for (int k = 0; k < a.length; k += 1) {
System.arraycopy(a[k], 0, l, offset, a[k].length);
offset += a[k].length;
}
return l;
}
private short[] flatten(short[][] a) {
int size = 0;
for (int k = 0; k < a.length; k += 1) {
size += a[k].length;
}
short[] l = new short[size];
int offset = 0;
for (int k = 0; k < a.length; k += 1) {
System.arraycopy(a[k], 0, l, offset, a[k].length);
offset += a[k].length;
}
return l;
}
private byte[] flatten(byte[][] a) {
int size = 0;
for (int k = 0; k < a.length; k += 1) {
size += a[k].length;
}
byte[] l = new byte[size];
int offset = 0;
for (int k = 0; k < a.length; k += 1) {
System.arraycopy(a[k], 0, l, offset, a[k].length);
offset += a[k].length;
}
return l;
}
private byte[] byteArrayFromIntArray(int[] a) {
byte[] l = new byte[a.length];
for (int k = 0; k < a.length; k += 1) {
l[k] = (byte) (a[k] & 0xFF);
}
return l;
}
private int generateOneBuffer() {
int[] buffer = {0};
GLES20.glGenBuffers(1, buffer, 0);
return buffer[0];
}
public void init() {
program_box = GLES20.glCreateProgram();
int vertShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
GLES20.glShaderSource(vertShader, box_vert);
GLES20.glCompileShader(vertShader);
int fragShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
GLES20.glShaderSource(fragShader, box_frag);
GLES20.glCompileShader(fragShader);
GLES20.glAttachShader(program_box, vertShader);
GLES20.glAttachShader(program_box, fragShader);
GLES20.glLinkProgram(program_box);
GLES20.glUseProgram(program_box);
pos_coord_box = GLES20.glGetAttribLocation(program_box, "coord");
pos_color_box = GLES20.glGetAttribLocation(program_box, "color");
pos_trans_box = GLES20.glGetUniformLocation(program_box, "trans");
pos_proj_box = GLES20.glGetUniformLocation(program_box, "proj");
vbo_coord_box = generateOneBuffer();
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo_coord_box);
float cube_vertices[][] = {
/* +z */{1.0f / 2, 1.0f / 2, 0.01f / 2}, {1.0f / 2, -1.0f / 2, 0.01f / 2}, {-1.0f / 2, -1.0f / 2, 0.01f / 2}, {-1.0f / 2, 1.0f / 2, 0.01f / 2},
/* -z */{1.0f / 2, 1.0f / 2, -0.01f / 2}, {1.0f / 2, -1.0f / 2, -0.01f / 2}, {-1.0f / 2, -1.0f / 2, -0.01f / 2}, {-1.0f / 2, 1.0f / 2, -0.01f / 2}
};
FloatBuffer cube_vertices_buffer = FloatBuffer.wrap(flatten(cube_vertices));
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cube_vertices_buffer.limit() * 4, cube_vertices_buffer, GLES20.GL_DYNAMIC_DRAW);
vbo_color_box = generateOneBuffer();
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo_color_box);
int cube_vertex_colors[][] = {
{255, 0, 0, 128}, {0, 255, 0, 128}, {0, 0, 255, 128}, {0, 0, 0, 128},
{0, 255, 255, 128}, {255, 0, 255, 128}, {255, 255, 0, 128}, {255, 255, 255, 128}};
ByteBuffer cube_vertex_colors_buffer = ByteBuffer.wrap(byteArrayFromIntArray(flatten(cube_vertex_colors)));
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cube_vertex_colors_buffer.limit(), cube_vertex_colors_buffer, GLES20.GL_STATIC_DRAW);
vbo_color_box_2 = generateOneBuffer();
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo_color_box_2);
int cube_vertex_colors_2[][] = {
{255, 0, 0, 255}, {255, 255, 0, 255}, {0, 255, 0, 255}, {255, 0, 255, 255},
{255, 0, 255, 255}, {255, 255, 255, 255}, {0, 255, 255, 255}, {255, 0, 255, 255}};
ByteBuffer cube_vertex_colors_2_buffer = ByteBuffer.wrap(byteArrayFromIntArray(flatten(cube_vertex_colors_2)));
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cube_vertex_colors_2_buffer.limit(), cube_vertex_colors_2_buffer, GLES20.GL_STATIC_DRAW);
vbo_faces_box = generateOneBuffer();
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, vbo_faces_box);
short cube_faces[][] = {
/* +z */{3, 2, 1, 0}, /* -y */{2, 3, 7, 6}, /* +y */{0, 1, 5, 4},
/* -x */{3, 0, 4, 7}, /* +x */{1, 2, 6, 5}, /* -z */{4, 5, 6, 7}};
ShortBuffer cube_faces_buffer = ShortBuffer.wrap(flatten(cube_faces));
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, cube_faces_buffer.limit() * 2, cube_faces_buffer, GLES20.GL_STATIC_DRAW);
}
public void render(Matrix44F projectionMatrix, Matrix44F cameraview, Vec2F size) {
float size0 = size.data[0];
float size1 = size.data[1];
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo_coord_box);
float height = size0 / 1000;
float cube_vertices[][] = {
/* +z */{size0 / 2, size1 / 2, height / 2}, {size0 / 2, -size1 / 2, height / 2}, {-size0 / 2, -size1 / 2, height / 2}, {-size0 / 2, size1 / 2, height / 2},
/* -z */{size0 / 2, size1 / 2, 0}, {size0 / 2, -size1 / 2, 0}, {-size0 / 2, -size1 / 2, 0}, {-size0 / 2, size1 / 2, 0}};
FloatBuffer cube_vertices_buffer = FloatBuffer.wrap(flatten(cube_vertices));
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cube_vertices_buffer.limit() * 4, cube_vertices_buffer, GLES20.GL_DYNAMIC_DRAW);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glUseProgram(program_box);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo_coord_box);
GLES20.glEnableVertexAttribArray(pos_coord_box);
GLES20.glVertexAttribPointer(pos_coord_box, 3, GLES20.GL_FLOAT, false, 0, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo_color_box);
GLES20.glEnableVertexAttribArray(pos_color_box);
GLES20.glVertexAttribPointer(pos_color_box, 4, GLES20.GL_UNSIGNED_BYTE, true, 0, 0);
GLES20.glUniformMatrix4fv(pos_trans_box, 1, false, cameraview.data, 0);
GLES20.glUniformMatrix4fv(pos_proj_box, 1, false, projectionMatrix.data, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, vbo_faces_box);
for (int i = 0; i < 6; i++) {
GLES20.glDrawElements(GLES20.GL_TRIANGLE_FAN, 4, GLES20.GL_UNSIGNED_SHORT, i * 4 * 2);
}
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo_coord_box);
float cube_vertices_2[][] = {
/* +z */{size0 / 4, size1 / 4, size0 / 4}, {size0 / 4, -size1 / 4, size0 / 4}, {-size0 / 4, -size1 / 4, size0 / 4}, {-size0 / 4, size1 / 4, size0 / 4},
/* -z */{size0 / 4, size1 / 4, 0}, {size0 / 4, -size1 / 4, 0}, {-size0 / 4, -size1 / 4, 0}, {-size0 / 4, size1 / 4, 0}};
FloatBuffer cube_vertices_2_buffer = FloatBuffer.wrap(flatten(cube_vertices_2));
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cube_vertices_2_buffer.limit() * 4, cube_vertices_2_buffer, GLES20.GL_DYNAMIC_DRAW);
GLES20.glEnableVertexAttribArray(pos_coord_box);
GLES20.glVertexAttribPointer(pos_coord_box, 3, GLES20.GL_FLOAT, false, 0, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo_color_box_2);
GLES20.glEnableVertexAttribArray(pos_color_box);
GLES20.glVertexAttribPointer(pos_color_box, 4, GLES20.GL_UNSIGNED_BYTE, true, 0, 0);
for (int i = 0; i < 6; i++) {
GLES20.glDrawElements(GLES20.GL_TRIANGLE_FAN, 4, GLES20.GL_UNSIGNED_SHORT, i * 4 * 2);
}
}
}
This one might be a bit much but it is rather simple and flexible because you can pretty much use any kind of text or font or even background.
Basically we draw text on a bitmap and render this bitmap on a 2D plane. The background of the bitmap won't be rendered (using discard in the fragment shader) as long as it is a predefined color.
So first we need to setup one additional vertex attribute for texture coordinates. Here is the complete setup including vertices and texture coordinates for a simple 2D-plane:
//the geometry with texture coordinates
public int vbs[] = new int[2];
public void initSprite(){
float vertices[] = {
1.0f, -1.0f, 0.0f, //triangle 1
-1.0f, -1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, //triangle 2
1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f
};
float texcoords[] = {
1.0f, 1.0f, 0.0f, //triangle 1
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, //triangle 2
1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f
};
int triangle_count = 2;
FloatBuffer vertex_pos_buffer;
FloatBuffer tex_coord_buffer;
int bytes_per_float = 4;
//generate buffers on gpu
GLES20.glGenBuffers(2, vbs,0);
// Allocate a direct block of memory on the native heap,
// size in bytes is equal to vertices.length * BYTES_PER_FLOAT.
// BYTES_PER_FLOAT is equal to 4, since a float is 32-bits, or 4 bytes.
vertex_pos_buffer = ByteBuffer.allocateDirect(vertices.length * bytes_per_float)
// Floats can be in big-endian or little-endian order.
// We want the same as the native platform.
.order(ByteOrder.nativeOrder())
// Give us a floating-point view on this byte buffer.
.asFloatBuffer();
//Transferring data from the Java heap to the native heap is then a matter of a couple calls:
// Copy data from the Java heap to the native heap.
vertex_pos_buffer.put(vertices)
// Reset the buffer position to the beginning of the buffer.
.position(0);
//Bind the vertices buffer and give OpenGL the data
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbs[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, triangle_count * 3* 3 * bytes_per_float, vertex_pos_buffer, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
tex_coord_buffer = ByteBuffer.allocateDirect(texcoords.length * bytes_per_float)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
tex_coord_buffer.put(texcoords).position(0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbs[1]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, triangle_count * 3* 3 * bytes_per_float, tex_coord_buffer, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
}
Next we need our Texture. We load a background image and draw our desired text ontop of it. size is the font size we want to use and should be a bit smaller than the background bitmap height. r g b are the color values of the font:
//the texture we gonna use during rendering
int tex = 0;
public void initTextTexture(String backgroundBitmapPath, String text, float size, int r, int g, int b){
//load the bitmap
Bitmap background = loadBitmapRGBA(backgroundBitmapPath);
//check if image could load
if(background == null){
return;
}
android.graphics.Bitmap.Config bitmapConfig = background.getConfig();
// set default bitmap config if none
if(bitmapConfig == null) {
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
// resource bitmaps are imutable,
// so we need to convert it to mutable one
background = background.copy(bitmapConfig, true);
Canvas canvas = new Canvas(background);
// new antialised Paint
Paint paint = new Paint();
paint.setColor(Color.rgb(r, g, b));
// text size in pixels
paint.setTextSize(size);
// draw text to the Canvas center
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
//left
int x = 1;
//center
int y = (background.getHeight() + bounds.height())/2;
canvas.drawText(text, x, y, paint);
//create a texture with the bitmap we just created
//try to allocate texture on GPU
int gl_map[] = new int[1];
GLES20.glGenTextures(1, gl_map, 0);
tex = gl_map[0];
//bind texture
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex);
//move the bitmap to the openGL texture
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, background, 0);
//set nearest filter
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
}
private Bitmap loadBitmapRGBA(String path){
if(path == null){
return null;
}
//replace this with your application/activity context
AssetManager assetManager = GlobalContext.getAppContext().getAssets();
InputStream istr = null;
try {
istr = assetManager.open(path);
} catch (IOException e) {
e.printStackTrace();
}
Rect outPadding = new Rect();
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap image = BitmapFactory.decodeStream(istr, outPadding, options);
return image;
}
Next we need draw our geometry with the texture we created, notice the glBindTexture :
public void drawTextSprite(){
//program is the shader programm we gonna use to draw the 2d plane
GLES20.glUseProgram(program);
int locPosition = GLES20.glGetAttribLocation(program, "a_Position");
int locTexcoord = GLES20.glGetAttribLocation(program, "a_TexCoord");
int locTexture = GLES20.glGetUniformLocation(program, "tex_sampler");
int locMVPMatrix = GLES20.glGetUniformLocation(program, "u_MVPMatrix");
//bind the vertex data
GLES20.glEnableVertexAttribArray(locPosition);
GLES20.glEnableVertexAttribArray(locTexcoord);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbs[0]);
GLES20.glVertexAttribPointer(locPosition, 3, GLES20.GL_FLOAT, false, 0, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbs[1]);
GLES20.glVertexAttribPointer(locTexcoord, 3, GLES20.GL_FLOAT, false, 0, 0);
//bind texture
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex);
// Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
GLES20.glUniform1i(locTexture, 0);
//set up the mvp matrix
float mvp[] = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
GLES20.glUniformMatrix4fv(locMVPMatrix, 1, false, mvp, 0);
//draw 2 triangles
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 2*3);
}
Now we just need our shader:
//vertex shader
uniform lowp mat4 u_MVPMatrix;
attribute lowp vec4 a_Position;
attribute lowp vec3 a_TexCoord;
varying lowp vec3 texc;
void main()
{
texc = a_TexCoord;
gl_Position = u_MVPMatrix * a_Position;
}
//fragment shader
uniform lowp sampler2D tex_sampler;
varying lowp vec3 texc;
void main()
{
lowp vec3 color = texture2D(tex_sampler, texc.st).rgb;
//test for the background color
if(color.r == 1.0 && color.g == 0.0 && color.b == 1.0){
discard; //get rid of the background
}
gl_FragColor = vec4(color.r, color.g, color.b, 1.0);
}
And to set everything up we call the following two lines:
initSprite();
initTextTexture("img/FF00FF_TEXT_BG.png","Loading...", 20.0f, 255, 255, 255);
FF00FF_TEXT_BG is stored under assets/img/ and looks like this.
If we call drawTextSprite(); during the renderloop we should get something like this:
Of course the output is a bit stretched, this is because i used the identity matrix to draw it. You just need to make sure you draw this over your box by providing the proper matrix.
Also make sure not to draw the plane directly at the same position as the box's side but slightly further way, otherwise you wont see the text or artefacts if you use depthtest.
If you don't need to generate strings during runtime you can ofcourse just load bitmaps with prerendered text.
Hope that helps.

Nested if statement within for loop [JAVA/LibGDX]

So I got my code to work this more of a question in regards to Java and why it worked the way I got it VS. why it didn't work the first way I wrote it. This is the original code I wrote.
private void renderGUIExtraLives (SpriteBatch batch){
float x = GUIcamera.viewportWidth - 50 - Constants.LIVES_START * 50;
float y = -15;
for (int i = 0; i < Constants.LIVES_START; i++) {
if (worldController.lives <= i) {
batch.setColor(0.5f, 0.5f, 0.5f, 0.5f);
batch.draw(Assets.instance.bunny.head, x + i * 50, y, 50, 50, 120, 100, 0.35f, -0.35f, 0);
batch.setColor(1, 1, 1, 1);
}
}
}
This didn't work, it threw no errors, but it did not draw the lives to the screen, all I did was remove the curly braces of the if statement like so:
private void renderGUIExtraLives (SpriteBatch batch){
float x = GUIcamera.viewportWidth - 50 - Constants.LIVES_START * 50;
float y = -15;
for (int i = 0; i < Constants.LIVES_START; i++) {
if (worldController.lives <= i)
batch.setColor(0.5f, 0.5f, 0.5f, 0.5f);
batch.draw(Assets.instance.bunny.head, x + i * 50, y, 50, 50, 120, 100, 0.35f, -0.35f, 0);
batch.setColor(1, 1, 1, 1);
}
}
And now magically it worked, can some explain why it worked after I removed the curly braces from the nested if statement? I would really appreciate it, as well as any discussion regarding this topic would be great to read if someone has a link to a similar question or answer here on Stack.
Your indentation is wrong and misleading. If you remove the braces after the if only the next statement is conditionally executed. That means the code basically is:
for (int i = 0; i < Constants.LIVES_START; i++) {
if (worldController.lives <= i)
batch.setColor(0.5f, 0.5f, 0.5f, 0.5f);
batch.draw(Assets.instance.bunny.head, x + i * 50, y, 50, 50, 120, 100, 0.35f, -0.35f, 0);
batch.setColor(1, 1, 1, 1);
}
Should be clear why it "magically works" now, it just draws unconditionally.

Game grid not outputting in Android Studios?

I am currently making an android app which plays the puzzle game hashi. I am currently struggling to output the game grid. i want to output a 2d array like bellow-
1 0 0 0 1
0 2 0 0 2
2 0 3 0 1
0 0 0 0 0
0 0 2 0 2
however when i run the application in the emulator it outputs just a blank white screen.
main activity-
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new boardView(this));
//sets the view to the board view to show the puzzle on open.
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
game board class-
public class boardView extends View {
public float IslandX;
public float IslandY;
public int islandDiameter;
private Canvas canvas;
public boardView(Context context) {
super(context);
}
int gameBoard[][] = {{0, 1, 0, 0, 1}, {0, 2, 0, 0, 2}, {2, 0, 3, 0, 1}, {0, 0, 0, 0, 0}, {0, 0, 2, 0, 2}};
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void DrawBoard(Canvas canvas){
Paint Island = new Paint();
Island.setStyle(Paint.Style.FILL);
Island.setStyle(Paint.Style.FILL);
float stepX = canvas.getWidth() / 5.f;
float stepY = canvas.getHeight() / 5.f;
for (int i = 0; i < 5; i++) {
for (int R = 0; R < 5; R++) {
IslandX = i * stepX;
IslandY = R * stepY;
if (gameBoard[i][R] == 0) {
Island.setColor(Color.BLUE);
canvas.drawOval(IslandX, IslandY, 50, 50, Island);
} else if (gameBoard[i][R] == 1) {
Island.setColor(Color.BLACK);
canvas.drawOval(IslandX, IslandY, 50, 50, Island);
} else if (gameBoard[i][R] == 2) {
Island.setColor(Color.BLUE);
canvas.drawOval(IslandX, IslandY, 50, 50, Island);
}
}
}
}
}
To make your board visible, you have to move your code from Drawboard to the overwritten method onDraw and in the onCreate method, you have to call invalidate() on an instance of the class boardView, that calls the onDraw method to update the screen, if visible.

School Project, Array Index Out of Bounds Exception: 2

I'm currently working on a project for school and am following a video tutorial, I'm pretty new to coding. From what I can tell everything looks right but when I run the preview it sends me a blank window with the error "ArrayIndexOutOfBoundsException:2"
PShape baseMap;
String csv[];
String myData[][];
//Setup BaseMap and csv info
void setup() {
size(1800, 900);
noLoop();
baseMap = loadShape("WorldMap.svg");
csv = loadStrings("FlightCancellations.csv");
myData = new String[csv.length][4];
for(int i=0; i<csv.length; i++) {
myData[i] = csv[i].split(",");
}
}
//draw
void draw() {
shape(baseMap, 0, 0, width, height);
noStroke();
fill(255, 0, 0, 50);
for(int i=0; i<myData.length; i++){
float graphLong = map(float(myData[i][2]), -180, 180, 0, width);
float graphLat = map(float(myData[i][3]), -90, 90, 0, height);
println(graphLong + " / " + graphLat);
ellipse(graphLong, graphLat, 10, 10);
}
}
Also, the mapped image works fine until I add
for(int i=0; i<myData.length; i++){
float graphLong = map(float(myData[i][2]), -180, 180, 0, width);
float graphLat = map(float(myData[i][3]), -90, 90, 0, height);
println(graphLong + " / " + graphLat);
You should get in the habit of checking that data exists before you use it in your program:
for(int i=0; i<myData.length; i++) {
if (myData[i].length > 3) { // Check that the array has at least 4 entries
float graphLong = map(float(myData[i][2]), -180, 180, 0, width);
float graphLat = map(float(myData[i][3]), -90, 90, 0, height);
println(graphLong + " / " + graphLat);
ellipse(graphLong, graphLat, 10, 10);
}
}

Difficulty with Text in JOGL

I'm trying to display text in my OpenGL / JOGL app. Here is some of the code:
private void display(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
GLUgl2 glu = new GLUgl2();
float[] rgba = new float[4];
backgroundColor.getRGBComponents(rgba);
gl.glClearColor(rgba[0], rgba[1], rgba[2], 1);
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
// Position the camera
glu.gluLookAt(cameraPos.x, cameraPos.y, cameraPos.z, cameraPos.x + cameraForward.x, cameraPos.y + cameraForward.y,
cameraPos.z + cameraForward.z, cameraUp.x, cameraUp.y, cameraUp.z);
gl.glPushMatrix();
GLUT glut = new GLUT();
gl.glTranslatef(0, 0, 0);
gl.glColor3f(1, 0, 0);
glut.glutBitmapString(GLUT.BITMAP_HELVETICA_18, "We're going to the moon!");
gl.glPopMatrix();
// ...
The text appears as soon as rendering begins, then runs off the right hand side of the screen. Why is this happening?
I'd like to display text in front of the user, not as a model in the world.
You need to set the current raster position before invoking glutBitmapString. The raster position is the pixel where the string will start being drawn. You can set it using the glRasterPos... family of functions. The reason your text seems to "run off" the right side of the screen is that calling glutBitmapString implicitly moves the raster position to the end of the string (see here).
There is very easy solution but it "links" your app against awt, which might be bad if you try to stay out of it in favour of newt.
Below example draws player osd using number of text renderers: one for play/pause glyph, one more for some information like time, etc., and yet another one for movie name.
import com.jogamp.opengl.util.awt.TextRenderer;
private static final Color DROP_SHADOW_COLOR = new Color(0, 0, 0, 0.5f);
class CustomRenderDelegate implements TextRenderer.RenderDelegate {
private int dropShadowDepth;
private Color color;
CustomRenderDelegate(int dropShadowDepth, Color color) {
this.dropShadowDepth = dropShadowDepth;
this.color = color;
}
public boolean intensityOnly() {
return false;
}
public Rectangle2D getBounds(CharSequence str, Font font, FontRenderContext frc) {
return getBounds(str.toString(), font, frc);
}
public Rectangle2D getBounds(String str, Font font, FontRenderContext frc) {
return getBounds(font.createGlyphVector(frc, str), frc);
}
public Rectangle2D getBounds(GlyphVector gv, FontRenderContext frc) {
Rectangle2D stringBounds = gv.getPixelBounds(frc, 0, 0);
return new Rectangle2D.Double(stringBounds.getX(), stringBounds.getY(), stringBounds.getWidth()
+ dropShadowDepth, stringBounds.getHeight() + dropShadowDepth);
}
public void drawGlyphVector(Graphics2D graphics, GlyphVector str, int x, int y) {
graphics.setColor(DROP_SHADOW_COLOR);
graphics.drawGlyphVector(str, x + dropShadowDepth, y + dropShadowDepth);
graphics.setColor(color);
graphics.drawGlyphVector(str, x, y);
}
public void draw(Graphics2D graphics, String str, int x, int y) {
graphics.setColor(DROP_SHADOW_COLOR);
graphics.drawString(str, x + dropShadowDepth, y + dropShadowDepth);
graphics.setColor(color);
graphics.drawString(str, x, y);
}
}
public void init(GLAutoDrawable drawable) {
...
pathRenderer = new TextRenderer(new Font("Helvetica", Font.ITALIC, 16), true, true, new CustomRenderDelegate(0,
Color.WHITE));
pathRenderer.setSmoothing(true);
playRenderer = new TextRenderer(new Font("Helvetica", Font.BOLD, 65), true, true, new CustomRenderDelegate(0,
Color.WHITE));
pauseRenderer = new TextRenderer(new Font("Helvetica", Font.BOLD, 50), true, true, new CustomRenderDelegate(0,
Color.WHITE));
osdRenderer = new TextRenderer(new Font("Helvetica", Font.PLAIN, 32), true, true, new CustomRenderDelegate(0,
Color.WHITE));
osdRenderer.setSmoothing(true);
}
private final void updateOsd() {
Time t = currentFrame != null ? currentFrame.getTime() : new Time(0, 0, 0, 0, 0);
String direction = video.direction == DirectionType.DIRECTION_LEFT ? "<" : ">";
String frameNumber = enterFrameNumber != null ? String.format("[%s]", enterFrameNumber)
: String.format("(%d)", t.fn);
osdText = String.format(" %s%s x %d # %.2f fps < %d/%d (%s) # %d fps", TimeUtil.hmsms(t.getPtsMillis()), frameNumber, (int) video.getPlaybackRate(), playbackFps, video.readyFrames(), maxFrames, direction, video.getFilterFps());
}
private void renderOsd(GLAutoDrawable drawable) {
updateOsd();
if (isOsdEnabled) {
maxModeWidth = (int) Math.max(maxModeWidth, playRenderer.getBounds("\u25B8").getWidth());
maxOsdHeight = (int) Math.max(maxOsdHeight, playRenderer.getBounds("\u25B8").getHeight());
if (isPaused) {
pauseRenderer.beginRendering(drawable.getWidth(), drawable.getHeight());
pauseRenderer.draw("\u2759", 10, drawable.getHeight() - maxOsdHeight - 2);
int barWidth = (int) pauseRenderer.getBounds("\u2759").getWidth();
pauseRenderer.draw("\u2759", 10 + barWidth - 3, drawable.getHeight() - maxOsdHeight - 2);
pauseRenderer.flush();
pauseRenderer.endRendering();
} else {
playRenderer.beginRendering(drawable.getWidth(), drawable.getHeight());
playRenderer.draw("\u25B8", 10, drawable.getHeight() - maxOsdHeight - 5);
playRenderer.flush();
playRenderer.endRendering();
}
int y = (int) ((maxOsdHeight + 10) - osdRenderer.getBounds(osdText).getHeight() / 2);
osdRenderer.beginRendering(drawable.getWidth(), drawable.getHeight());
osdRenderer.draw(osdText, maxModeWidth + 18, drawable.getHeight() - y - 2);
osdRenderer.flush();
osdRenderer.endRendering();
if (isFullScreen) {
pathRenderer.beginRendering(drawable.getWidth(), drawable.getHeight());
pathRenderer.draw(videoFile.getName(), 18, drawable.getHeight() - y - maxOsdHeight + 15);
pathRenderer.flush();
pathRenderer.endRendering();
}
}
}
public void display(GLAutoDrawable drawable) {
GL gl = drawable.getGL();
gl.glClear(GL.GL_COLOR_BUFFER_BIT);
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
renderFrame(drawable);
renderOsd(drawable);
gl.glFinish();
}

Categories