Changing plane geometry vectors in ThreeJS leaving behind connecting plane - reactjs

// this method will be called once per frame
(plane as any).tick = (delta: number) => {
let pos = geometry.getAttribute("position");
let pa = pos.array as Float32Array;
let vectorArr : THREE.Vector3[] = [];
for (let i = 0; i < pa.length; i += 3) {
vectorArr.push(new THREE.Vector3(pa[i], pa[i + 1], pa[i + 2]));
}
for (let vect of vectorArr) {
vect.x -= 5 * delta;
if (vect.x < - 40) {
vect.x = 40;
removeArr.push(vect);
}
}
vectorArr.map((vect, i) => {
pa[3 * i] = vect.x;
pa[3 * i + 1] = vect.y;
pa[3 * i + 2] = vect.z;
});
pos.needsUpdate = true;
}
The above code is used for modifying the plane, I'm basically just trying to reset the vectors that are past x=-40, but that's leaving behind some sort of 'connecting plane' between the plane. Image below an example, the material is double sided(but changing it still leaves behind the weird connecting plane).
What it looks like normally, without the vector.x -= 5 * delta below.
I'm basically just trying to create an infinite scrolling landscape, so if you have a good way to do this in ThreeJS apart from my code, please let me know!

Related

How can I properly implement zero cross triggering for digital oscilloscope in C?

