i have made this code,with a 3d model,the model starts dismorph after 100 frames.I have a box shape that is moved with mouse,i want when ever the vertices be inside the box,to reset their position to the original position,and reconstruct the model,while the others dismorph. Always resetting the position when they are in the box,and move when they are not.Can anyone help me.Until now what it happens,is that when the vertices are inside the box they stop moving.
Thanks in Advance
import peasy.*;
import saito.objloader.*;
OBJModel model ;
OBJModel tmpmodel ;
PeasyCam cam;
float easing = 0.005;
float r;
float k =0.00001;
int VertCount;
PVector[] Verts;
PVector Mouse;
void setup()
{
size(800, 800, P3D);
frameRate(30);
noStroke();
model = new OBJModel(this, "Model2.obj", "absolute", TRIANGLES);
model.enableDebug();
model.scale(100);
model.translateToCenter();
tmpmodel = new OBJModel(this, "Model2.obj", "absolute", TRIANGLES);
tmpmodel.enableDebug();
tmpmodel.scale(100);
tmpmodel.translateToCenter();
cam = new PeasyCam(this, width/2, height/2, 0, 994);
}
void draw()
{
background(129);
lights();
int VertCount = model.getVertexCount ();
PVector[] Verts = new PVector[VertCount];
PVector[] locas = new PVector[VertCount];
float r =80;
PVector Mouse = new PVector(mouseX-width/2, mouseY-height/2, 0);
cam.setMouseControlled(true);
//println(frameCount);
pushMatrix();
translate(width/2, height/2, 0);
for (int i = 0; i < VertCount; i++) {
//PVector orgv = model.getVertex(i);
Verts[i]= model.getVertex(i);
arrayCopy(Verts, locas);
//PVector tmpv = new PVector();
if (frameCount> 100) {
float randX = random(-5, 5);
float randY = random(-5, 5);
float randZ = random(-5, 5);
PVector Ran = new PVector(randX, randY, randZ);
//float norX = abs(cos(k)) * randX;
//float norY = abs(cos(k)) * randY;
//float norZ = abs(cos(k)) * randZ;
if (Verts[i].x > Mouse.x - r/2 && Verts[i].x < Mouse.x + r/2) {
if (Verts[i].x > Mouse.y - r/2 && Verts[i].x < Mouse.y + r/2) {
if (Verts[i].x > Mouse.z - r/2 && Verts[i].x < Mouse.z + r/2) {
arrayCopy(locas, Verts);
}
}
} else {
Verts[i].x+=Ran.x;
Verts[i].y+=Ran.y;
Verts[i].z+=Ran.z;
if (Verts[i].x > width/2 || Verts[i].x < -width/2) {
Verts[i].x+=-Ran.x;
}
if (Verts[i].y > height/2 || Verts[i].y < -height/2) {
Verts[i].y+=-Ran.y;
}
if (Verts[i].z < -800/2 || Verts[i].z > 800/2) {
Verts[i].z+=-Ran.z;
}
}
tmpmodel.setVertex(i, Verts[i].x, Verts[i].y, Verts[i].z);
}
k+=0.0001;
}
pushMatrix();
translate(Mouse.x, Mouse.y, Mouse.z);
noFill();
stroke(255);
box(r);
popMatrix();
noStroke();
tmpmodel.draw();
popMatrix();
pushMatrix();
translate(width/2, height/2, 0);
noFill();
stroke(255);
box(width, height, 600);
popMatrix();
}
if you want to run it use the model from the saito obj example or the PshapeObj example.
There are a few things about your code that don't make a ton of sense (some comments might have helped with that). Why are you copying the array like that?
In any case, I would start simpler if I were you. I would adopt an object oriented approach, where you create a class that encapsulates a point's original position as well as its current position.
Here's an example that does this in two dimensions, but this approach generalizes to three dimensions:
ArrayList<MovingPoint> points = new ArrayList<MovingPoint>();
float circleDiameter = 200;
void setup(){
size(500, 500);
for(int i = 0; i < 100; i++){
points.add(new MovingPoint());
}
}
void draw(){
background(0);
noFill();
stroke(255, 0, 0);
ellipse(mouseX, mouseY, circleDiameter, circleDiameter);
fill(255);
stroke(255);
MovingPoint previousPoint = null;
for(MovingPoint mp : points){
mp.draw();
if(previousPoint != null){
line(previousPoint.current.x, previousPoint.current.y, mp.current.x, mp.current.y);
}
previousPoint = mp;
}
}
class MovingPoint{
PVector original;
PVector current;
public MovingPoint(){
original = new PVector(random(width), random(height));
current = original.copy();
}
void draw(){
if(dist(current.x, current.y, mouseX, mouseY) < circleDiameter/2){
//inside circle, reset position
current = original.copy();
}
else{
//outside circle, move randomly
current.x += random(-5, 5);
current.y += random(-5, 5);
}
ellipse(current.x, current.y, 10, 10);
}
}
You shouldn't have to go through the rigmarole of copying arrays. Just use a class that remembers each point's original and current positions, and then switch between them depending on the mouse position.
If you still can't get it working, please post another question that works from this example instead of your entire sketch. It's hard to help if we don't have access to the libraries you're using, so you're better off getting rid of them and narrowing the problem down to as few lines as possible. Good luck.
Related
My problem is wherever i click a node appears and for the second click another node appears with connected edge...so i want that When i click at any location, the node should be generated at the closest grid intersection point. I tried using loops.
and i'm trying to do that without "class"
int n_partition=10;
int length = 101;
PVector[] position = new PVector[length];
int BallNum;
void setup() {
size(600, 360);
background(255);
}
void draw() {
fill(255);
grid();
fill(0);
}
void mousePressed(){
stroke(0);
BallNum++;
position[BallNum]= new PVector(mouseX, mouseY);
circle(position[BallNum].x, position[BallNum].y, 10);
if (BallNum > 1) {
line(position[BallNum].x,position[BallNum].y,position[BallNum-
1].x,position[BallNum-1].y);
line(position[1].x,position[1].y,position[BallNum].x,position[BallNum] .y);
}
for (int i = 0; i < position[BallNum].length; ++ i) {
position[BallNum] = position[BallNum].get(i);
position[BallNum] = position[BallNum].get((i+1) % position[BallNum].length);
line(position[BallNum].x, position[BallNum].y,
position[BallNum].x, position[BallNum].y);
}
}
I EXPECT THE NODE SHOULD GO TO THE CLOSEST INTERSECTION.
You've to calculate the nearest position of the mouse to a point on the grid. For that you've to know the width (tile_width) and the height (tile_height) of cell.
The index of the cell can be calculated by the dividing the mouse position to the size of a tile and round() the result to an integral value (e.g. round(mouseX / (float)tile_width)).
Don't draw anything in int the mousePressed callback. The only thing you've to do there is to add a pint to the list:
void mousePressed(){
int tile_width = width / n_partition; // adapt this for your needs
int tile_height = height / n_partition;
int x = round(mouseX / (float)tile_width) * tile_width;
int y = round(mouseY / (float)tile_height) * tile_height;
position[BallNum]= new PVector(x, y);
BallNum++;
}
All the drawing has to be done in draw(). Draw the lines and points in separate loops:
void draw() {
background(255);
grid();
// draw the lines in a loop
strokeWeight(3);
stroke(0, 0, 255);
for (int i = 0; i < BallNum; ++ i) {
int i2 = (i+1) % BallNum;
line(position[i].x, position[i].y, position[i2].x, position[i2].y);
}
// draw balls in a loop
strokeWeight(1);
stroke(0, 0, 0);
fill (255, 0, 0);
for (int i = 0; i < BallNum; ++i) {
circle(position[i].x, position[i].y, 10);
}
}
Note, the scene is consecutively redrawn in every frame. Before the scene is drawn, the entire window has to be "cleared" by background().
See the result:
I'm trying to create a script that drawls a curve through 'n' vertexes equally spaced around the center of an ellipse.
The reason I'm not just drawling an ellipse around the center ellipse is because I eventually want to connect a micro-controller to Processing where the data points acquired from the 'n' amount of sensors will vary the height ('y') of each vertex, creating constantly changing, irregular curves around the center ellipse such as this possible curve:
Essentially, this is supposed to be a data visualizer, but I cannot figure out why this is not working or how to achieve this effect after going through examples and the documentation on https://processing.org/reference/.
Here is my code:
color WHITE = color(255);
color BLACK = color(0);
void setup() {
size(500, 500);
}
void draw() {
background(WHITE);
translate(width/2, height/2); // move origin to center of window
// center ellipse
noStroke();
fill(color(255, 0, 0));
ellipse(0, 0, 10, 10); // center point, red
fill(BLACK);
int n = 10;
int y = 100;
float angle = TWO_PI / n;
beginShape();
for (int i = 0; i < n; i++) {
rotate(angle);
curveVertex(0, y);
}
endShape();
}
The matrix operations like rotate do not transform the single vertices in a shape. The current matrix is applied to the entire shape when it is draw (at endShape). You've to calculate all the vertex coordinates:
Create a ArrayList of PVector, fill it with points and draw it in a loop:
color WHITE = color(255);
color BLACK = color(0);
ArrayList<PVector> points = new ArrayList<PVector>();
void setup() {
size(500, 500);
int n = 10;
int radius = 100;
for (int i = 0; i <= n; i++) {
float angle = TWO_PI * (float)i/n;
points.add(new PVector(cos(angle)*radius, sin(angle)*radius));
}
}
void draw() {
background(WHITE);
translate(width/2, height/2);
noFill();
stroke(255, 0, 0);
beginShape();
PVector last = points.get(points.size()-1);
curveVertex(last.x, last.y);
for (int i = 0; i < points.size(); i++) {
PVector p = points.get(i);
curveVertex(p.x, p.y);
}
PVector first = points.get(0);
curveVertex(first.x, first.y);
endShape();
}
I've been working on this a while and feel so close! Should be easy, but I'm still new to this.
The skeleton hand data is being passed in as joints[KinectPV2.JointType_HandLeft] and can be accessed through joint.getX() and joint.getY(). I want to pass this data into the update function to replace mouseX and mouseY. I'm guessing I have to create global variables to access it within the update function or maybe I have to pass the skeleton data as parameters into the update function? How can I replace the mouse position data with the hand position?
import KinectPV2.*;
KinectPV2 kinect;
private class MyFluidData implements DwFluid2D.FluidData{
// update() is called during the fluid-simulation update step.
#Override
public void update(DwFluid2D fluid) {
float px, py, vx, vy, radius, vscale, temperature;
radius = 15;
vscale = 10;
px = width/2;
py = 50;
vx = 1 * +vscale;
vy = 1 * vscale;
radius = 40;
temperature = 1f;
fluid.addDensity(px, py, radius, 0.2f, 0.3f, 0.5f, 1.0f);
fluid.addTemperature(px, py, radius, temperature);
particles.spawn(fluid, px, py, radius, 100);
boolean mouse_input = mousePressed;
// add impulse: density + velocity, particles
if(mouse_input && mouseButton == LEFT){
radius = 15;
vscale = 15;
px = mouseX;
py = height-mouseY;
vx = (mouseX - pmouseX) * +vscale;
vy = (mouseY - pmouseY) * -vscale;
fluid.addDensity (px, py, radius, 0.25f, 0.0f, 0.1f, 1.0f);
fluid.addVelocity(px, py, radius, vx, vy);
particles.spawn(fluid, px, py, radius*2, 300);
}
// add impulse: density + temperature, particles
if(mouse_input && mouseButton == CENTER){
radius = 15;
vscale = 15;
px = mouseX;
py = height-mouseY;
temperature = 2f;
fluid.addDensity(px, py, radius, 0.25f, 0.0f, 0.1f, 1.0f);
fluid.addTemperature(px, py, radius, temperature);
particles.spawn(fluid, px, py, radius, 100);
}
// particles
if(mouse_input && mouseButton == RIGHT){
px = mouseX;
py = height - 1 - mouseY; // invert
radius = 50;
particles.spawn(fluid, px, py, radius, 300);
}
}
}
int viewport_w = 1280;
int viewport_h = 720;
int viewport_x = 230;
int viewport_y = 0;
int gui_w = 200;
int gui_x = 20;
int gui_y = 20;
int fluidgrid_scale = 3;
DwFluid2D fluid;
// render targets
PGraphics2D pg_fluid;
//texture-buffer, for adding obstacles
PGraphics2D pg_obstacles;
// custom particle system
MyParticleSystem particles;
// some state variables for the GUI/display
int BACKGROUND_COLOR = 0;
boolean UPDATE_FLUID = true;
boolean DISPLAY_FLUID_TEXTURES = false;
boolean DISPLAY_FLUID_VECTORS = false;
int DISPLAY_fluid_texture_mode = 0;
boolean DISPLAY_PARTICLES = true;
public void settings() {
size(viewport_w, viewport_h, P2D);
smooth(4);
}
public void setup() {
surface.setLocation(viewport_x, viewport_y);
// main library context
DwPixelFlow context = new DwPixelFlow(this);
context.print();
context.printGL();
// fluid simulation
fluid = new DwFluid2D(context, viewport_w, viewport_h, fluidgrid_scale);
// set some simulation parameters
fluid.param.dissipation_density = 0.999f;
fluid.param.dissipation_velocity = 0.99f;
fluid.param.dissipation_temperature = 0.80f;
fluid.param.vorticity = 0.10f;
fluid.param.timestep = 0.25f;
fluid.param.gridscale = 8f;
// interface for adding data to the fluid simulation
MyFluidData cb_fluid_data = new MyFluidData();
fluid.addCallback_FluiData(cb_fluid_data);
// pgraphics for fluid
pg_fluid = (PGraphics2D) createGraphics(viewport_w, viewport_h, P2D);
pg_fluid.smooth(4);
pg_fluid.beginDraw();
pg_fluid.background(BACKGROUND_COLOR);
pg_fluid.endDraw();
// pgraphics for obstacles
pg_obstacles = (PGraphics2D) createGraphics(viewport_w, viewport_h, P2D);
pg_obstacles.smooth(4);
pg_obstacles.beginDraw();
pg_obstacles.clear();
float radius;
radius = 200;
pg_obstacles.stroke(64);
pg_obstacles.strokeWeight(1);
pg_obstacles.fill(0);
pg_obstacles.rect(1*width/2f, 1*height/4f, radius, radius/2, 10);
pg_obstacles.stroke(64);
pg_obstacles.strokeWeight(1);
pg_obstacles.fill(0);
pg_obstacles.rect(1*width/3.5f, 1*height/2.5f, radius, radius/2, 10);
//// border-obstacle
//pg_obstacles.strokeWeight(20);
//pg_obstacles.stroke(64);
//pg_obstacles.noFill();
//pg_obstacles.rect(0, 0, pg_obstacles.width, pg_obstacles.height);
pg_obstacles.endDraw();
fluid.addObstacles(pg_obstacles);
// custom particle object
particles = new MyParticleSystem(context, 1024 * 1024);
kinect = new KinectPV2(this);
//Enables depth and Body tracking (mask image)
kinect.enableDepthMaskImg(true);
kinect.enableSkeletonDepthMap(true);
kinect.init();
background(0);
frameRate(60);
}
public void draw() {
PImage imgC = kinect.getDepthMaskImage();
image(imgC, 0, 0, 320, 240);
//get the skeletons as an Arraylist of KSkeletons
ArrayList<KSkeleton> skeletonArray = kinect.getSkeletonDepthMap();
//individual joints
for (int i = 0; i < skeletonArray.size(); i++) {
KSkeleton skeleton = (KSkeleton) skeletonArray.get(i);
//if the skeleton is being tracked compute the skleton joints
if (skeleton.isTracked()) {
KJoint[] joints = skeleton.getJoints();
color col = skeleton.getIndexColor();
fill(col);
stroke(col);
drawHandState(joints[KinectPV2.JointType_HandRight]);
drawHandState(joints[KinectPV2.JointType_HandLeft]);
}
}
// update simulation
if(UPDATE_FLUID){
fluid.addObstacles(pg_obstacles);
fluid.update();
particles.update(fluid);
}
// clear render target
pg_fluid.beginDraw();
pg_fluid.background(BACKGROUND_COLOR);
pg_fluid.endDraw();
// render fluid stuff
if(DISPLAY_FLUID_TEXTURES){
// render: density (0), temperature (1), pressure (2), velocity (3)
fluid.renderFluidTextures(pg_fluid, DISPLAY_fluid_texture_mode);
}
if(DISPLAY_FLUID_VECTORS){
// render: velocity vector field
fluid.renderFluidVectors(pg_fluid, 10);
}
if( DISPLAY_PARTICLES){
// render: particles; 0 ... points, 1 ...sprite texture, 2 ... dynamic points
particles.render(pg_fluid, BACKGROUND_COLOR);
}
// display
image(pg_fluid , 320, 0);
image(pg_obstacles, 320, 0);
// display number of particles as text
//String txt_num_particles = String.format("Particles %,d", particles.ALIVE_PARTICLES);
//fill(0, 0, 0, 220);
//noStroke();
//rect(10, height-10, 160, -30);
//fill(255,128,0);
//text(txt_num_particles, 20, height-20);
// info
//String txt_fps = String.format(getClass().getName()+ " [size %d/%d] [frame %d] [fps %6.2f]", fluid.fluid_w, fluid.fluid_h, fluid.simulation_step, frameRate);
//surface.setTitle(txt_fps);
}
//draw a ellipse depending on the hand state
void drawHandState(KJoint joint) {
noStroke();
handState(joint.getState());
//println(joint.getState());
pushMatrix();
translate(joint.getX(), joint.getY(), joint.getZ());
//println(joint.getX(), joint.getY(), joint.getZ());
ellipse(joint.getX(), joint.getY(), 70, 70);
popMatrix();
}
/*
Different hand state
KinectPV2.HandState_Open
KinectPV2.HandState_Closed
KinectPV2.HandState_Lasso
KinectPV2.HandState_NotTracked
*/
//Depending on the hand state change the color
void handState(int handState) {
switch(handState) {
case KinectPV2.HandState_Open:
fill(0, 255, 0);
break;
case KinectPV2.HandState_Closed:
fill(255, 0, 0);
break;
case KinectPV2.HandState_Lasso:
fill(0, 0, 255);
break;
case KinectPV2.HandState_NotTracked:
fill(100, 100, 100);
break;
}
}
I'm guessing I have to create global variables to access it within the update function or maybe I have to pass the skeleton data as parameters into the update function?
What happened when you tried those approaches?
Either approach sounds fine. You could store the variables in a sketch-level variable, set those variables from the kinect code, then use those variables in your drawing code. Or you could pass the variables as a parameter to the drawing code. Either should work fine. I'd probably go for the first approach because it sounds easier to me, but that's just my personal preference.
I suggest working in smaller chunks. Create a separate program that ignores the kinect for now. Create a hard-coded sketch-level variable that holds the same type of information you'd get from the kinect. Then write drawing code that uses that hard-coded variable to draw the frame. Get that working perfectly before you try adding the kinect code back in.
Then if you get stuck on a specific step, you can post a MCVE and we can go from there. Good luck.
first of all, sorry, because of my rusty English. Since i learnt German i forgot the English.
I'm doing tests with libGDX and my code doesn't detect any collisions.
In my Screen:
public Pantalla(SpriteBatch batch_1) {
batch = batch_1;
screenWidth = Gdx.graphics.getWidth();
screenHeight = Gdx.graphics.getHeight();
stage = new Stage(new StretchViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()),batch);
Gdx.input.setInputProcessor(stage);
camera = new OrthographicCamera();
camera.setToOrtho(false, 1000, 840);
camera.update();
mapas = new Mapas(camera);
// ACTORS
indiana_actor = new indiana_Actor();
//Here comes TOUCHPAD with Skin blaBlaBla...
if (touchpad.isTouched()) {
if (touchpad.getKnobX() > 120) {
indiana_actor.moveBy(32,0);
camera.translate(32, 0);
return; }
}
stage.addActor(indiana_actor);
stage.addActor(touchpad);
Gdx.input.setInputProcessor(stage);
}
public void render(float delta) {//TODO RENDER
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
mapas.MapasRender(camera,indiana_actor);
batch.begin();
batch.end();
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
indiana_actor Class:
public indiana_Actor() {
W=Gdx.graphics.getWidth(); H=Gdx.graphics.getHeight();
bounds=new Rectangle((int)getX(), (int)getY(), (int)getWidth(), (int)getHeight());
}
Animation anim_temp;
#Override
public void draw(Batch batch, float parentAlpha) {
stateTime += Gdx.graphics.getDeltaTime();
batch.setColor(getColor());
batch.draw(Assets.indiana_stop_arriba, (W/2), (H/2), 110, 160);
bounds=new Rectangle((int)getX(), (int)getY(), (int)getWidth(), (int)getHeight());
}
and Mapas Class.
In these class i get the Objects in the "objetos" TiledLayer, and triying to check collisions with a for(...) in the renderer.
public Mapas(OrthographicCamera camera2){
map = new TmxMapLoader().load("terrain/prueba.tmx");
renderer = new OrthogonalTiledMapRenderer(map, 10);//ESCALA
renderer.setView(camera2);
collisionObjects = map.getLayers().get("objetos").getObjects();
collisionRects = new Array<Rectangle>();
collisionRects_total=collisionObjects.getCount();
int tileWidth = 32; // whatever your tile width is
int tileHeight = 32; // whatever your tile height is
for (int i = 0; i < collisionObjects.getCount(); i++) {
RectangleMapObject obj = (RectangleMapObject) collisionObjects.get(i);
Rectangle rect = obj.getRectangle();
collisionRects.add(new Rectangle(rect.x / tileWidth, rect.y / tileHeight, rect.width / tileWidth, rect.height / tileHeight));
}
}
public void MapasRender(OrthographicCamera camera2,indiana_Actor indi){
camera2.update();
renderer.setView(camera2);
renderer.render();
for (int i = 0; i < collisionRects_total; i++) {
Rectangle rect = collisionRects.get(i);
if (indi.bounds.overlaps(rect)){
Gdx.app.log("EVENTO", "MAPAS RENDER - COLISION!");
}if (rect.overlaps(indi.bounds)){
Gdx.app.log("EVENTO", "MAPAS RENDER - COLISION!");
}
}
}
I know (Through the logcat) that the
" for (int i = 0; i < collisionRects_total; i++) {
Rectangle rect = collisionRects.get(i); "
get always the objectsRectangle , but in the next line find any overlaps.
Is that a problem with the actor bounds-rectangle?A problem when moving actor through the map??....
Thanks in advance!!
Why dont U at first check if your rectangle for collision draw correctly on position. You can do that by calling
shapeRenderer.begin(ShapeType.Line);
shapeRenderer.setColor(Color.NAVY);
shapeRenderer.rect(object.getrect().x,
object.getrect().y,object.getrect().width,
object.getrect().height);
may be you draw collision rectangles at wrong position so collision will never occur.
I am writing a program in Processing to make a 3-D scatterplot that one can rotate around in space using PeasyCam. Data is read in from a text file to an ArrayList of PVectors. The entire code is shown below. What I don't understand is that importTextfile() needs to be called (repeatedly) within draw() and this significantly slows things down. Why can't I get away with calling it once within setup()? With "println(pointsList)" within draw() I can see that pointList changes if it's not preceded by importTextFile(). Can anyone explain why?
(Update: From trying to construct a minimum working example I see now that the problem is when I make a PVector V and then write over it to map it to the display window. I would still appreciate feedback on a good work around that involves calling importTextFile() just during setup(). What do I use instead of .get() so I get a copy of what's in the Arraylist and not a pointer to the actually value in the ArrayList?)
Here is the code:
import peasy.*;
PeasyCam cam;
ArrayList <PVector>pointList;
int maxX = 0;
int maxY = 0;
int maxZ = 0;
int minX = 10000;
int minY = 10000;
int minZ = 10000;
int range = 0;
void setup() {
size(500, 500, P3D);
cam = new PeasyCam(this, width/2, width/2, width/2, 800);
cam.setMinimumDistance(100);
cam.setMaximumDistance(2000);
pointList = new ArrayList();
importTextFile();
println(pointList);
//Determine min and max along each axis
for (int i=0; i < pointList.size(); i++) {
PVector R = pointList.get(i);
if (R.x > maxX) {
maxX = (int)R.x;
}
if (R.x < minX) {
minX = (int)R.x;
}
if (R.y > maxY) {
maxY = (int)R.y;
}
if (R.y < minY) {
minY = (int)R.y;
}
if (R.z > maxZ) {
maxZ = (int)R.z;
}
if (R.z < minZ) {
minZ = (int)R.z;
}
}
if (maxX - minX > range) {
range = maxX - minX;
}
if (maxY - minY > range) {
range = maxY - minY;
}
if (maxZ - minZ > range) {
range = maxZ - minZ;
}
println(pointList);
}
void draw() {
//importTextFile(); Uncomment to make run properly
println(pointList);
background(255);
stroke(0);
strokeWeight(2);
line(0, 0, 0, width, 0, 0);
line(0, 0, 0, 0, width, 0);
line(0, 0, 0, 0, 0, width);
stroke(150);
strokeWeight(1);
for (int i=1; i<6; i++) {
line(i*width/5, 0, 0, i*width/5, width, 0);
line(0, i*width/5, 0, width, i*width/5, 0);
}
lights();
noStroke();
fill(255, 0, 0);
sphereDetail(10);
//**The problem is here**
for (int i=0; i < pointList.size(); i++) {
PVector V = pointList.get(i);
V.x = map(V.x, minX-50, minX+range+50, 0, width);
V.y = map(V.y, minY-50, minY+range+50, 0, width);
V.z = map(V.z, minZ-50, minZ+range+50, 0, width);
pushMatrix();
translate(V.x, V.y, V.z);
sphere(4);
popMatrix();
}
}
void importTextFile() {
String[] strLines = loadStrings("positions.txt");
for (int i = 0; i < strLines.length; ++i) {
String[] arrTokens = split(strLines[i], ',');
float xx = float(arrTokens[2]);
float yy = float(arrTokens[1]);
float zz = float(arrTokens[0]);
pointList.add( new PVector(xx,zz,yy) );
}
}
You could continue to refactor, I don't know why they show this way of iterating through ArrayLists in the Processing documentation but here is a go at refactoring it:
float calcV (float n) {
return map (n, minX-50, minX+range+50, 0, width);
}
for (PVector V: pointList) {
pushMatrix();
translate(calcV(V.x), calcV(V.y), calcV(V.z));
sphere(4);
popMatrix();
}
You might consider creating a new Class with a PVector as a field or extending PVector. Daniel Shiffman uses this pattern a lot. Create a Class with a PVector for position, another for velocity, a method to calc the new position per frame and another to draw it out to screen. That gives you a lot of flexibility without having to write a ton of loops, other than one to calc and display the objects in your ArrayList.
As PVector is an object, when you do PVector V = pointList.get(i) you pass the reference for that specific element in pointList, to V. It's address in memory. So now V and pointList.get(number) share the same memory address. Any change in either one will change both, as they are two different pointers to same place.
But, if you do:
PVector V = new PVector(pointList.get(i).x, pointList.get(i).y, pointList.get(i).z);
V will be a new object and things will work as you want, cause now V has it's own memory address. And poinList will remain untouched. Same thing goes for other objects, arrays for instance, try this to see:
int[] one = new int[3];
int[] two = new int[3];
void setup(){
one[0] = 0;
one[1] = 1;
one[2] = 2;
print("one firstPrint -> \n");
println(one);
two = one;
print("two firstPrint -> \n");
println(two);
two[2] = 4;
// we didn't mean to change one, but...
print("one secondPrint -> \n");
println(one);
}
I fixed things with the code below but am still interested in other ways.
for (int i=0; i < pointList.size(); i++) {
PVector V = pointList.get(i);
PVector W = new PVector(0.0, 0.0, 0.0);
W.x = map(V.x, minX-50, minX+range+50, 0, width);
W.y = map(V.y, minY-50, minY+range+50, 0, width);
W.z = map(V.z, minZ-50, minZ+range+50, 0, width);
pushMatrix();
translate(W.x, W.y, W.z);
sphere(4);
popMatrix();
}