PGraphics camera positioning only happens in the next frame - rendering

From this Github issue:
Computer specs: Mac OS Sierra 10.12.3, Processing 3.2.3
When using dynamic values in a Processing PGraphics camera, these only get applied in the next frame. I have not been able to save the current frame to a file with this offset not being a problem. Is this the expected behavior?
Consider the code below:
It will show a rotating cube, a red rotating square, and the current frame count.
There is an x_up global variable that controls that value in the camera (default 0.0).
If the frameCount % 90 == 0:
changes the x_up (from 0.0 to 1.0).
changes the fill to transparent blue.
saves a file "output/#####_" + x_up + "_.png" (e.g: 00090_1.0_.png)
If the frameCount % 90 == 1:
saves another file with same convention, no fill, no x_up change (e.g: 00091_0.0_.png)
PGraphics pg;
PMatrix mat_scene;
float x_up;
void setup() {
size(600, 600, P3D);
pg = createGraphics(width, height, P3D);
mat_scene = getMatrix();
}
void draw() {
pg.beginDraw();
pg.hint(DISABLE_DEPTH_TEST);
pg.background(200);
pg.noFill();
// change stuff if frame % 90
if (frameCount % 90 == 0) {
x_up = 1.0;
pg.fill(0, 0, 255, 10);
} else {
x_up = 0.0;
}
// the red rect
pg.pushMatrix();
pg.setMatrix(mat_scene);
pg.stroke(255, 0, 0);
pg.rectMode(CENTER);
pg.translate(width * .5, height * .5, -600);
pg.rotateZ(radians(float(frameCount)));
pg.rect(0, 0, 600, 600);
pg.popMatrix();
// the cube
pg.pushMatrix();
pg.stroke(128);
pg.translate(10, 100, -200);
pg.rotateZ(radians(float(frameCount)));
pg.box(300);
pg.popMatrix();
// the camera
pg.beginCamera();
pg.camera(width, height, -height, 0, 0, 0, x_up, 0.0, 1.0);
pg.endCamera();
// the frame counter
pg.pushMatrix();
pg.fill(255);
pg.setMatrix(mat_scene);
pg.textSize(20);
pg.text(frameCount, 20, 30);
pg.popMatrix();
pg.endDraw();
image(pg, 0, 0);
if (frameCount > 10 && frameCount % 90 == 0) {
saveFrame("output/#####_" + x_up + "_.png");
}
if (frameCount > 10 && frameCount % 90 == 1) {
saveFrame("output/#####_" + x_up + "_.png");
}
}
You can see the “blip” happen every 90 frames. If you look at the output folder, you will see something like this in frame 90:
and something like this in frame 91:
Notice that you can tell it is only the camera because both attributes (blue and camera x_up) are changed in frame 90 but only frame 91 shows the change in camera. Frame 90 correctly shows the blue fill in both boxes. This happens even if I set the frame rate to 1. It also happens if I use pg.save instead of saveFrame.
Is this a bug? I might be missing something obvious, but I'm not an expert in 3D transformations or cameras.

