How to increase size of mesh? - three.js

Here's a demo of a rotating paper cup
https://jsfiddle.net/o5cd8g0h/
I want to increase the size of image in the cup, tried this
logoMesh.scale.x = 1.5;
logoMesh.scale.y = 1.5;
logoMesh.scale.z = 1.5;
logoMesh.position.set(0,-0.6,-0.6);
But the result is not what i expect https://jsfiddle.net/nL2spe5d/
Image gets placed incorrectly
How to increase size of logoMesh?

As I get it, it depends on logoFaceArray. In simple words, it contains indices of faces. 6 faces on width, 8 faces on height.
Thus, if you want to make your logo mesh bigger, then you have to change this array of indices.
var logoFaceArray = [];
var multiplier = 2;
for(var lx = 0; lx < 6 * multiplier; lx++){
for(var ly = 0; ly < 8 * multiplier; ly++){
var index = 24 * lx + ly;
logoFaceArray.push(index);
}
}
Here you can play around with the multiplier variable, or you can leave it equal to 1, but change the limits of lx and ly, but remember that they (lx, ly) have to be even numbers, else you'll get a saw edge at the bottom of the logo.
jsfiddle example

Related

Why is the floor in my raycaster seemingly "misaligned"?

I have been working on a doom/wolfenstein style raycaster for a while now. I implemented the "floor raycasting" to the best of my ability, roughly following a well known raycaster tutorial. It almost works, but the floor tiles seem slightly bigger than they should be, and they don't "stick", as in they don't seem to align properly and they slide slightly as the player moves/rotates. Additionally, the effect seems worsened as the FOV is increased. I cannot figure out where my floor casting is going wrong, so any help is appreciated.
Here is a (crappy) gif of the glitch happening
Here is the most relevant part of my code:
void render(PVector pos, float dir) {
ArrayList<FloatList> dists = new ArrayList<FloatList>();
for (int i = 0; i < numColumns; i++) {
float curDir = atan((i - (numColumns/2.0)) / projectionDistance) + dir;
// FloatList because it returns a few pieces of data
FloatList curHit = cast(pos, curDir);
// normalize distances with cos
curHit.set(0, curHit.get(0) * cos(curDir - dir));
dists.add(curHit);
}
screen.beginDraw();
screen.background(50);
screen.fill(0, 30, 100);
screen.noStroke();
screen.rect(0, 0, screen.width, screen.height/2);
screen.loadPixels();
PImage floor = textures.get(4);
// DRAW FLOOR
for (int y = screen.height/2 + 1; y < screen.height; y++) {
float rowDistance = 0.5 * projectionDistance / ((float)y - (float)rY/2);
// leftmost and rightmost (on screen) floor positions
PVector left = PVector.fromAngle(dir - fov/2).mult(rowDistance).add(p.pos);
PVector right = PVector.fromAngle(dir + fov/2).mult(rowDistance).add(p.pos);
// current position on the floor
PVector curPos = left.copy();
PVector stepVec = right.sub(left).div(screen.width);
float b = constrain(map(rowDistance, 0, maxDist, 1, 0), 0, 1);
for (int x = 0; x < screen.width; x++) {
color sample = floor.get(floor((curPos.x - floor(curPos.x)) * floor.width), floor((curPos.y - floor(curPos.y)) * floor.height));
screen.pixels[x + y*screen.width] = color(red(sample) * b, green(sample) * b, blue(sample) * b);
curPos.add(stepVec);
}
}
updatePixels();
}
If anyone wants to look at the full code or has any questions, ask away.
Ok, I seem to have found a "solution". I will be the first to admit that I do not understand why it works, but it does work. As per my comment above, I noticed that my rowDistance variable was off, which caused all of the problems. In desperation, I changed the FOV and then hardcoded the rowDistance until things looked right. I plotted the ratio between the projectionDistance and the numerator of the rowDistance. I noticed that it neatly conformed to a scaled cos function. So after some simplification, here is the formula I came up with:
float rowDistance = (rX / (4*sin(fov/2))) / ((float)y - (float)rY/2);
where rX is the width of the screen in pixels.
If anyone has an intuitive explanation as to why this formula makes sense, PLEASE enlighten me. I hope this helps anyone else who may have this problem.

How is this ray casting algorithm flawed?