So I'm doing a simple oscilloscope in C. It reads audio data from the output buffer (and drops buffer write counter when called so the buffer is refreshed). I tried making simple zero-cross triggering since most of the time users will see simple (sine, pulse, saw, triangle) waves but the best result I got with the code below is a wave that jumps back and forth for half of its cycle. What is wrong?
Signal that is fed in goes from -32768 to 32767 so zero is where it should be.
If you didn't understand what I meant you can see the video: click
Upd: Removed the code unrelated to triggering so all function may be understood easier.
extern Mused mused;
void update_oscillscope_view(GfxDomain *dest, const SDL_Rect* area)
{
if (mused.output_buffer_counter >= OSC_SIZE * 12) {
mused.output_buffer_counter = 0;
}
for (int x = 0; x < area->h * 0.5; x++) {
//drawing a black rect so bevel is hidden when it is under oscilloscope
gfx_line(domain,
area->x, area->y + 2 * x,
area->x + area->w - 1, area->y + 2 * x,
colors[COLOR_WAVETABLE_BACKGROUND]);
}
Sint32 sample, last_sample, scaled_sample;
for (int i = 0; i < 2048; i++) {
if (mused.output_buffer[i] < 0 && mused.output_buffer[i - 1] > 0) {
//here comes the part with triggering
if (i < OSC_SIZE * 2) {
for (int x = i; x < area->w + i; ++x) {
last_sample = scaled_sample;
sample = (mused.output_buffer[2 * x] + mused.output_buffer[2 * x + 1]) / 2;
if (sample > OSC_MAX_CLAMP) { sample = OSC_MAX_CLAMP; }
if (sample < -OSC_MAX_CLAMP) { sample = -OSC_MAX_CLAMP; }
if (last_sample > OSC_MAX_CLAMP) { last_sample = OSC_MAX_CLAMP; }
if (last_sample < -OSC_MAX_CLAMP) { last_sample = -OSC_MAX_CLAMP; }
scaled_sample = (sample * OSC_SIZE) / 32768;
if(x != i) {
gfx_line(domain,
area->x + x - i - 1, area->h / 2 + area->y + last_sample,
area->x + x - i, area->h / 2 + area->y + scaled_sample,
colors[COLOR_WAVETABLE_SAMPLE]);
}
}
}
return;
}
}
}
During debugging, I simplified the code until it started working. Thanks Clifford.
I found a trigger index i (let's say it is array index 300). Modified it so that the oscilloscope was drawing lines from [(2 * i) + offset] to [(2 * i + 1) + offset], thus an incorrect picture was formed.
I used (2 * i), because I wanted long waves to fit into oscilloscope. I replaced it with drawing from [i + offset] to [i + 1 + offset] and that solved a problem.
Afterwards, I implemented "horizontal scale 0.5x properly.
The output waveform still jumps a little, but overall it holds it in place.

Draw an image from an array value p5.js

I am fairly new to p5.js, however I am trying to read a .txt file which contains the below text, and draw a picture depending on the value within the .txt file.
00000
20022
00222
22020
11111
I am currently stumped as to how to draw an image depending on the number in the array, as an example '1' would be grass. I have loaded the file in as a string using the following code: track = loadStrings("track1.txt");
I am trying to load it as a 5x5 'tile' if you will. Any help would be appreciated :)
I've used p5.Image to create a picture based on the pixels in the file.
This is a way of writing the code:
let track;
let colors;
let img;
function setup() {
createCanvas(100, 100);
track=loadStrings("track1.txt")
colors = [color(255,0,0),color(0,255,0),color(0,0,255)]
}
function draw() {
background(220);
img = createImage(track.length, track[0].length)
img.loadPixels();
for (let i = 0 ; i < track.length ; i++){
for (let j = 0 ; j < track.length ; j++){
img.set(i, j, colors[int(track[i][j])]);
}
}
img.updatePixels();
image(img, 50, 50);
}
Well you could probs split it up into arrays and also if you'd have some sort of seperator for colors, like: track1.txt: 10, 30, 255\n ... r, g, b\n .... Right now you would have to use the rgb rrrgggbbb
let colors = track.split("\n") // makes every new line into an array
for(let x = 0; x <= width; x ++) // "\n" = new line
for(let y = 0; y <= height; y ++){
let currentCol = []
for(let i = 0; i < 9; i += 3)
currentCol.push(
colors[x + y][0 + i] + // I'm really not sure about the: colors[x + y]...
colors[x + y][1 + i] +
colors[x + y][2 + i]
)
set(x, y, color(currentCol[0], currentCol[1], currentCol[2]))
}
I also made a function with a slightly different formula, which might work better, i am not sure though, but this is the actual formula to get from pixel array
function getColor(x, y, allColorsArr){
let _col = [] // current color, underscore not to accidentally clear your variable
for(let i = 0; i < 3; i ++)
_col.push(
allColorsArr[x + y * width][0 + i * 3] +
allColorsArr[x + y * width][1 + i * 3] +
allColorsArr[x + y * width][2 + i * 3]
)
return {
r: parseInt(_col[0], 10),
g: parseInt(_col[1], 10),
b: parseInt(_col[2], 10)
} // returning an object here just for the `.r`; `.g`; `.b`
} // you could do something like: let Colors = {red: 0, green: 1, blue: 2}
// col[Colors.red], col[Colors.green], col[Colors.blue] if you want
// example: let col = getColor(1, 0, track.split("\n"))
// example: stroke(col.r, col.g, col.b)
THERE IS MOST LIKELY IS A BETTER WAY TO DO THIS, but at least this works...

Action Script 3. Randomly moving items UP and DOWN from array

So I'm creating game similar like this: example
I have an array of items already added to 4 holes. I need to make that these items randomly moved up (+100px) and down(-100px).
I have added to all holes for 6 items:
for(var i:uint = 0; i < 6; i++)
{
holeArr[0].inside.addChild(itemsArr[4][i]);
holeArr[1].inside.addChild(itemsArr[5][i]);
holeArr[2].inside.addChild(itemsArr[6][i]);
holeArr[3].inside.addChild(itemsArr[7][i]);
}
How can I make them randomly move up (+100px) and down(-100px)? I started, but I don't know what to do next... Could you help me, please?
function randomSpawn() {
for(var i:uint = 0; i < 6; i++)
{
itemsArr[4][i].x += 100;
itemsArr[5][i].x += 100;
itemsArr[6][i].x += 100;
itemsArr[7][i].x += 100;
}
}
To move an item randomly up/down +-100 pixels:
var distance = Math.round(Math.random() * 2 - 1) * 100;
mySprite.y += distance;
To animate it with Tweenlite
var newPosY = mySprite.y;
newPosY += Math.round(Math.random() * 2 - 1) * 100;
TweenLite.to(mySprite,1,{y:newPosY});
The simplest way to select a random item from an array
var index = Math.round(Math.random * (myArray.length - 1));
var myRandomItem = myArray[index];