You're calling the camera() function after you've done all your drawing. So each frame, you do this:
Move the objects in your scene and take a picture.
Now move the camera.
So on frame 90, you draw your scene, then move the camera. So on frame 91, the camera is using the position from the last frame.
To fix this, just move your call to camera() to before you draw everything (but after you set the x_up variable.

Related

Kinect V2 how to extract player/user from background with original resolution 1920x1080

In Kinect V2 as we know depth and color resolutions are different. With mapping API available in SDK it is easy to get color value from color frame and put in on depth frame as shown by many posts on the internet. That will give final image of the size 512x414.
But I wanted to extract player/user in original color frame so that final image is of resolution 1920x1080.
I can think of using the mapping API and mark color frame with User/PLayer pixel. Then apply some heuristic and expose RGB value neighboring pixels and complete the User/Player image.
Does any one has better suggestion on how best we can do that ?
Hi instead of mapping from depth to color try mapping your color frame to depthspace and set your output Image's size equal color Image's size.
coordinateMapper.MapColorFrameToDepthSpace(depthData, depthPoints);
for (int colorIndex = 0; colorIndex < depthPoints.Length; ++colorIndex)
{
DepthSpacePoint depthPoint = depthPoints[colorIndex];
if (!float.IsNegativeInfinity(depthPoint.X) && !float.IsNegativeInfinity(depthPoint.Y))
{
int depthX = (int)(depthPoint.X + 0.5f);
int depthY = (int)(depthPoint.Y + 0.5f);
if ((depthX >= 0) && (depthX < depthWidth) && (depthY >= 0) && (depthY < depthHeight))
{
int depthIndex = (depthY * depthWidth) + depthX;
byte player = bodyData[depthIndex];
if (player != 0xff)
{
int sourceIndex = colorIndex * 4;
OutImage[sourceIndex] = _colorData[sourceIndex++];
OutImage[sourceIndex] = _colorData[sourceIndex++];
OutImage[sourceIndex] = _colorData[sourceIndex++];
OutImage[sourceIndex] = 0xff;
}
}
}
}
Init for output Image:
OutImage= new byte[colorWidth*colorHeight*4]; //1920x1080x4

Android - Trying to gradually fill a circle bottom to top

I'm trying to fill a round circle (transparent other than the outline of the circle) in an ImageView.
I have the code working:
public void setPercentage(int p) {
if (this.percentage != p ) {
this.percentage = p;
this.invalidate();
}
}
#Override public void onDraw(Canvas canvas) {
Canvas tempCanvas;
Paint paint;
Bitmap bmCircle = null;
if (this.getWidth() == 0 || this.getHeight() == 0 )
return ; // nothing to do
mergedLayersBitmap = Bitmap.createBitmap(this.getWidth(), this.getHeight(), Bitmap.Config.ARGB_8888);
tempCanvas = new Canvas(mergedLayersBitmap);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setFilterBitmap(false);
bmCircle = drawCircle(this.getWidth(), this.getHeight());
tempCanvas.drawBitmap(bmCircle, 0, 0, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
tempCanvas.clipRect(0,0, this.getWidth(), (int) FloatMath.floor(this.getHeight() - this.getHeight() * ( percentage/100)));
tempCanvas.drawColor(0xFF660000, PorterDuff.Mode.CLEAR);
canvas.drawBitmap(mergedLayersBitmap, null, new RectF(0,0, this.getWidth(), this.getHeight()), new Paint());
canvas.drawBitmap(mergedLayersBitmap, 0, 0, new Paint());
}
static Bitmap drawCircle(int w, int h) {
Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bm);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(drawColor);
c.drawOval(new RectF(0, 0, w, h), p);
return bm;
}
It kind of works. However, I have two issues: I run out of memory quickly and the GC goes crazy. How can I utilize the least amount of memory for this operation?
I know I Shouldn't be instantiating objects in onDraw, however I'm not sure where to draw then. Thank you.
pseudo would look something like this.
for each pixel inside CircleBitmap {
if (pixel.y is < Yboundary && pixelIsInCircle(pixel.x, pixel.y)) {
CircleBitmap .setPixel(x, y, Color.rgb(45, 127, 0));
}
}
that may be slow, but it would work, and the smaller the circle the faster it would go.
just know the basics, bitmap width and height, for example 256x256, the circles radius, and to make things easy make the circle centered at 128,128. then as you go pixel by pixel, check the pixels X and Y to see if it falls inside the circle, and below the Y limit line.
then just use:
CircleBitmap .setPixel(x, y, Color.rgb(45, 127, 0));
edit: to speed things up, don't even bother looking at the pixels above the Y limit.
in case if you want to see another solution (perhaps cleaner), look at this link, filling a circle gradually from bottom to top android

Rotating camera around the X-axis (three.js)

I am trying to rotate the camera around to X-axis of the scene.
At this point my code is like this:
rotation += 0.05;
camera.position.y = Math.sin(rotation) * 500;
camera.position.z = Math.cos(rotation) * 500;
This makes the camera move around but during the rotation something weird happens and either the camera flips, or it skips some part of the imaginary circle it's following.
You have only provided a snippet of code, so I have to make some assumptions about what you are doing.
This code:
rotation += 0.05;
camera.position.x = 0;
camera.position.y = Math.sin(rotation) * 500;
camera.position.z = Math.cos(rotation) * 500;
camera.lookAt( scene.position ); // the origin
will cause the "flipping" you refer to because the camera is trying to remain "right side up", and it will quickly change orientation as it passes over the "north pole."
If you offset the camera's x-coordinate like so,
camera.position.x = 200;
the camera behavior will appear more natural to you.
Three.js tries to keep the camera facing up. When you pass 0 along the z-axis, it'll "fix" the camera's rotation. You can just check and reset the camera's angle manually.
camera.lookAt( scene.position ); // the origin
if (camera.position.z < 0) {
camera.rotation.z = 0;
}
I'm sure this is not the best solution, but if anyone else runs across this question while playing with three.js (like I just did), it'll give one step further.
This works for me, I hope it helps.
Rotating around X-Axis:
var x_axis = new THREE.Vector3( 1, 0, 0 );
var quaternion = new THREE.Quaternion;
camera.position.applyQuaternion(quaternion.setFromAxisAngle(x_axis, rotation_speed));
camera.up.applyQuaternion(quaternion.setFromAxisAngle(x_axis, rotation_speed));
Rotating around Y-Axis:
var y_axis = new THREE.Vector3( 0, 1, 0 );
camera.position.applyQuaternion(quaternion.setFromAxisAngle(y_axis, angle));
Rotating around Z-Axis:
var z_axis = new THREE.Vector3( 0, 0, 1 );
camera.up.applyQuaternion(quaternion.setFromAxisAngle(z_axis, angle));
I wanted to move my camera to a new location while having the camera look at a particular object, and this is what I came up with [make sure to load tween.js]:
/**
* Helper to move camera
* #param loc Vec3 - where to move the camera; has x, y, z attrs
* #param lookAt Vec3 - where the camera should look; has x, y, z attrs
* #param duration int - duration of transition in ms
**/
function flyTo(loc, lookAt, duration) {
// Use initial camera quaternion as the slerp starting point
var startQuaternion = camera.quaternion.clone();
// Use dummy camera focused on target as the slerp ending point
var dummyCamera = camera.clone();
dummyCamera.position.set(loc.x, loc.y, loc.z);
// set the dummy camera quaternion
var rotObjectMatrix = new THREE.Matrix4();
rotObjectMatrix.makeRotationFromQuaternion(startQuaternion);
dummyCamera.quaternion.setFromRotationMatrix(rotObjectMatrix);
dummyCamera.up.set(camera)
console.log(camera.quaternion, dummyCamera.quaternion);
// create dummy controls to avoid mutating main controls
var dummyControls = new THREE.TrackballControls(dummyCamera);
dummyControls.target.set(loc.x, loc.y, loc.z);
dummyControls.update();
// Animate between the start and end quaternions
new TWEEN.Tween(camera.position)
.to(loc, duration)
.onUpdate(function(timestamp) {
// Slerp the camera quaternion for smooth transition.
// `timestamp` is the eased time value from the tween.
THREE.Quaternion.slerp(startQuaternion, dummyCamera.quaternion, camera.quaternion, timestamp);
camera.lookAt(lookAt);
})
.onComplete(function() {
controls.target = new THREE.Vector3(scene.children[1].position-0.001);
camera.lookAt(lookAt);
}).start();
}
Example usage:
var pos = {
x: -4.3,
y: 1.7,
z: 7.3,
};
var lookAt = scene.children[1].position;
flyTo(pos, lookAt, 60000);
Then in your update()/render() function, call TWEEN.update();
Full example

