I've imported an object into Processing that I created in Blender.
The code below works and the object appears but seemingly very small (or distant).
If I try to move close to the object with PeasyCamm it disappears completely before it gets close enough to see properly. The only thing I could figure is that the object itself is very close to the camera but is in fact tiny...
I attempted to scale the object but a call to
myshape.getVertexCount()
indicates my object has no vertices and nothing I do seems to change anything. I have a tiny rendered object that disappears at about a quarter of the screen height.
PShape myshape;
import peasy.test.*;
import peasy.org.apache.commons.math.*;
import peasy.*;
import peasy.org.apache.commons.math.geometry.*;
PeasyCam camera;
void setup(){
size( 640, 480, P3D);
camera = new PeasyCam(this, 0, 0, 0, 50);
frameRate(10);
myshape = loadShape("test.obj");
for (int i = 0; i < myshape.getVertexCount(); i++){
PVector v = myshape.getVertex(i);
println("Inside");
v.x *= 45;
v.y *= 45;
v.z *= 45;
myshape.setVertex(i, v);
}
}
void draw(){
background(0);
shape(myshape);
}
The getVertexCount() and getVertex() functions only work with shapes that you create in the code, using the vertex() function. More info can be found in the reference.
If all you want to do is scale your shape, then you can simply use the scale() function. Here is some example code that scaled your object by a factor of 20:
PShape myshape;
void setup() {
size(500, 500, P3D);
myshape = loadShape("test.obj");
}
void draw() {
background(0);
translate(width/2, height/2, 100);
scale(20);
shape(myshape);
}
Edit: Apparently you can still get to the vertexes inside an object file, it just isn't as straightforward as calling the getVertex() function. First you have to loop through the shape's children and then call getVertex() on the children. More info in this forum post (see jeremydouglass's answer).
Related
I'm a total beginner so forgive me if this is probably silly or improper of me to ask.
I'm trying to make my own virtual oscillograph in processing. I don't really know how to explain it, but I want to "zoom out" from where I am getting the peaks in waveforms, which is the window size. I'm not sure what I'm doing wrong here or what's wrong with my code. I've tried changing the buffer size, and changing the multiplier for x/y. My sketch is adapted from a minim example Sketch.
All Help is greatly appreciated.
import ddf.minim.*;
Minim minim;
AudioInput in;
int frames;
int refresh = 7;
float fade = 32;
void setup()
{
size(800, 800, P3D);
minim = new Minim(this);
ellipseMode(RADIUS);
// use the getLineIn method of the Minim object to get an AudioInput
in = minim.getLineIn(Minim.STEREO);
println (in.bufferSize());
//in.enableMonitoring();
frameRate(1000);
background(0);
}
void draw()
{
frames++; //same saying frames = frames+1
if (frames%refresh == 0){
fill (0, 32, 0, fade);
rect (0, 0, width, height);
}
float x;
float y;
stroke (0, 0);
fill (0,255,0);
// draw the waveforms so we can see what we are monitoring
for(int i = 0; i < in.bufferSize() - 1; i++)
{
x = width/2 + in.left.get(i) * height/2;
y = height/2- in.right.get(i) * height/2;
ellipse(x, y, .5, .5);
}
}
Thanks
Edit: you don't need push and pop matrix here. Guess my understanding of it is lacking too. You can just use translate.
You can use matrices to create a camera object, there is tons of material out there that you can read up on to understand the math behind this and implement it anywhere.
However, there might be an easier solution here. You can use pushMatrix and popMatrix in combination with translate. Push and popping the matrix will manipulate the matrix stack - you create a new "frame" where you can play around with translations, then pop back the original frame (so you don't get lost by applying new translations on each frame).
push the matrix, translate the z coordinate once before drawing everything you want zoomed out, pop the matrix. You can set up a variable for the translation so that you can control this with your mouse.
Here's a crude example (I don't have all those libraries so couldn't add it to your code):
float scroll = 0;
float scroll_multiplier = 10;
void setup()
{
size(800, 800, P3D);
frameRate(1000);
background(0);
}
void draw()
{
background(0);
//draw HUD - things that don't zoom.
fill(255,0,0);
rect(400,300,100,100);
//We don't want to mess up our coordinate system, we push a new "frame" on the matrix stack
pushMatrix();
//We can now safely translate the Y axis, creating a zoom effect. In reality, whatever we pass to translate gets added to the coordinates of draw calls.
translate(0,0,scroll);
//Draw zoomed elements
fill(0,255,0);
rect(400,400,100,100);
//Pop the matrix - if we don't push and pop around our translation, the translation will be applied every frame, making our drawables dissapear in the distance.
popMatrix();
}
void mouseWheel(MouseEvent event) {
scroll += scroll_multiplier * event.getCount();
}
I have three global variables:
private PhysicsActor blade;
private PhysicsActor blades;
private ArrayList<PhysicsActors> blades;
I created an actor object from a class I created for my game.
blade = new PhysicsActor();
blade.storeAnimation( "", exTex );
blade.setOriginCenter();
blade.setEllipseBoundary();
blade.setMaxSpeed(50);
blade.setDeceleration(50);
bladesList = new ArrayList<PhysicsActor>();
for (int i = 0; i < 3 ; i++)
{
float xCoord = randomFloatGenerator(425, 50);
float yCoord = randomFloatGenerator(mapHeight - 200, 275);
blades = blade.clone();
blades.setPosition(xCoord, yCoord);
mainStage.addActor(blades);
bladesList.add(blades);
}
The problem is not that they do not spawn. It is that when I call for them to rotate while my game is running in my update(float dt) method, only one of them is rotating:
public void update(float dt)
{
// rotate the blade 70 degrees
blades.rotateBy(70);
// rest of code etc
}
Here is an image to help visualize
I know that this is happening because I am only rotating the blades actor. What I want to do is have them all rotate from the ArrayList. I do not know how to get them from the list however. I have tried bladesList.get(i) using a for loop and a couple other ways I saw online but it would not work. Any tips or instructions for me?
Also, I will post more code to clarify anything confusing if requested.
You can try this
for (PhysicsActor blade : bladesList) {
blade.rotateBy(70);
}
this will make all the blades in your list rotate by 70. Given you can access the array from where you are calling it.
Im writing a 3D sketch in which the user rotates the camera with peasyCam while left clicking and moving the mouse. The thing is that I want to move the objects while right click is pressed so that the user can drag the object across the screen's X and Y axis. Of course I know how to use mouseX and mouseY inputs to modify the translation but only across the 3D space coordinates as it shows on the GIF below:
example code of whats happening in the image:
import peasy.*;
import peasy.org.apache.commons.math.*;
import peasy.org.apache.commons.math.geometry.*;
PeasyCam cam;
float x=15;float y=15; float z=15;
float e;
void setup(){
size (700,700,P3D);
cam = new PeasyCam(this, 200);
cam.setRightDragHandler(null);
}
void draw(){
background(0);
pushMatrix();
translate(5, 5, 0);
fill(255);
stroke(255);
sphere(5);
popMatrix();
pushMatrix();
fill(255,0,0);
stroke(255,0,0);
translate(x, y, z);
sphere(5);
popMatrix();
stroke(0,0,255);
line(5,5,0,x,y,z);
//obvoiusly not working method
if(mousePressed && (mouseButton == RIGHT)){
x= x+(mouseX-pmouseX);
y= y+(mouseY-pmouseY);
}
}
void mouseWheel(MouseEvent event) {
e = event.getCount();
z=z+e;
println(e);
}
void mousePressed(){
if (mouseButton==RIGHT){
cam.setActive(false);
}
}
void mouseReleased(){
cam.setActive(true);
}
What I would need is to be able to drag the sphere only on the screens X/Y axis, at a fixed Z just like image below shows(simple simulation I made of the behaviour im looking for).
PeasyCam is for exploring the 3D space. The question might be difficult to undesrtand. The problem is about moving the object on the 3D world, using the screen/canvas 2D coordinates to make the object follow the cursor's movement. If the mouse goes to the left (x axis decreases), the object should move to the left on the screen, and not just on the worlds X axis. This is how the second example image behaves, but achieved by just simulating the 3D space with no actual rotations to the x,y,z axis.
I've been scratching my head with this thing and I cant seem to figure it out. I wouldn't have asked here otherwise. Thanks in advance guys.
PeasyCam is a library that gives you a camera that by default is controlled by the mouse. This allows you to render 3D scenes and not worry about the camera, since the library handles it for you.
But it sounds like that's not what you want. You want to render a 3D scene and use the mouse to control the position of the shapes in that scene. Basically, your controls are fighting with the default controls provided by the PeasyCam library.
I see that you've already tried disabling the right-click controls here:
cam.setRightDragHandler(null);
So at the very least you probably want to do the same thing with the left drag handler.
But at that point, why are you using the PeasyCam library at all?
And even if you disable the default left controls, you'll notice that the dragging of shapes is "exaggerated" because the camera is closer to the red shape, so moving it a little bit looks like it's moving more. Just like an object right in front of your face looks like it's moving a lot more than an object that's far away.
It sounds like what you really want to do is get rid of the PeasyCam library, and then use standard Processing functions to calculate the position of the spheres based on the user input. Check out the modelX(), modelY(), and modelZ() function in the reference.
Edit: Here is a simple example that shows the model functions in action:
float x;
float y;
void setup() {
size (700, 700, P3D);
}
void draw() {
background(0);
pushMatrix();
translate(width/2, height/2, 0);
fill(255);
stroke(255);
sphere(5);
popMatrix();
fill(255, 0, 0);
stroke(255, 0, 0);
if (mousePressed) {
x= modelX(mouseX, mouseY, 0);
y= modelY(mouseX, mouseY, 0);
}
translate(x, y, 15);
sphere(5);
}
May be you should be looking in beginHUD() and endHUD();
Here is the example code:
(Code from https://forum.processing.org/one/topic/2-questions-on-camera-view.html)
import peasy.*;
PeasyCam cam;
void setup() {
size(300,200,P3D);
// either put it here like this:
// cam = new PeasyCam(this, 50, 0, 0, 100);
cam = new PeasyCam(this, 0, 0, 0, 100);
cam.setMinimumDistance(50);
cam.setMaximumDistance(500);
// or separate like this:
cam.lookAt(50,0,0);
}
void draw() {
background(0);
//3D object
pushMatrix();
fill(255,0,0);
translate(50,0,0);
rotateX(-.5);
rotateY(-.5);
box(30);
popMatrix();
//2D object that is not affected by the camera
cam.beginHUD();
fill(0,0,255);
rect(200, height/2 -25 , 50, 50);
cam.endHUD();
}
I'm new to Processing, and I am trying to work with the Tweaking tool. My problem is that I can't seem to be able to tweak the values of variables created in the setup() method.
Below, an example:
Ellipse e;
void setup(){
size(640, 480);
e = new Ellipse();
}
void draw(){
background(220);
e.draw();
}
class Ellipse {
float w, l;
Ellipse(){
this.w = 300.0;
this.l = 300.0;
}
void draw(){
ellipse(300, 300 , w, l);
}
}
When I use "Tweak", I can tweak all four instances of 300 in the Ellipse class. It works exactly as expected for the 3rd and 4th ones, but when I tweak the values of w or l, nothing happens.
I assume this is because the Ellipse object is created from setup() and not draw(). Is this the right diagnostic, and is there a way around the problem? (I don't want to create a brand new object at every call of draw()).
The only changes you'll see are when you change numbers that haven't happened yet.
Your Ellipse has already been constructed, so changing the values of 300 in the constructor won't do anything. Note that if you were to create a new instance of Ellipse, then that new instance would indeed pick up the changes.
You are able to tweak the first two 300 values because they "happen" every frame.
If you want to be able to tweak the w and l variables, you need to put them in a place that happens every frame. You could do something like this:
void draw(){
w = 300;
l = 300;
ellipse(300, 300 , w, l);
}
Or you could just shorten it to this:
void draw(){
ellipse(300, 300 , 300, 300);
}
From the TweakMode homepage:
Scope of change
Without going into too much detail of how tweak mode operates
internally, you should remember that changing a number will have
effect only if the tweaked code will be executed in the future. For
example, take the following code:
void setup()
{
size(200, 200);
background(20);
}
void draw()
{
fill(100, 0, 0);
ellipse(100, 100, 50, 50);
}
In this code, changing the values of 'size(...)' and 'background(...)'
functions will have no effect while the sketch is running because
these lines of code happened once on setup and will never be executed
again during the sketch life. On the contrary, changing the values of
fill() and ellipse() will have effect because 'draw' is executed over
and over again.
The same principle applies to global variables, for example:
int CIRCLE_SIZE = 50;
void setup()
{
size(200, 200);
background(20);
}
void draw()
{
int red = 100;
fill(red, 0, 0);
ellipse(100, 100, CIRCLE_SIZE, CIRCLE_SIZE);
}
In this case, changing the value assigned to CIRCLE_SIZE (50) will
have no effect because the assignment of the value '50' to the
variable CIRCLE_SIZE happened only once during the sketch life, so the
value of CIRCLE_SIZE will remain the same even if the assigned value
is changed. On the contrary, changing the assigned value of the
variable 'red' (100) will have the expected effect because this
assignment happens every draw.
A simple solution to the problem with the global variables is to
reassign values you wish to tweak in the draw function. For example,
the following draw function will elliminate the issue we had with the
size of the ellipse in the previous code.
void draw()
{
CIRCLE_SIZE = 50;
int red = 100;
fill(red, 0, 0);
ellipse(100, 100, CIRCLE_SIZE, CIRCLE_SIZE);
}
Adding the line 'CIRCLE_SIZE = 50;' to the top of the draw function
made it possible to tweak this number and control also the size of the
circle in real time.
For a university course I'm making a game with a friend. The general idea is that we have some platforms moving from right to left and each time one goes offscreen it is generated at a random x and y position on the right (within some limits). There will be a little sprite that jumps from platform to platform.
We have reached a problem we're not sure how to solve. We have all the right code and everything but the platforms just won't move. They should move to the left at a constant speed of -4 pixels per frame (rectVelocity).
We cannot get them to move, though; they are static on the screen at the position each one is initially called in at.
This is the code as condensed as I can make it:
Platforms [] mainPlats;
void setup() {
size(750, 400);
mainPlats = new Platforms[3];
}
void draw() {
level();
}
void level() {
//This is the code for the first platform
mainPlats[0] = new Platforms(200, 200, 100, 15); //These values need to be set inside the class so that
//they aren't constantly overwriting the movement variables in the class
mainPlats[0].displayPlat();
mainPlats[0].platTransition();
//This is the code for the second platform
mainPlats[1] = new Platforms(420, 300, 100, 15);
mainPlats[1].displayPlat();
mainPlats[1].platTransition();
//This is the code for the third platform
mainPlats[2] = new Platforms(570, 350, 100, 15);
mainPlats[2].displayPlat();
mainPlats[2].platTransition();
}
class Platforms {
PImage platform;
int rectX, rectY, rectWidth, rectHeight;
int rectVelocity = 4;
Platforms(int x, int y, int w, int h) {
rectX = x;
rectY = y;
// rectX = (int(random(600, 800))); //Tried to randomise start position, failed hilariously
//rectY = (int(random(150, 350)));
rectWidth = w;
rectHeight = h;
}
void displayPlat() {
platform = loadImage ("images/tiles.png");
//imageMode(CENTER);
image(platform, rectX, rectY, 100, 15); //rectangle platforms replaced with images
}
void platMove() {
rectX -= rectVelocity;
}
void platTransition() {
if (rectX < -200) {
rectX = (int(random(700, 1000)));
rectY = (int(random(150, 350)));
}
}
}
From the draw() function, you call your level() function, which initializes your Platform array every single frame.
This means that you create new Platforms at their starting positions every frame. You never see the platforms move, because as soon as you do move them, you replace them with new platforms at the starting positions again.
So step one is to move their initialization out of the level() function and only call them once, at the beginning of your sketch- the setup() function would be one place you could put them.
Your other problem is that you never actually call the platMove() function. So step two is to make sure you call that function.
A solution might look something like this:
Platforms [] mainPlats;
void setup() {
size(750, 400);
mainPlats = new Platforms[3];
mainPlats[0] = new Platforms(200, 200, 100, 15);
mainPlats[1] = new Platforms(420, 300, 100, 15);
mainPlats[2] = new Platforms(570, 350, 100, 15);
}
void draw() {
level();
}
void level() {
mainPlats[0].displayPlat();
mainPlats[0].platMove();
mainPlats[0].platTransition();
mainPlats[1].displayPlat();
mainPlats[1].platMove();
mainPlats[1].platTransition();
mainPlats[2].displayPlat();
mainPlats[2].platMove();
mainPlats[2].platTransition();
}
Also note that you shouldn't load the image every single frame, either. You should only load it once, at startup. You also might want to use a for loop to iterate over your Platforms instead of referring to every single index. But these don't really affect your problem.
You've got rectX as positive values (>0) when you construct the platforms, but you are checking for rectX < -200 when you call platTransition, which is why it never does anything.