Loading...
Processing Forum
Recent Topics
All Forums
Screen name:
arrmin
arrmin's Profile
2
Posts
6
Responses
0
Followers
Activity Trend
Last 30 days
Last 30 days
Date Interval
From Date :
To Date :
Go
Loading Chart...
Posts
Responses
PM
Show:
All
Discussions
Questions
Expanded view
List view
Private Message
Rotating voxels in toxiclibs' VolumetricSpace using Quaternions?
[0 Replies]
22-Apr-2012 11:18 AM
Forum:
Contributed Library Questions
Ok, I drew stuff in a VolumetricSpace using this blue-illuminated table tennis ball.
It looks very 2d at the beginning but just take a look at the end of the video, where I rotate it:
https://vimeo.com/40036315
Ok, I rotate it. (the following is not in the video)
The problem:
Sure enough, the coordinate system of the VolumetricSpace got rotated too.
So when I draw now, my tabletennis ball and the newly drawn line won't be congruent(wont overlap) any more.
I thought if I still want them to be congruent, the VolumetricSpace shouldn't be rotated. - only the voxels inside of it should be rotated.
So I experimented with quaternions
http://stackoverflow.com/questions/9843298/java-quaternion-3d-rotation-implementation
It didn't work out that well after a few hours.
I also saw there's a quaternion toxiclibs class, but I couldn't figure out how to use it for this task.
I also thought maybe I could use proscene to accomplish this task, but I don't exactly know how I would do that yet.
Could someone give me some advice?
Here is what I worked out so far for rotation of voxels in a VolumetricSpace:
You can press 'r' to invoke this function call:
rotation3D(points, Math.toRadians(10), 1, 0, 0);
It rotates the voxels 10 degrees around the x-axis.
I couldn't figure out how to rotate the cube in the example around it's own center. Furthermore, the voxel's positions get kind of messy.
import java.util.ArrayList;
import processing.core.*;
import processing.opengl.*;
import javax.media.opengl.GL;
import toxi.geom.*;
import toxi.geom.mesh.*;
import toxi.volume.*;
public class Test extends PApplet {
public static void main(String[] args) {
PApplet.main(new String[] { "--present", "Test" });
}
ArrayList<Integer> points = new ArrayList<Integer>();
int DIMX = 48;
int DIMY = 48;
int DIMZ = 48;
float ISO_THRESHOLD = 0.1f;
float NS = 0.03f;
Vec3D SCALE = new Vec3D(1, 1, 1).scaleSelf(300);
float currScale = 1;
VolumetricSpace volume = new VolumetricSpaceArray(SCALE, DIMX, DIMY, DIMZ);
VolumetricSpace newVolume = new VolumetricSpaceArray(SCALE, DIMX, DIMY, DIMZ);
TriangleMesh mesh;
PGraphicsOpenGL pgl;
GL gl;
// used to store mesh on GPU
VBO vbo;
public void rotation3D(ArrayList<Integer> points, double angle, int x,
int y, int z) {
// ArrayList<Integer> newpoints = points;
for (int i = 0; i < points.size(); i += 3) {
int x_old = points.get(i).intValue();
int y_old = points.get(i + 1).intValue();
int z_old = points.get(i + 2).intValue();
double[] initial = { 1, 0, 0, 0 };
double[] total = new double[4];
double[] local = new double[4];
// components for local quaternion
// w
local[0] = Math.cos(0.5 * angle);
// x
local[1] = x * Math.sin(0.5 * angle);
// y
local[2] = y * Math.sin(0.5 * angle);
// z
local[3] = z * Math.sin(0.5 * angle);
// local = magnitude(local);
// components for final quaternion Q1*Q2
// w = w1w2 - x1x2 - y1y2 - z1z2
total[0] = local[0] * initial[0] - local[1] * initial[1] - local[2]
* initial[2] - local[3] * initial[3];
// x = w1x2 + x1w2 + y1z2 - z1y2
total[1] = local[0] * initial[1] + local[1] * initial[0] + local[2]
* initial[3] - local[3] * initial[2];
// y = w1y2 - x1z2 + y1w2 + z1x2
total[2] = local[0] * initial[2] - local[1] * initial[3] + local[2]
* initial[0] + local[3] * initial[1];
// z = w1z2 + x1y2 - y1x2 + z1w2
total[3] = local[0] * initial[3] + local[1] * initial[2] - local[2]
* initial[1] + local[3] * initial[0];
// new x,y,z of the 3d point using rotation matrix made from the
// final quaternion
int x_new = (int) ((1 - 2 * total[2] * total[2] - 2 * total[3]
* total[3])
* x_old
+ (2 * total[1] * total[2] - 2 * total[0] * total[3])
* y_old + (2 * total[1] * total[3] + 2 * total[0]
* total[2])
* z_old);
int y_new = (int) ((2 * total[1] * total[2] + 2 * total[0]
* total[3])
* x_old
+ (1 - 2 * total[1] * total[1] - 2 * total[3] * total[3])
* y_old + (2 * total[2] * total[3] + 2 * total[0]
* total[1])
* z_old);
int z_new = (int) ((2 * total[1] * total[3] - 2 * total[0]
* total[2])
* x_old
+ (2 * total[2] * total[3] - 2 * total[0] * total[1])
* y_old + (1 - 2 * total[1] * total[1] - 2 * total[2]
* total[2])
* z_old);
points.set(i, x_new);
points.set(i + 1, y_new);
points.set(i + 2, z_new);
}
}
public void setup() {
size(1024, 768, OPENGL);
// fill volume
for (int z = 0; z < DIMZ; z++) {
for (int y = 0; y < DIMY; y++) {
for (int x = 0; x < DIMX; x++) {
//fill volume with a box
if(x<24+10 && y<24+10 && z<24+10 && x>24-10 && y>24-10 && z>24-10){
volume.setVoxelAt(x, y, z, 1);
}
points.add(x);
points.add(y);
points.add(z);
}
}
}
prepareVolume(volume);
}
public void prepareVolume(VolumetricSpace vol){
vol.closeSides();
// store in IsoSurface and compute surface mesh for the given threshold
// value
mesh = new TriangleMesh("iso");
IsoSurface surface = new HashIsoSurface(vol, 0.333333f);
surface.computeSurfaceMesh(mesh, ISO_THRESHOLD);
// get opengl related references
pgl = (PGraphicsOpenGL) g;
gl = pgl.gl;
// update lighting information
mesh.computeVertexNormals();
// get flattened vertex array
float[] verts = mesh.getMeshAsVertexArray();
// in the array each vertex has 4 entries (XYZ + 1 spacing)
int numV = verts.length / 4;
// create a VBO instance and set buffers from mesh
vbo = new VBO(gl, numV);
vbo.updateVertices(verts);
vbo.updateNormals(mesh.getVertexNormalsAsArray());
int[] normals = new int[mesh.getVertexNormalsAsArray().length];
for (int i = 0; i < normals.length; i++) {
print(normals[i]);
}
}
public void draw() {
background(128);
translate(width / 2, height / 2, 0);
scale(currScale);
// need to switch to pure OpenGL mode first
pgl.beginGL();
glLights();
// render mesh as triangle soup
vbo.render(GL.GL_TRIANGLES);
// back to processing
pgl.endGL();
}
// setup some lights/material for OpenGL
void glLights() {
gl.glEnable(GL.GL_LIGHTING);
gl.glEnable(GL.GL_LIGHT0);
gl.glEnable(GL.GL_COLOR_MATERIAL);
gl.glEnable(GL.GL_BLEND);
gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE);
gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT, new float[] {
-1.0f, -1.0f, 1.0f, 0.5f }, 0);
}
public void rotate() {
rotation3D(points, Math.toRadians(10), 1, 0, 0);
newVolume.clear();
int i = 0;
for (int z = 0; z < DIMZ; z++) {
for (int y = 0; y < DIMY; y++) {
for (int x = 0; x < DIMX; x++) {
//
int xp = Math.abs(points.get(i).intValue());
//
int yp = Math.abs(points.get(i + 1).intValue());
//
int zp = Math.abs(points.get(i + 2).intValue());
int xp = points.get(i).intValue();
int yp = points.get(i + 1).intValue();
int zp = points.get(i + 2).intValue();
i+=3;
/*println("x "+xp);
println("y "+yp);
println("z "+zp);*/
if(xp > 0 && yp > 0 && zp > 0){
int ix = volume.getIndexFor(x, y, z);
float vox = volume.getVoxelAt(ix);
int newIx = newVolume.getIndexFor(xp, yp, zp);
newVolume.setVoxelAt(newIx,vox);
}
}
}
}
prepareVolume(newVolume);
}
public void keyPressed() {
if (key == '-')
currScale = max(currScale - 0.1f, 0.5f);
if (key == '=')
currScale = min(currScale + 0.1f, 10);
if (key == 's') {
// save mesh as STL or OBJ file
mesh.saveAsSTL(sketchPath("noise.stl"));
}
if (key == 'r') {
rotate();
}
}
}
using toxi's vbo wrapper
/**
* A reusable, barebones wrapper for OpenGL Vertex Buffer Objects. Only
* handles actual vertex, normal and color buffers and assumes they can be dynamically
* modified/updated.
*
* @author Karsten Schmidt <info at postspectacular.com>
*/
import javax.media.opengl.GL;
import processing.opengl.*;
import com.sun.opengl.util.BufferUtil;
public class VBO {
final int STRIDE = BufferUtil.SIZEOF_FLOAT * 4;
int numVertices;
int[] vertID = new int[] {-1};
int[] normID = new int[] {-1};
int[] colorID = new int[] {-1};
private GL gl;
public VBO(GL gl, int num) {
this.gl = gl;
numVertices = num;
}
public void cleanup() {
gl.glDeleteBuffers(1, vertID, 0);
gl.glDeleteBuffers(1, normID, 0);
gl.glDeleteBuffers(1, colorID, 0);
}
void initBuffer(int[] bufferID) {
gl.glGenBuffers(1, bufferID, 0);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, bufferID[0]);
gl.glBufferData(GL.GL_ARRAY_BUFFER, numVertices * STRIDE, null,
GL.GL_DYNAMIC_DRAW);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
}
public void render(int shapeID) {
// gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
// check if we need to use normals?
if (normID[0] != -1) {
gl.glEnableClientState(GL.GL_NORMAL_ARRAY);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, normID[0]);
gl.glNormalPointer(GL.GL_FLOAT, STRIDE, 0);
}
// check if we need to use colors?
if (colorID[0] != -1) {
gl.glEnableClientState(GL.GL_COLOR_ARRAY);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, colorID[0]);
gl.glColorPointer(4, GL.GL_FLOAT, STRIDE, 0);
}
gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertID[0]);
gl.glVertexPointer(3, GL.GL_FLOAT, STRIDE, 0);
gl.glDrawArrays(shapeID, 0, numVertices);
gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
if (normID[0] != -1) {
gl.glDisableClientState(GL.GL_NORMAL_ARRAY);
}
if (colorID[0] != -1) {
gl.glDisableClientState(GL.GL_COLOR_ARRAY);
}
}
protected void updateBuffer(int id, float[] data) {
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, id);
gl.glMapBuffer(GL.GL_ARRAY_BUFFER, GL.GL_WRITE_ONLY)
.asFloatBuffer().put(data);
gl.glUnmapBuffer(GL.GL_ARRAY_BUFFER);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
}
public void updateColors(float[] colors) {
if (colorID[0] == -1) {
initBuffer(colorID);
}
updateBuffer(colorID[0], colors);
}
public void updateNormals(float[] normals) {
if (normID[0] == -1) {
initBuffer(normID);
}
updateBuffer(normID[0], normals);
}
public void updateVertices(float[] vertices) {
if (vertID[0] == -1) {
initBuffer(vertID);
}
updateBuffer(vertID[0], vertices);
}
}
Processing workshops for beginners in Berlin
[3 Replies]
03-Jul-2011 03:23 PM
Forum:
Events and Opportunities
I proposed a class at the Public School Berlin to have weekly processing workshops for beginners starting in August. I can teach and it's free. We should also go to Processing Berlin on August the 11th.
click:
http://berlin.thepublicschool.org/class/3571
Maybe you'd like to join us?
«Prev
Next »
Moderate user : arrmin
Forum