JavaFX 2 Slider for circular knob and snap to value

based on the volume knob from this example, http://fxexperience.com/2012/01/fun-javafx-2-0-audio-player/
How would you make a volume knob that snaps to particular angle value, every 15 or 30 degree for example ? Thanks for any hint.
What i did is redefine rotateKnob in subclass and set the angle in this manner for the slider to snap at values 180, 120, 60, 0, -180, -160, -120, -60 :
Slider s = getSkinnable();
double zeroOneValue = (s.getValue() - s.getMin()) / (s.getMax() - s.getMin());
double angle = minAngle + ((maxAngle - minAngle) * zeroOneValue);
int angleMod = (int) (angle % 60);
double val;
if (angleMod == 0) {
val = (int) angle;
} else if (angleMod > (60 / 2)) {
val = (int) angle - angleMod;
} else {
val = (int) angle - angleMod + 60;
}
You don't need to do anything special. Just make use of the "snapToTicks" property. In the main class, after the volume knob is defined, put this code:
volumeKnob.setMinorTickCount(0);
volumeKnob.setMajorTickUnit(1.0/14.0);
volumeKnob.snapToTicksProperty().set(true);
The numbers here are based on the fact that there are 14 "dots" around the volume knob. This code will make sure that you can only set the volume to one of those dots.
#Enwired has a good answer. you need a different graphical resource to change the number of dots. but that is not a part of what makes the angle between each tick around the rotary control.
just as he divided the circle into 1/14's, you can choose to divide it into 60 degree slices by 60.0/360.0 or 1.0/6.0.

Raphael -- How to fit the paper size to the browser's window size?

I want to change the paper(objects base) size of Raphael to fit the window resizing. [ using Firefox_13.0, Raphael_2.1.0, WindowsXP ]
If it is available, I would like to fit full-screen-mode.
==================================================
(steps)
I created the paper : paper = Raphael(0, 50, 800, 600); // initial width and height are 800 and 600.
I placed objects on the paper.
The window size of browser is checked by windowW = window.innerWidth and winnowH = window.innerHeight (on Firefox).
Scaling value is calculated by sv = windowW/800;
And scaling the paper by paper.scale(sv, sv);
==================================================
(the script)
window.onload = function () {
paper = Raphael(0, 50, 800, 600);
var background = paper.rect(0, 0, 800, 600).attr({fill:'#669999'});
// placing the objects
var circle = ...;
var rect = ...;
var ellipse = ...;
winowW = window.innerWidth;
winowH = window.innerHeight;
sv = winowW/800.
paper.scale(sv, sv);
}
==================================================
(result)
Though circle.scale(sv), rect.scale(sv, sv) and ellipse.scale(sv, sv) are valid, paper.scale(sv, sv) and background.scale(sv, sv) are not.
Why this case is happen ? I can get the window size by window.onresize = function() {...} on real-time. If there are better methods, please tell me.
Thanks,
I've succeeded by following two points:
1) "paper" itself is not manipulative object. I think we should look it as billboard.
2) use st = paper.set() and put the objects(circle, rect, ...) in it. And use st.scale(sv, sv, 0, 0);
* third and fourth parameter (0, 0) are very impotent.
(caution)
Serial resizing operation is not good for the function "scale()". Because each of resizing coefficient is piled as the
power of a number. So when one have done 1.1 times resizing operation 5 times, the scale will be 1.1^5.
Use setViewBox()
It should do the work
http://raphaeljs.com/reference.html#Paper.setViewBox