Matrix operations performed on the GPU can be pretty hard to debug because GPU operations don't really allow for console logs.
I've written one designed for a real time 2D rendering engine based on a very simple form of I guess what could be called ray casting and am having trouble figuring out what's wrong with it (it's outputting [0,0,0,255,0,0,0,255,...] instead of populating colors).
this.thread.x is the index of the current unit (color channel) in the matrix being operated on.
scene is a buffer made up of 6-unit clumps, each value containing, in order:
The type of entity, always 1 for "sprite" in this case.
The sprite ID, corresponding the the index in this.constants.textures containing the buffer for the entity's sprite.
X offset, the left edge of the sprite
Y offset, the top edge of the sprite
width of the sprite
height of the sprite
bufferWidth is the width of the render area multiplied by 4 channels.
this.constants.textures is an array containing buffers of each sprite which the sprite IDs from the scene refer to.
Note: For those curious, this is being done with GPU.js, a JavaScript lib that converts a JS func into GLSL code to be run via WebGL.
function(scene, sceneLength, bufferWidth) {
var channel = this.thread.x % 4;
if (channel === 3) {
return 255;
}
var x = this.thread.x % bufferWidth;
var y = Math.floor(this.thread.x / bufferWidth);
for (let i1 = 0; i1 < sceneLength; i1 += 6) {
var id = scene[i1 + 1];
var x1 = scene[i1 + 2];
var y1 = scene[i1 + 3];
var w1 = scene[i1 + 4];
var h1 = scene[i1 + 5];
var r1 = scene[i1 + 6];
var offsetX1 = x1 - x;
if (offsetX1 > 0 && offsetX1 < w1) {
var offsetY1 = y1 - y;
if (offsetY1 > 0 && offsetY1 < h1) {
var c1 = offsetY1 * w1 * 4 + offsetX1 * 4;
var c1R = c1 - (c1 % 4);
var c1A = c1R + 3;
if (this.constants.textures[id][c1A] != 0) {
return this.constants.textures[id][c1];
}
}
}
}
return 0;
}
Explanation for the concept I'm trying to implement:
With a matrix operation, when you want to draw a sprite if you were to perform a pass on the entire render area, you'd be doing far more work than necessary. If you break the rendering area down into chunks and only update the sections involved in the sprite being drawn, that would be a fairly decent way to do it. It would certainly be good enough for real time game rendering. This would be a multi-pass approach, where sprites are rendered one at a time.
Alternatively, for what seems to me to be the most optimal approach possible, instead of that, we can use a single-pass approach that performs a single matrix operation for the entire rendering area, evaluating for each color channel what should be there based on doing a very basic form of collision detection with each sprite in the scene and the relevant pixel in that sprite.
You're calculating your sprite offsets backwards, the calculations should be:
var offsetX1 = x - x1;
and
var offsetY1 = y - y1;
The offsets should increase as x and y increase (assuming the sprite co-ordinates have the same co-ordinate system as the screen co-ordinates), so you shouldn't be subtracting x and y.

Processing - creating circles from current pixels

I'm using processing, and I'm trying to create a circle from the pixels i have on my display.
I managed to pull the pixels on screen and create a growing circle from them.
However i'm looking for something much more sophisticated, I want to make it seem as if the pixels on the display are moving from their current location and forming a turning circle or something like this.
This is what i have for now:
int c = 0;
int radius = 30;
allPixels = removeBlackP();
void draw {
loadPixels();
for (int alpha = 0; alpha < 360; alpha++)
{
float xf = 350 + radius*cos(alpha);
float yf = 350 + radius*sin(alpha);
int x = (int) xf;
int y = (int) yf;
if (radius > 200) {radius =30;break;}
if (c> allPixels.length) {c= 0;}
pixels[y*700 +x] = allPixels[c];
updatePixels();
}
radius++;
c++;
}
the function removeBlackP return an array with all the pixels except for the black ones.
This code works for me. There is an issue that the circle only has the numbers as int so it seems like some pixels inside the circle won't fill, i can live with that. I'm looking for something a bit more complex like I explained.
Thanks!
Fill all pixels of scanlines belonging to the circle. Using this approach, you will paint all places inside the circle. For every line calculate start coordinate (end one is symmetric). Pseudocode:
for y = center_y - radius; y <= center_y + radius; y++
dx = Sqrt(radius * radius - y * y)
for x = center_x - dx; x <= center_x + dx; x++
fill a[y, x]
When you find places for all pixels, you can make correlation between initial pixels places and calculated ones and move them step-by-step.
For example, if initial coordinates relative to center point for k-th pixel are (x0, y0) and final coordinates are (x1,y1), and you want to make M steps, moving pixel by spiral, calculate intermediate coordinates:
calc values once:
r0 = Sqrt(x0*x0 + y0*y0) //Math.Hypot if available
r1 = Sqrt(x1*x1 + y1*y1)
fi0 = Math.Atan2(y0, x0)
fi1 = Math.Atan2(y1, x1)
if fi1 < fi0 then
fi1 = fi1 + 2 * Pi;
for i = 1; i <=M ; i++
x = (r0 + i / M * (r1 - r0)) * Cos(fi0 + i / M * (fi1 - fi0))
y = (r0 + i / M * (r1 - r0)) * Sin(fi0 + i / M * (fi1 - fi0))
shift by center coordinates
The way you go about drawing circles in Processing looks a little convoluted.
The simplest way is to use the ellipse() function, no pixels involved though:
If you do need to draw an ellipse and use pixels, you can make use of PGraphics which is similar to using a separate buffer/"layer" to draw into using Processing drawing commands but it also has pixels[] you can access.
Let's say you want to draw a low-res pixel circle circle, you can create a small PGraphics, disable smoothing, draw the circle, then render the circle at a higher resolution. The only catch is these drawing commands must be placed within beginDraw()/endDraw() calls:
PGraphics buffer;
void setup(){
//disable sketch's aliasing
noSmooth();
buffer = createGraphics(25,25);
buffer.beginDraw();
//disable buffer's aliasing
buffer.noSmooth();
buffer.noFill();
buffer.stroke(255);
buffer.endDraw();
}
void draw(){
background(255);
//draw small circle
float circleSize = map(sin(frameCount * .01),-1.0,1.0,0.0,20.0);
buffer.beginDraw();
buffer.background(0);
buffer.ellipse(buffer.width / 2,buffer.height / 2, circleSize,circleSize);
buffer.endDraw();
//render small circle at higher resolution (blocky - no aliasing)
image(buffer,0,0,width,height);
}
If you want to manually draw a circle using pixels[] you are on the right using the polar to cartesian conversion formula (x = cos(angle) * radius, y = sin(angle) * radius).Even though it's focusing on drawing a radial gradient, you can find an example of drawing a circle(a lot actually) using pixels in this answer

Calculate the vertex while creating terrain from heightmap using ThreeJs

I'm reading "create terrain from heightmap" example from ThreeJs Cookbook
This example load GrandCanyon: http://lh5.ggpht.com/_-B0hFoGrn-w/SvHiYk39yAI/AAAAAAAABOQ/6IGZwifUYGA/GrandCanyon.png
And create a 3D terrain: http://www.smartjava.org/tjscb/02-geometries-meshes/02.06-create-terrain-from-heightmap.html
There are some code pieces I can not understand:
// draw on canvas
ctx.drawImage(img, 0, 0);
var pixel = ctx.getImageData(0, 0, width, depth);
var geom = new THREE.Geometry;
var output = [];
for (var x = 0; x < depth; x++) {
for (var z = 0; z < width; z++) {
// get pixel
// since we're grayscale, we only need one element
var yValue = pixel.data[z * 4 + (depth * x * 4)] / heightOffset;
var vertex = new THREE.Vector3(x * spacingX, yValue, z * spacingZ);
geom.vertices.push(vertex);
}
}
why is yValue calculated with that value ? why don't we use var yValue = pixel.data[z * 4 + (depth * x )] or something like that ?
And do we really need spacingX and spacingZ ?
Source code is here: https://github.com/josdirksen/threejs-cookbook/blob/master/02-geometries-meshes/02.06-create-terrain-from-heightmap.html
Could you please help me ?
Thank you very much!
You don't NEED spacingX and spacingZ, no. You could adjust scale in other ways, like applying a scale matrix to the entire THREE.Geometry after you've populated the vertices. Up to you, really.
As fort the yValue, the indexing is to adjust for the way the data for the texture is laid out. There are four channels, usually RGBA, but in this case we only need one of them as a height.

how to account for linewidth in drawing lines within a bounding box

I am drawing a set of evenly spaced horizontal lines within the entirety of a bounding box.
The problem I am having is that the lines (when larger than 1px) get drawn beyond the top and bottom edges of my bounds. Half on each side of the top and bottom is missing, to be precise.
Here is some pseudo code that attempts a fix for this, but it didn't work. It should describe what I am trying to do:
var halfline = linewidth / 2.;
var maxheight = boxsize.height - halfline;
var minheight = halfline;
//draw h lines
for(i = 0; i < maxlines; i++)
{
var xloc = 0;
var xfrac = i / maxlines - 1;
var yloc = (xfrac * boxsize.height) + minheight;
move_to(xloc, yloc);
line_to(boxsize.width, yloc);
}
Please keep in mind that the lang is not important here, just the idea of how to offset and scale the lines (that are drawn within the for loop) properly.
Thanks for any tips... It's safe to assume the following:
the line width is in pixels
the coordinate system is pixel-based, from (0,0) to (n,n)
Your question is a little unclear, but I think this might help:
var availablespace = boxsize.height - linewidth;
...
var yloc = (xfrac * availablespace) + minheight;

Resources