I am trying to rotate a vector I have created in illustrator using processing. I would like it to rotate this vector from it's center so it appears to be spinning as oppose to moving around an invisible point. Below is my attempt:
PShape WOE;
void setup(){
WOE = loadShape("WOE.svg");
size (500, 500);
smooth();
}
void draw(){
background(20);
shape(WOE, width/2, height/2, WOE.width, WOE.height); //draw shape in "center" of canvas (250, 250)
translate(-WOE.width/2, -WOE.height/2); //move shape so that center of shape is aligned with 250, 250
WOE.rotate(0.01);
}
From a strictly logical point of view this should work, however this results in the vector rotating around the center of the canvas, but approximately 100px away. I have tried using shapeMode(CENTER); but this unfortunately causes no improvement. Hope someone can help, thanks!
For Reference
Here is WOE.svg: https://www.dropbox.com/s/jp02yyfcrrnep93/WOE.svg?dl=0
I think part of your problem is that you're mixing rotating the shape and translating the entire sketch. I would try to stick with one or the other: either translate and rotate the entire sketch, or only translate and rotate the shape.
That being said, I'm not surprised this gave you trouble.
I would expect this to work:
PShape WOE;
void setup() {
size (500, 500);
WOE = loadShape("WOE.svg");
WOE.translate(-WOE.width/2, -WOE.height/2);
}
void draw() {
background(20);
WOE.rotate(.01);
shape(WOE, width/2, height/2);
}
However, this exhibits the same off-center behavior you're noticing. But if I switch to the P2D renderer, it works fine!
size (500, 500, P2D);
Now the shape is centered in the window and rotates around the shape's center. The difference between renderers seems buggy, but I can't find an open bug on GitHub. Edit: I found this SO question, which lead to this GitHub issue.
In any case, it might be easier to rotate the entire sketch instead of the shape:
PShape WOE;
float rotation = 0;
void setup() {
size (500, 500);
WOE = loadShape("WOE.svg");
shapeMode(CENTER);
}
void draw() {
background(20);
translate(width/2, height/2);
rotate(rotation);
shape(WOE);
rotation += .01;
}
This code works by translating the entire sketch to the center of the window, then rotating the entire sketch, then drawing the shape. Think of this like moving the camera instead of moving the shape. If you have other stuff to draw, then you can use the pushMatrix() and popMatrix() functions to isolate the transformation. This works the same in the default renderer and the P2D renderer.
Related
In Processing, how can I modify an existing sketch which saves each frame to an image file so that it does not render to the screen?
I saw in https://forum.processing.org/one/topic/how-can-i-save-calculate-frame-without-displaying-them-in-real-time.html that you can use PGraphics to draw graphics into an offline buffer, which seems like it would be what I am after, but I am not sure how I can easily modify my existing sketch to use the PGraphics class in that way.
On top of this, I would like the option to render to screen as well if needed by setting a toggle variable.
Is there an easy way of "retrofitting" an existing sketch so that it can use PGraphics instead of the default rendering method (say, in the setup method) so I don't have to go into my sketch and change every single draw command?
You can use a PGraphics object and draw on it just like you would with a canvas. Here's an example sketch with no draw loop which outputs an image file:
void setup() {
PGraphics pg = createGraphics(150, 150);
pg.beginDraw();
pg.background(255);
pg.stroke(0);
pg.fill(color(0, 0, 200));
pg.rect(50, 50, 50, 50);
pg.endDraw();
pg.save("fileName.png");
}
In my sketch's folder, it created this file:
About the other question: I don't think that you can retrofit a written draw loop into a similar output without rendering it in the sketch's window without heavily modifying the code, BUT... if your goal is yo be able to choose between drawing to the sketch window or to a file, you can draw in PGraphics every frame and choose whether if you want to show the PGraphics or not depending on your business rules. You'll still have a lot of refactoring to do, but it's unavoidable.
Here's the same example than before, but implementing this idea:
boolean showFrame = true;
boolean saveFrame = false;
void setup() {
size(150, 150);
}
void draw() {
PGraphics pg = createGraphics(150, 150);
pg.beginDraw();
pg.background(255);
pg.stroke(0);
pg.fill(color(0, 0, 200));
pg.rect(50, 50, 50, 50);
pg.endDraw();
if (showFrame) {image(pg, 0, 0);}
if (saveFrame) {pg.save("fileName.png");}
}
Hope this helps. Have fun!
I have a question regarding rendering with box2d and libgdx.
As you can see in the screenshot below I have a problem when changing the window resolution.
Box2d gets scaled over the entire screen although the viewport is only using a small portion of it. Also the lights get scaled and do not match the real position anymore (but I think this is related to the same issue).
My idea is that I somehow need to adjust the matrix (b2dCombinedMatrix) for box2d before rendering but I have no idea how.
Personally I think that I need to tell it that it should use the same "render boundaries" as the viewport but I cannot figure out how to do that.
Here is the render method (the issue is after the draw lights comments part):
public void render(final float alpha) {
viewport.apply();
spriteBatch.begin();
AnimatedTiledMapTile.updateAnimationBaseTime();
if (mapRenderer.getMap() != null) {
mapRenderer.setView(gameCamera);
for (TiledMapTileLayer layer : layersToRender) {
mapRenderer.renderTileLayer(layer);
}
}
// render game objects first because they are in the same texture atlas as the map so we avoid a texture binding --> better performance
for (final Entity entity : gameObjectsForRender) {
renderEntity(entity, alpha);
}
for (final Entity entity : charactersForRender) {
renderEntity(entity, alpha);
}
spriteBatch.end();
// draw lights
b2dCombinedMatrix.set(spriteBatch.getProjectionMatrix());
b2dCombinedMatrix.translate(0, RENDER_OFFSET_Y, 0);
rayHandler.setCombinedMatrix(b2dCombinedMatrix, gameCamera.position.x, gameCamera.position.y, gameCamera.viewportWidth, gameCamera.viewportHeight);
rayHandler.updateAndRender();
if (DEBUG) {
b2dRenderer.render(world, b2dCombinedMatrix);
Gdx.app.debug(TAG, "Last number of render calls: " + spriteBatch.renderCalls);
}
}
And this is the resize method which moves the viewport up by 4 world units:
public void resize(final int width, final int height) {
viewport.update(width, height, false);
// offset viewport by y-axis (get distance from viewport to viewport with offset)
renderOffsetVector.set(gameCamera.position.x - gameCamera.viewportWidth * 0.5f, RENDER_OFFSET_Y + gameCamera.position.y - gameCamera.viewportHeight * 0.5f, 0);
gameCamera.project(renderOffsetVector, viewport.getScreenX(), viewport.getScreenY(), viewport.getScreenWidth(), viewport.getScreenHeight());
viewport.setScreenY((int) renderOffsetVector.y);
}
After hours of fiddling around with the matrix I finally got it to work but there is actually a very easy solution to my problem :D
Basically the render method of the rayhandler was messing up my matrix calculations all the time and the reason is that I did not tell it to use a custom viewport.
So adjusting the resize method to this
public void resize(final int width, final int height) {
viewport.update(width, height, false);
// offset viewport by y-axis (get distance from viewport to viewport with offset)
renderOffsetVector.set(gameCamera.position.x - gameCamera.viewportWidth * 0.5f, RENDER_OFFSET_Y + gameCamera.position.y - gameCamera.viewportHeight * 0.5f, 0);
gameCamera.project(renderOffsetVector, viewport.getScreenX(), viewport.getScreenY(), viewport.getScreenWidth(), viewport.getScreenHeight());
viewport.setScreenY((int) renderOffsetVector.y);
rayHandler.useCustomViewport(viewport.getScreenX(), viewport.getScreenY(), viewport.getScreenWidth(), viewport.getScreenHeight());
}
and simplifying the render method to
// draw lights
rayHandler.setCombinedMatrix(gameCamera);
rayHandler.updateAndRender();
if (DEBUG) {
b2dRenderer.render(world, b2dCombinedMatrix);
Gdx.app.debug(TAG, "Last number of render calls: " + spriteBatch.renderCalls);
}
solved my problem.
Maybe I am stupid but I did not find useCustomViewport method in any of the documentations.
Anyway , solved!
I am trying to rotate an OBJ from maya around an axis in Maya. It works just fine with a sphere, but with my own object - it is following an orbit. Maybe I don't understand the shape(parameters).
PShape s;
float theta = 0;
void setup() {
size(500, 500, P3D);
shapeMode(CENTER);
s = loadShape("obj2.obj");
}
void draw() {
background(32);
lights();
float z = 0;
pushMatrix();
translate(0,height*1/4);
rotateY(theta);
theta += .01;
scale(4.0);
box(100);
//shape(s, 0,0);
popMatrix();
}
here is the object: https://drive.google.com/open?id=0B3ddDpsAjuqPYUR6RHd0OFBfVU0
Take out this line of code:
shapeMode(CENTER);
For some reason, this line of code is causing the offset you're seeing. I'm not sure exactly why this causes the offset, but getting rid of it seems to fix your problem.
There is a good simple example of loading and displaying a 3d shape in the examples that come with the Processing editor. Just go to File > Examples and then go to Basics > Shape > LoadDisplayOBJ.
Kevin is right, part of the problem is shapeMode(CENTER).
Additionally you may want to double check if the mesh is centered in your editor.
I've imported your mesh in Blender, and although there is a difference in scale, the origin of your geometry was not at 0,0,0
Here's a tweaked version of your .obj and .mtl exported from Blender after manually translating the mesh so it's closer to the center:
PShape s;
float theta = 0;
void setup() {
size(500, 500, P3D);
s = loadShape("coral.obj");
}
void draw() {
background(32);
lights();
float z = 0;
pushMatrix();
translate(width * .5,height* .5);
rotateY(theta);
theta += .01;
scale(50.0);
shape(s, 0,0);
popMatrix();
}
Additionally you can manually compute the mesh bounding box and centroid to orbit around that position, or look a library that provides this functionality.
I'm working on a digital vinyl record player project, and am currently stuck on the vinyl part. I have found many tutorials on how to rotate an image using rotate() and translate(), but all those tutorials take for granted that the image is at the center of the window. My vinyl is not. Help please?
The code in your comment should work:
void draw() {
background(0);
counter++;
translate(width/2-img.width/2, height/2-img.height/2);
rotate(counter*TWO_PI/360);
translate(-img.width/2, -img.height/2);
image(img,0,0);
}
To make it easier to handle even more than one image rotating from its centre it might be worth isolating the image's coordinate system using pushMatrix()/popMatrix() (see the 2D Transformations Processing tutorial for more details):
void draw() {
background(0);
//draw everything from the centre
translate(width/2,height/2);
counter++;
//isolate image coordinate system
pushMatrix();
//move to centre of image
translate(img.width/2, img.height/2);
//rotate from centre
rotate(counter*TWO_PI/360);
//translate back to corner
translate(-img.width/2, -img.height/2);
//render image
image(img,0,0);
//exit image coordinate system, return to Processing's global coordinates
popMatrix();
}
I would like to rotate a sprite on the scene by pressing the left or right arrows keys (think of the spaceship in Asteroids).
I have placed the sprite in question on the scene and created a script, but am not really certain of where to go from there.
My current script looks like this:
using UnityEngine;
using System.Collections;
public class RotateLeftRight : MonoBehaviour {
public float speed = 1.0f;
public string axisName = "Horizontal";
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if(Input.GetKeyDown(KeyCode.LeftArrow)) {
// left
transform.Rotate(-1.0f, 0.0f, 0.0f); // does nothing, just a bad guess
}
if(Input.GetKeyDown(KeyCode.RightArrow)) {
// right
transform.Rotate(1.0f, 0.0f, 0.0f); // does nothing, just a bad guess
}
}
}
I just coded the above without any knowledge of what would happen (and, hardly surprising, nothing appears to happen at all).
Any advice on how to rotate the sprite and control the speed of the rotation would be greatly appreciated.
I'm not able to try it with Unity right now, but my guess is that it is either rotating just 1º, so you are not able to notice it, or rotating 360º, and so it really stays the same.
Try to break down your problem:
Instead of transform.Rotate try transform.Translate(20f, 20f, 20f) just to make sure it is recognizing the input;
Use a different value instead of 1.0f, such as 0.1f and 30.0f (I think 30.0f would be 30º, but I'm not sure);
Try changing the rotation on the other axes y and z instead of x;
Use the alternative definition Rotate(Vector3 axis, float angle).
Hope it helps!
#Sailing Judo, here's the best answer if you want to rotate it like a wheel. Try observe again to your code and instead of putting/changing the X-axis as parameter, put your value at the Z-axis instead. Changing x or y-axis in a circular rotation ended up like flipping coins. Observe and try again.
if(Input.GetKey(KeyCode.LeftArrow)) {
// Clockwise
transform.Rotate(0, 0, -3.0f); // --> Instead of "transform.Rotate(-1.0f, 0.0f, 0.0f);"
}
if(Input.GetKey(KeyCode.RightArrow)) {
// Counter-clockwise
transform.Rotate(0, 0, 3.0f); // --> Instead of transform.Rotate(1.0f, 0.0f, 0.0f);
}