Get evenly spaced X, Y cords from a given size and required amount

I'm working in Actionscript 3, but this is pretty general.
I'd like to make a simple function that I can call, e.g. GiveCords(Width, Height, Num) that will take a width and height, map that out and using the Num variable place the given amount evenly across the space.
Say I give it a value of 500, 500, 1. I'd expect it to return an X, Y position of 250, 250.
But I'd like it to return an array of given points with X, Y.
So If I gave it 10 points, it would find the best position for them all to be of even distance apart from each other.
I'm guessing there is a simple formula for working this out, but I've searched a plenty and found nothing.
Cheers
If I understood correctly this should do the job:
var object:Object = {width: 500, height:500, num:10};
var points:Array = getCoordinates(object);
function getCoordinates(object:Object):Array {
var array:Array = new Array();
var widthMultiplier:Number = object.width / (object.num + 1);
var heightMultiplier:Number = object.height / (object.num + 1);
for (a = 1; a <= object.num; a++) {
var coordinates:Point = new Point();
coordinates.x = widthMultiplier * a;
coordinates.y = heightMultipler * a;
array.push(coordinates);
}
return array;
}
It takes the number of items and the total space, divides the total space by the number of items + 1 (to account for the space at the end of the last element) increment the objects each time.
Edit: In response to comments here is a version where you can state the number of rows you want your objects to spread across. If the number of rows does not divide the number of objects and return an integer then the function will return null. If you do not give it a rows paramater it assumes you want it across one row. Enjoy.
var object:Object = {width:500,height:500,num:10};
var points:Array = getCoordinates(object,2);
function getCoordinates(object:Object, rows:int = 1):Array
{
if ((object.num / rows) % 1)
{
return null;
}
else
{
var columns:int = object.num / rows;
var array:Array = new Array();
var widthMultiplier:Number = object.width / (columns + 1);
var heightMultiplier:Number = object.height / (rows + 1);
for (var a = 1; a <= rows; a++)
{
for (var b = 1; b <= columns; b++)
{
var coordinates:Point = new Point();
coordinates.x = widthMultiplier * b;
coordinates.y = heightMultiplier * a;
array.push(coordinates);
}
}
return array;
}
}

VsampFactor and HsampFactor in FJCore library

I've been using the FJCore library in a Silverlight project to help with some realtime image processing, and I'm trying to figure out how to get a tad more compression and performance out of the library. Now, as I understand it, the JPEG standard allows you to specify a chroma subsampling ratio (see http://en.wikipedia.org/wiki/Chroma_subsampling and http://en.wikipedia.org/wiki/Jpeg); and it appears that this is supposed to be implemented in the FJCore library using the HsampFactor and VsampFactor arrays:
public static readonly byte[] HsampFactor = { 1, 1, 1 };
public static readonly byte[] VsampFactor = { 1, 1, 1 };
However, I'm having a hard time figuring out how to use them. It looks to me like the current values are supposed to represent 4:4:4 subsampling (e.g., no subsampling at all), and that if I wanted to get 4:1:1 subsampling, the right values would be something like this:
public static readonly byte[] HsampFactor = { 2, 1, 1 };
public static readonly byte[] VsampFactor = { 2, 1, 1 };
At least, that's the way that other similar libraries use these values (for instance, see the example code here for libjpeg).
However, neither the above values of {2, 1, 1} nor any other set of values that I've tried besides {1, 1, 1} produce a legible image. Nor, in looking at the code, does it seem like that's the way it's written. But for the life of me, I can't figure out what the FJCore code is actually trying to do. It seems like it's just using the sample factors to repeat operations that it's already done -- i.e., if I didn't know better, I'd say that it was a bug. But this is a fairly established library, based on some fairly well established Java code, so I'd be surprised if that were the case.
Does anybody have any suggestions for how to use these values to get 4:2:2 or 4:1:1 chroma subsampling?
For what it's worth, here's the relevant code from the JpegEncoder class:
for (comp = 0; comp < _input.Image.ComponentCount; comp++)
{
Width = _input.BlockWidth[comp];
Height = _input.BlockHeight[comp];
inputArray = _input.Image.Raster[comp];
for (i = 0; i < _input.VsampFactor[comp]; i++)
{
for (j = 0; j < _input.HsampFactor[comp]; j++)
{
xblockoffset = j * 8;
yblockoffset = i * 8;
for (a = 0; a < 8; a++)
{
// set Y value. check bounds
int y = ypos + yblockoffset + a; if (y >= _height) break;
for (b = 0; b < 8; b++)
{
int x = xpos + xblockoffset + b; if (x >= _width) break;
dctArray1[a, b] = inputArray[x, y];
}
}
dctArray2 = _dct.FastFDCT(dctArray1);
dctArray3 = _dct.QuantizeBlock(dctArray2, FrameDefaults.QtableNumber[comp]);
_huf.HuffmanBlockEncoder(buffer, dctArray3, lastDCvalue[comp], FrameDefaults.DCtableNumber[comp], FrameDefaults.ACtableNumber[comp]);
lastDCvalue[comp] = dctArray3[0];
}
}
}
And notice that in the i & j loops, they're not controlling any kind of pixel skipping: if HsampFactor[0] is set to two, it's just grabbing two blocks instead of one.
I figured it out. I thought that by setting the sampling factors, you were telling the library to subsample the raster components itself. Turns out that when you set the sampling factors, you're actually telling the library the relative size of the raster components that you're providing. In other words, you need to do the chroma subsampling of the image yourself, before you ever submit it to the FJCore library for compression. Something like this is what it's looking for:
private byte[][,] GetSubsampledRaster()
{
byte[][,] raster = new byte[3][,];
raster[Y] = new byte[width / hSampleFactor[Y], height / vSampleFactor[Y]];
raster[Cb] = new byte[width / hSampleFactor[Cb], height / vSampleFactor[Cb]];
raster[Cr] = new byte[width / hSampleFactor[Cr], height / vSampleFactor[Cr]];
int rgbaPos = 0;
for (short y = 0; y < height; y++)
{
int Yy = y / vSampleFactor[Y];
int Cby = y / vSampleFactor[Cb];
int Cry = y / vSampleFactor[Cr];
int Yx = 0, Cbx = 0, Crx = 0;
for (short x = 0; x < width; x++)
{
// Convert to YCbCr colorspace.
byte b = RgbaSample[rgbaPos++];
byte g = RgbaSample[rgbaPos++];
byte r = RgbaSample[rgbaPos++];
YCbCr.fromRGB(ref r, ref g, ref b);
// Only include the byte in question in the raster if it matches the appropriate sampling factor.
if (IncludeInSample(Y, x, y))
{
raster[Y][Yx++, Yy] = r;
}
if (IncludeInSample(Cb, x, y))
{
raster[Cb][Cbx++, Cby] = g;
}
if (IncludeInSample(Cr, x, y))
{
raster[Cr][Crx++, Cry] = b;
}
// For YCbCr, we ignore the Alpha byte of the RGBA byte structure, so advance beyond it.
rgbaPos++;
}
}
return raster;
}
static private bool IncludeInSample(int slice, short x, short y)
{
// Hopefully this gets inlined . . .
return ((x % hSampleFactor[slice]) == 0) && ((y % vSampleFactor[slice]) == 0);
}
There might be additional ways to optimize this, but it's working for now.

Resources