Best way to add a scaling mechanism to line function? - processing

I've made a script that makes rectangles inside larger rectangles, which I call boxes. Now I'm trying to implement a mechanism to make it look like you're zooming in. Im using the line() function to draw the boxes. Does anyone have a suggestion to make everything scale continuasly?
Code (It's quite long):
import java.util.ArrayList;
// *Gloabal Variables
// Random Points for dots
int randomXPoint;
int randomYPoint;
// Window offset on sides
public final int WINDOW_OFFSET = 10;
// Box and dot colour in HSB
public static int[] boxColour = { 0, 255, 255 };
public int[] pointColour = { 0, 0, 255 };
// Storages for boxes and points
public Box firstBox;
public ArrayList<Box> boxArray;
public ArrayList<PVector> pointPos;
// *Functions
// Colour changer, going from red to red
public void ChangeColour(int[] colour) {
if (colour[0] >= 255) {
colour[0] = 0;
}
else {
colour[0]++;
}
}
// Box class
public class Box {
public boolean isRealBox = true;
public int x, y, w, h;
public int cH, cS, cB;
private Box parentBox;
public Box(int x, int y, int w, int h, int[] colour) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.cH = colour[0];
this.cS = colour[1];
this.cB = colour[2];
}
public Box(int x, int y, int w, int h, int[] colour, Box parentBox) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.cH = colour[0];
this.cS = colour[1];
this.cB = colour[2];
this.parentBox = parentBox;
}
public boolean isInsideBox(int x, int y) {
if (((x > this.x) && (x < this.x + this.w)) && (y > this.y) && (y < this.y + this.h))
return true;
else
return false;
}
// Gets sector in box, enabling to know which way to shorten
public int getSector(int x, int y) {
if (((x < this.x + this.w / 2) && (x > this.x)) && ((y < this.y + this.h / 2) && (y > this.y))) return 0;
else if (((x < this.x + this.w) && (x > this.x + this.w / 2)) && ((y < this.y + this.h / 2) && (y > this.y))) return 1;
else if (((x < this.x + this.w / 2) && (x > this.x)) && ((y < this.y + this.h) && (y > this.y + this.h / 2))) return 2;
else if (((x < this.x + this.w) && (x > this.x + this.w / 2)) && ((y < this.y + this.h) && (y > this.y + this.h / 2))) return 3;
else return -1;
}
// Runs if (x, y) is inside the box
public Box ifInsideBox(int x, int y) {
switch (getSector(x, y)) {
case 0:
ChangeColour(boxColour);
return new Box(this.x, this.y, this.w / 2, this.h / 2, boxColour, this);
case 1:
ChangeColour(boxColour);
return new Box(this.x + this.w / 2, this.y, this.w / 2, this.h / 2, boxColour, this);
case 2:
ChangeColour(boxColour);
return new Box(this.x, this.y + this.h / 2, this.w / 2, this.h / 2, boxColour, this);
case 3:
ChangeColour(boxColour);
return new Box(this.x + this.w / 2, this.y + this.h / 2, this.w / 2, this.h / 2, boxColour, this);
default:
Box temp = new Box(this.x, this.y, this.w, this.h, boxColour);
temp.isRealBox = false;
return temp;
}
}
// Function for drawing the box. Uses 4 lines
public void drawBox() {
stroke(cH, cS, cB);
line(this.x, this.y, this.x + this.w, this.y);
line(this.x + this.w, this.y, this.x + this.w, this.y + this.h);
line(this.x + this.w, this.y + this.h, this.x, this.y + this.h);
line(this.x, this.y + this.h, this.x, this.y);
}
public void drawBox(int x, int y) {
stroke(cH, cS, cB);
switch (parentBox.getSector(x, y)) {
case 0:
line(parentBox.x + parentBox.w / 2, parentBox.y, parentBox.x + parentBox.w / 2, parentBox.y + parentBox.h / 2);
line(parentBox.x + parentBox.w / 2, parentBox.y + parentBox.h / 2, parentBox.x, parentBox.y + parentBox.h / 2);
break;
case 1:
line(parentBox.x + parentBox.w / 2, parentBox.y, parentBox.x + parentBox.w / 2, parentBox.y + parentBox.h / 2);
line(parentBox.x + parentBox.w / 2, parentBox.y + parentBox.h / 2, parentBox.x + parentBox.w, parentBox.y + parentBox.h / 2);
break;
case 2:
line(parentBox.x, parentBox.y + parentBox.h / 2, parentBox.x + parentBox.w / 2, parentBox.y + parentBox.h / 2);
line(parentBox.x + parentBox.w / 2, parentBox.y + parentBox.h / 2, parentBox.x + parentBox.w / 2, parentBox.y + parentBox.h);
break;
case 3:
line(parentBox.x + parentBox.w / 2, parentBox.y + parentBox.h / 2, parentBox.x + parentBox.w, parentBox.y + parentBox.h / 2);
line(parentBox.x + parentBox.w / 2, parentBox.y + parentBox.h / 2, parentBox.x + parentBox.w / 2, parentBox.y + parentBox.h);
break;
}
}
}
void setup() {
size(810, 810);
colorMode(HSB);
strokeWeight(2);
frameRate(60);
// Initialising firstBox, which offsets from the side
firstBox = new Box(WINDOW_OFFSET / 2, WINDOW_OFFSET / 2, width - WINDOW_OFFSET, height - WINDOW_OFFSET, boxColour);
boxArray = new ArrayList<Box>();
boxArray.add(firstBox);
pointPos = new ArrayList<PVector>();
}
void draw() {
background(0, 0, 0);
for (int loop = 0; loop < 3; loop++) {
randomXPoint = (int)random(WINDOW_OFFSET / 2, width - WINDOW_OFFSET / 2);
randomYPoint = (int)random(WINDOW_OFFSET / 2, height - WINDOW_OFFSET / 2);
boolean addedBox = false;
for (int i = boxArray.size() - 1; i >= 0; i--) {
if (!addedBox) {
if (boxArray.get(i).isInsideBox(randomXPoint, randomYPoint)) {
boxArray.add(boxArray.get(i).ifInsideBox(randomXPoint, randomYPoint));
addedBox = true;
}
}
}
//point(randomXPoint, randomYPoint);
pointPos.add(new PVector(randomXPoint, randomYPoint));
// Draws every box
for (int i = boxArray.size() - 1; i >= 1; i--) {
if (boxArray.get(i).isRealBox == true)
boxArray.get(i).drawBox();
}
boxArray.get(0).drawBox();
stroke(pointColour[0], pointColour[1], pointColour[2]);
for (PVector pos : pointPos) {
point(pos.x, pos.y);
}
}
}
Any other suggestions would be apriciated!

Just add the following lines at the top of your draw (to zoom based on mouseY):
float scaleFactor = 5 * (mouseY/(float)height) - 1; // max-scale 500%
translate(-width/2 * scaleFactor, -height/2 * scaleFactor);
scale(scaleFactor + 1);

Related

p5.js: Random movement of drawing tool

I coded this drawing tool:
var a = 0;
function setup() {
createCanvas(windowWidth, windowHeight);
background(0, 0, 255);
}
function draw() {
fill(0, 255, 255, random(255));
translate(mouseX, mouseY);
rotate(a);
textSize(120);
textAlign(CENTER, CENTER);
text('*', 0, 0);
rotate(a);
a = a + 0.08;
}
<script src="https://cdn.jsdelivr.net/npm/p5#1.4.1/lib/p5.js"></script>
Now I would like to have a movement, without doing it with the cursor. I have thought about something like this:
var a;
function centerCanvas() {
var x = (windowWidth - width) / 2;
var y = (windowHeight - height) / 2;
a.position(x, y);
}
function setup() {
a = createCanvas(windowHeight, windowHeight);
centerCanvas();
}
function draw() {
fill(0, 255, 255, random(255));
var x =
windowHeight / 2 +
sin(frameCount * 0.01) * cos(frameCount * 0.04) * windowHeight / 3;
var y =
windowHeight / 2 +
cos(frameCount * 0.01) * sin(frameCount * 0.04) * windowHeight / 3;
rotate(a);
textSize(120);
textAlign(CENTER, CENTER);
text('*', 0, 0);
rotate(a);
a = a + 0.08;
}
<script src="https://cdn.jsdelivr.net/npm/p5#1.4.1/lib/p5.js"></script>
Unfortunately, it doesn't work. It also would be cool if the movement would be random inside the canvas. Does anyone know how to do it?
This (almost) worked for me:
let wander;
function setup() {
createCanvas(windowWidth, windowHeight);
background(0, 0, 0);
wander = new Vehicle(0, 0);
}
function draw() {
wander.wander();
wander.update();
wander.edges();
wander.show();
}
class Vehicle {
constructor(x, y) {
this.pos = createVector(x, y);
this.vel = createVector(1, 0);
this.acc = createVector(0, 0);
this.maxSpeed = 4;
this.maxForce = 0.2;
this.r = 16;
this.wanderTheta = PI / 2;
this.xoff = 0;
}
wander() {
let angle = noise(this.xoff) * TWO_PI * 2;
let steer = p5.Vector.fromAngle(angle);
steer.setMag(this.maxForce);
this.applyForce(steer);
this.xoff += 0.01;
}
applyForce(force) {
this.acc.add(force);
}
update() {
this.vel.add(this.acc);
this.vel.limit(this.maxSpeed);
this.pos.add(this.vel);
this.acc.set(0, 0);
}
show() {
stroke(255);
strokeWeight(2);
fill(255);
push();
translate(this.pos.x, this.pos.y);
rotate(this.vel.heading());
textAlign(CENTER, CENTER);
textSize(120);
fill(0, 255, 255, random(255));
text("*", 0, 0);
pop();
}
edges() {
let hitEdge = false;
if (this.pos.x > width + this.r) {
this.pos.x = -this.r;
hitEdge = true;
} else if (this.pos.x < -this.r) {
this.pos.x = width + this.r;
hitEdge = true;
}
if (this.pos.y > height + this.r) {
this.pos.y = -this.r;
hitEdge = true;
} else if (this.pos.y < -this.r) {
this.pos.y = height + this.r;
hitEdge = true;
}
}
}
<script src="https://cdn.jsdelivr.net/npm/p5#1.4.1/lib/p5.js"></script>
Using P5.js's noise function is a really accurate way to represent wandering. With a little tinkering you can get the effect you want.
EDIT
This is your (debugged) code:
let a;
let r;
function centerCanvas() {
var x = (windowWidth - width) / 2;
var y = (windowHeight - height) / 2;
a.position(x, y);
}
function setup() {
a = createCanvas(windowHeight, windowHeight);
centerCanvas();
}
function draw() {
fill(0, 255, 255, random(255));
const x = windowHeight / 2 +
sin(frameCount * 0.01) * cos(frameCount * 0.04) * windowHeight / 3;
const y = windowHeight / 2 +
cos(frameCount * 0.01) * sin(frameCount * 0.04) * windowHeight / 3;
translate(x, y);
rotate(a * 0.08);
textSize(50);
textAlign(CENTER, CENTER);
text('*', 0, 0);
a += 1;
}
<script src="https://cdn.jsdelivr.net/npm/p5#1.4.1/lib/p5.js"></script>
How about this?
var a = 0;
var x = 0;
var y = 0;
var delta = 1;
function setup() {
createCanvas(windowWidth, windowHeight);
background(0, 0, 255);
}
function draw() {
fill(0, 255, 255, random(255));
x = x + 2 + Math.random();
y = y + 0.5 + Math.random();
x = x * delta;
y = y * delta;
if (x < 0) delta = -1;
translate((x) % windowWidth,(y) % windowHeight);
rotate(a);
textSize(120);
textAlign(CENTER, CENTER);
text('*', 0, 0);
rotate(a);
a = a + 0.08;
}
<script src="https://cdn.jsdelivr.net/npm/p5#1.4.1/lib/p5.js"></script>

How do I rotate an object in p5js?

I'm currently making a project similar to John Conway's Game of Life, and I would like to know how to rotate a point without using rotate().
When I use it it rotates it around the canvas, its difficult to explain here's the code:
//Setup
var x;
var y;
var x2;
var y2;
var x3;
var y3;
let slider;
function setup() {
//Setup and Varibles
createCanvas(400, 400);
x = 200;
y = 200;
x2 = 150;
y2 = 100;
x3 = 300;
y3 = 220;
slider = createSlider(0, 255, 100);
slider.position(10, 10);
slider.style("width", "80px");
}
function draw() {
let val = slider.value();
background(54);
stroke(255);
strokeWeight(1);
line(x, y, x + 30, y - 10);
strokeWeight(10);
point(x, y);
var r = ceil(random(5));
//Player 1 AI
switch (r) {
case 0:
x = x + 2;
break;
case 1:
x = x - 2;
break;
case 2:
y = y + 2;
break;
case 3:
y = y - 2;
break;
case 4:
//EXTRA
break;
}
point(x2, y2);
var ra = floor(random(5));
//Player 2 AI
switch (ra) {
case 0:
x2 = x2 + 2;
break;
case 1:
x2 = x2 - 2;
break;
case 2:
y2 = y2 + 2;
break;
case 3:
y2 = y2 - 2;
break;
case 4:
//EXTRA
break;
}
//Player 3 AI
var ran = ceil(random(5));
point(x3, y3);
switch (ran) {
case 0:
x3 = x3 + 2;
break;
case 1:
x3 = x3 - 2;
break;
case 2:
y3 = y3 + 2;
break;
case 3:
y3 = y3 - 2;
break;
case 4:
//EXTRA
break;
}
//Collision detection between Players
var d = int(dist(x2, y2, x, y));
var d2 = int(dist(x3, y3, x, y));
var d3 = int(dist(x2, y2, x3, y3));
function reset() {
x = 200;
y = 200;
x2 = 150;
y2 = 100;
x3 = 300;
y3 = 220;
}
noStroke();
text("1", x - 3, y - 5);
text("2", x2 - 3, y2 - 5);
text("3", x3 - 3, y3 - 5);
if (d === 10) {
reset();
}
if (d2 === 10) {
reset();
}
if (d3 === 10) {
reset();
}
//Barriers
if (y === 0) {
reset();
}
if (y2 === 0) {
reset();
}
if (y3 === 0) {
reset();
}
if (y === 400) {
reset();
}
if (y2 === 400) {
reset();
}
if (y3 === 400) {
reset();
}
if (x === 400) {
reset();
}
if (x2 === 400) {
reset();
}
if (x3 === 400) {
reset();
}
if (x === 0) {
reset();
}
if (x2 === 0) {
reset();
}
if (x3 === 0) {
reset();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
Thank You
https://editor.p5js.org/
I'm new p5js so sorry if the answer is simple!
Unless the shape in question is trivially simple (i.e. just a line). Then I think you will definitely want to utilize the rotate() function. It sounds like you've been trying to use just rotate(), which will rotate all future drawing commands around the origin (position 0, 0) of the canvas. In order to rotate a particular object around its own origin you need to translate that origin, then perform the rotation, then draw the object. After drawing a rotated object you can use pop() to reset the translation and rotation back to the original. Here's an example:
function setup() {
createCanvas(windowWidth, windowHeight);
// Draw squares centered on the origin
rectMode(CENTER);
}
function draw() {
background(100);
for (let i = 1; i <= 4; i++) {
// Save the current state (translation/rotation/etc)
push();
// Translate to the origin of the shape
translate(mouseX * i / 4, mouseY * i / 4);
// Rotate around the origin
rotate(millis() / 1000 * PI / 2);
// Because we've translated to the origin, we draw the square at 0, 0
square(0, 0, 50);
// Restore the state saved with push();
pop();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
In order to demonstrate why this is easier than the alternative, here is an example that does the same thing but does not use translate() or rotate():
function setup() {
createCanvas(windowWidth, windowHeight);
}
// Declare each vertex of our geometry as a vector from the origin.
const rectPoints = [
new p5.Vector(-25, -25),
new p5.Vector(25, -25),
new p5.Vector(25, 25),
new p5.Vector(-25, 25)
];
function draw() {
background(100);
let angle = millis() / 1000 * PI / 2;
// Use p5.Vector.rotate to rotate each of the points that defines our geometry
let rotatedRectPoints = rectPoints.map(v => v.copy().rotate(angle));
for (let i = 1; i <= 4; i++) {
// We can't using normal primitives like square(), so we have to draw shapes
// with beginShape/endShape
beginShape();
for (const p of rotatedRectPoints) {
vertex(p.x + mouseX * i / 4, p.y + mouseY * i / 4);
}
endShape();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

p5.js change object colour after X frames

I would like to change the fill colour of an object over time. Is there a way to change the fill colour of an object after X frames?
I am learning about constructors, and I am thinking that in the code's updateParticle function, after this.age counts to 'X', the fill colour of the ellipse could change.
'''
function Particle(x, y, xSpeed, ySpeed, size, colour) {
this.x = x;
this.y = y;
this.xSpeed = xSpeed;
this.ySpeed = ySpeed;
this.size = size;
this.colour = colour;
this.age = 0;
this.drawParticle = function() {
fill(this.colour);
noStroke();
ellipse(this.x, this.y, this.size);
}
this.updateParticle = function() {
this.x += this.xSpeed;
this.y += this.ySpeed;
this.age++;
}
}
function Emitter(x, y, xSpeed, ySpeed, size, colour) {
this.x = x;
this.y = y;
this.xSpeed = xSpeed;
this.ySpeed = ySpeed;
this.size = size;
this.colour = colour;
this.particles = [];
this.startParticles = [];
this.lifetime = 0;
this.addParticle = function() {
var p = new Particle(random(this.x - 10, this.x + 10),
random(this.y - 10, this.y + 10),
random(this.xSpeed - 0.4, this.xSpeed + 0.4),
random(this.ySpeed - 5, this.ySpeed - 1),
random(this.size - 4, this.size + 40),
this.colour);
return p;
}
this.startEmitter = function(startParticles, lifetime) {
this.startParticles = startParticles;
this.lifetime = lifetime;
for (var i = 0; i < startParticles; i++) {
this.particles.push(this.addParticle());
}
}
this.updateParticles = function() {
var deadParticles = 0
for (var i = this.particles.length - 1; i >= 0; i--) {
this.particles[i].drawParticle();
this.particles[i].updateParticle();
if (this.particles[i].age > random(0, this.lifetime)) {
this.particles.splice(i, 1);
deadParticles++;
}
}
if (deadParticles > 0) {
for (var i = 0; i < deadParticles; i++) {
this.particles.push(this.addParticle());
}
}
}
}
var emit;
function setup() {
createCanvas(800, 600);
emit = new Emitter(width / 2, height - 100, 0, -1, 10, color(200, 0, 200, 50));
emit.startEmitter(600, 4000);
}
function draw() {
background(200);
emit.updateParticles();
}
'''
Well you could just:
if(frameCount % 30 == 0){ // % 30 is the remainder of num / 30, so 4 % 3 = 1, since 3 / 3 = 0 And 4 / 3 = 3.33
fill("lime") // these are just preset colors in p5.js AND css lime == rgb(0,255,0)
} else {
fill('darkred')
}
or you could also do it with for example a switch statement: using background for no reason
switch(MY_frameCount){
case 1:
background('blue')
break
case 2:
background("darkgreen")
break
case 376:
background(crimson)
// break
}
MY_frameCount ++
or:
if(Math.random() < 0.1){
fill(Math.random() * 255, Math.random() * 255, Math.random() * 255)
} // this should on average fill with random color every 10 frames

THREE.JS Multiple textures (60+) on one complex geometry (terrain)

Let's say I want to create a dynamic terrain based on level-of-detail algorithm and a very high-res satellite texture (i.e. 32.768x32.768px). Eventually, I have created tiles out of this image according to levels:
level1 4 tiles
level2 16 tiles
level3 64 tiles
level4 256 tiles
level5 1024 tiles
All these tiles are 1024x1024
I have attached a very basic snippet, which has already divided plane (THREE.BufferGeometry) according to camera position.
The Delaunator from Mapbox works pretty fast, however I don't know how to place textures onto plane like on following illustration:
I bet it has to be done with shader, but don't have any ideas how to do it.
Merging these tiles to one large texture leads us to 32.768x32.768, so it's the dead end.
Yeah, it could be multi-texturing with THREE.MeshFaceMaterial(materials) and assigning each material (tile) to certain vertices. However, I'm looking for straight GLSL solution capable of processing ~60-65 textures of at least 512x512, better 1024x1024.
PS: Yes, I have already version where this single plane is divided to small ones, but I'm looking for single plane approach, since there are crack on tile joints similar as described in this article, Figure 8.
PS: Please ignore quadtree algrorithm. I am asking for general solution of rendering 60-70 textures for one geometry.
//https://hofk.de/main/discourse.threejs/2018/Triangulation/Triangulation.html
////by Mapbox https://github.com/mapbox/delaunator
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.Delaunator = factory());
}(this, (function () { 'use strict';
var EPSILON = Math.pow(2, -52);
var Delaunator = function Delaunator(coords) {
var this$1 = this;
var n = coords.length >> 1;
if (n > 0 && typeof coords[0] !== 'number') { throw new Error('Expected coords to contain numbers.'); }
this.coords = coords;
var maxTriangles = 2 * n - 5;
var triangles = this.triangles = new Uint32Array(maxTriangles * 3);
var halfedges = this.halfedges = new Int32Array(maxTriangles * 3);
this._hashSize = Math.ceil(Math.sqrt(n));
var hullPrev = this.hullPrev = new Uint32Array(n);
var hullNext = this.hullNext = new Uint32Array(n);
var hullTri = this.hullTri = new Uint32Array(n);
var hullHash = new Int32Array(this._hashSize).fill(-1);
var ids = new Uint32Array(n);
var minX = Infinity;
var minY = Infinity;
var maxX = -Infinity;
var maxY = -Infinity;
for (var i = 0; i < n; i++) {
var x = coords[2 * i];
var y = coords[2 * i + 1];
if (x < minX) { minX = x; }
if (y < minY) { minY = y; }
if (x > maxX) { maxX = x; }
if (y > maxY) { maxY = y; }
ids[i] = i;
}
var cx = (minX + maxX) / 2;
var cy = (minY + maxY) / 2;
var minDist = Infinity;
var i0, i1, i2;
for (var i$1 = 0; i$1 < n; i$1++) {
var d = dist(cx, cy, coords[2 * i$1], coords[2 * i$1 + 1]);
if (d < minDist) {
i0 = i$1;
minDist = d;
}
}
var i0x = coords[2 * i0];
var i0y = coords[2 * i0 + 1];
minDist = Infinity;
for (var i$2 = 0; i$2 < n; i$2++) {
if (i$2 === i0) { continue; }
var d$1 = dist(i0x, i0y, coords[2 * i$2], coords[2 * i$2 + 1]);
if (d$1 < minDist && d$1 > 0) {
i1 = i$2;
minDist = d$1;
}
}
var i1x = coords[2 * i1];
var i1y = coords[2 * i1 + 1];
var minRadius = Infinity;
for (var i$3 = 0; i$3 < n; i$3++) {
if (i$3 === i0 || i$3 === i1) { continue; }
var r = circumradius(i0x, i0y, i1x, i1y, coords[2 * i$3], coords[2 * i$3 + 1]);
if (r < minRadius) {
i2 = i$3;
minRadius = r;
}
}
var i2x = coords[2 * i2];
var i2y = coords[2 * i2 + 1];
if (minRadius === Infinity) {
throw new Error('No Delaunay triangulation exists for this input.');
}
if (orient(i0x, i0y, i1x, i1y, i2x, i2y)) {
var i$4 = i1;
var x$1 = i1x;
var y$1 = i1y;
i1 = i2;
i1x = i2x;
i1y = i2y;
i2 = i$4;
i2x = x$1;
i2y = y$1;
}
var center = circumcenter(i0x, i0y, i1x, i1y, i2x, i2y);
this._cx = center.x;
this._cy = center.y;
var dists = new Float64Array(n);
for (var i$5 = 0; i$5 < n; i$5++) {
dists[i$5] = dist(coords[2 * i$5], coords[2 * i$5 + 1], center.x, center.y);
}
quicksort(ids, dists, 0, n - 1);
this.hullStart = i0;
var hullSize = 3;
hullNext[i0] = hullPrev[i2] = i1;
hullNext[i1] = hullPrev[i0] = i2;
hullNext[i2] = hullPrev[i1] = i0;
hullTri[i0] = 0;
hullTri[i1] = 1;
hullTri[i2] = 2;
hullHash[this._hashKey(i0x, i0y)] = i0;
hullHash[this._hashKey(i1x, i1y)] = i1;
hullHash[this._hashKey(i2x, i2y)] = i2;
this.trianglesLen = 0;
this._addTriangle(i0, i1, i2, -1, -1, -1);
for (var k = 0, xp = (void 0), yp = (void 0); k < ids.length; k++) {
var i$6 = ids[k];
var x$2 = coords[2 * i$6];
var y$2 = coords[2 * i$6 + 1];
if (k > 0 && Math.abs(x$2 - xp) <= EPSILON && Math.abs(y$2 - yp) <= EPSILON) { continue; }
xp = x$2;
yp = y$2;
if (i$6 === i0 || i$6 === i1 || i$6 === i2) { continue; }
var start = 0;
for (var j = 0, key = this._hashKey(x$2, y$2); j < this._hashSize; j++) {
start = hullHash[(key + j) % this$1._hashSize];
if (start !== -1 && start !== hullNext[start]) { break; }
}
start = hullPrev[start];
var e = start, q = (void 0);
while (q = hullNext[e], !orient(x$2, y$2, coords[2 * e], coords[2 * e + 1], coords[2 * q], coords[2 * q + 1])) {
e = q;
if (e === start) {
e = -1;
break;
}
}
if (e === -1) { continue; }
var t = this$1._addTriangle(e, i$6, hullNext[e], -1, -1, hullTri[e]);
hullTri[i$6] = this$1._legalize(t + 2);
hullTri[e] = t;
hullSize++;
var n$1 = hullNext[e];
while (q = hullNext[n$1], orient(x$2, y$2, coords[2 * n$1], coords[2 * n$1 + 1], coords[2 * q], coords[2 * q + 1])) {
t = this$1._addTriangle(n$1, i$6, q, hullTri[i$6], -1, hullTri[n$1]);
hullTri[i$6] = this$1._legalize(t + 2);
hullNext[n$1] = n$1;
hullSize--;
n$1 = q;
}
if (e === start) {
while (q = hullPrev[e], orient(x$2, y$2, coords[2 * q], coords[2 * q + 1], coords[2 * e], coords[2 * e + 1])) {
t = this$1._addTriangle(q, i$6, e, -1, hullTri[e], hullTri[q]);
this$1._legalize(t + 2);
hullTri[q] = t;
hullNext[e] = e;
hullSize--;
e = q;
}
}
this$1.hullStart = hullPrev[i$6] = e;
hullNext[e] = hullPrev[n$1] = i$6;
hullNext[i$6] = n$1;
hullHash[this$1._hashKey(x$2, y$2)] = i$6;
hullHash[this$1._hashKey(coords[2 * e], coords[2 * e + 1])] = e;
}
this.hull = new Uint32Array(hullSize);
for (var i$7 = 0, e$1 = this.hullStart; i$7 < hullSize; i$7++) {
this$1.hull[i$7] = e$1;
e$1 = hullNext[e$1];
}
this.hullPrev = this.hullNext = this.hullTri = null;
this.triangles = triangles.subarray(0, this.trianglesLen);
this.halfedges = halfedges.subarray(0, this.trianglesLen);
};
Delaunator.from = function from (points, getX, getY) {
if ( getX === void 0 ) getX = defaultGetX;
if ( getY === void 0 ) getY = defaultGetY;
var n = points.length;
var coords = new Float64Array(n * 2);
for (var i = 0; i < n; i++) {
var p = points[i];
coords[2 * i] = getX(p);
coords[2 * i + 1] = getY(p);
}
return new Delaunator(coords);
};
Delaunator.prototype._hashKey = function _hashKey (x, y) {
return Math.floor(pseudoAngle(x - this._cx, y - this._cy) * this._hashSize) % this._hashSize;
};
Delaunator.prototype._legalize = function _legalize (a) {
var this$1 = this;
var ref = this;
var triangles = ref.triangles;
var coords = ref.coords;
var halfedges = ref.halfedges;
var b = halfedges[a];
var a0 = a - a % 3;
var b0 = b - b % 3;
var al = a0 + (a + 1) % 3;
var ar = a0 + (a + 2) % 3;
var bl = b0 + (b + 2) % 3;
if (b === -1) { return ar; }
var p0 = triangles[ar];
var pr = triangles[a];
var pl = triangles[al];
var p1 = triangles[bl];
var illegal = inCircle(
coords[2 * p0], coords[2 * p0 + 1],
coords[2 * pr], coords[2 * pr + 1],
coords[2 * pl], coords[2 * pl + 1],
coords[2 * p1], coords[2 * p1 + 1]);
if (illegal) {
triangles[a] = p1;
triangles[b] = p0;
var hbl = halfedges[bl];
if (hbl === -1) {
var e = this.hullStart;
do {
if (this$1.hullTri[e] === bl) {
this$1.hullTri[e] = a;
break;
}
e = this$1.hullNext[e];
} while (e !== this.hullStart);
}
this._link(a, hbl);
this._link(b, halfedges[ar]);
this._link(ar, bl);
var br = b0 + (b + 1) % 3;
this._legalize(a);
return this._legalize(br);
}
return ar;
};
Delaunator.prototype._link = function _link (a, b) {
this.halfedges[a] = b;
if (b !== -1) { this.halfedges[b] = a; }
};
Delaunator.prototype._addTriangle = function _addTriangle (i0, i1, i2, a, b, c) {
var t = this.trianglesLen;
this.triangles[t] = i0;
this.triangles[t + 1] = i1;
this.triangles[t + 2] = i2;
this._link(t, a);
this._link(t + 1, b);
this._link(t + 2, c);
this.trianglesLen += 3;
return t;
};
function pseudoAngle(dx, dy) {
var p = dx / (Math.abs(dx) + Math.abs(dy));
return (dy > 0 ? 3 - p : 1 + p) / 4;
}
function dist(ax, ay, bx, by) {
var dx = ax - bx;
var dy = ay - by;
return dx * dx + dy * dy;
}
function orient(px, py, qx, qy, rx, ry) {
return (qy - py) * (rx - qx) - (qx - px) * (ry - qy) < 0;
}
function inCircle(ax, ay, bx, by, cx, cy, px, py) {
var dx = ax - px;
var dy = ay - py;
var ex = bx - px;
var ey = by - py;
var fx = cx - px;
var fy = cy - py;
var ap = dx * dx + dy * dy;
var bp = ex * ex + ey * ey;
var cp = fx * fx + fy * fy;
return dx * (ey * cp - bp * fy) -
dy * (ex * cp - bp * fx) +
ap * (ex * fy - ey * fx) < 0;
}
function circumradius(ax, ay, bx, by, cx, cy) {
var dx = bx - ax;
var dy = by - ay;
var ex = cx - ax;
var ey = cy - ay;
var bl = dx * dx + dy * dy;
var cl = ex * ex + ey * ey;
var d = 0.5 / (dx * ey - dy * ex);
var x = (ey * bl - dy * cl) * d;
var y = (dx * cl - ex * bl) * d;
return x * x + y * y;
}
function circumcenter(ax, ay, bx, by, cx, cy) {
var dx = bx - ax;
var dy = by - ay;
var ex = cx - ax;
var ey = cy - ay;
var bl = dx * dx + dy * dy;
var cl = ex * ex + ey * ey;
var d = 0.5 / (dx * ey - dy * ex);
var x = ax + (ey * bl - dy * cl) * d;
var y = ay + (dx * cl - ex * bl) * d;
return {x: x, y: y};
}
function quicksort(ids, dists, left, right) {
if (right - left <= 20) {
for (var i = left + 1; i <= right; i++) {
var temp = ids[i];
var tempDist = dists[temp];
var j = i - 1;
while (j >= left && dists[ids[j]] > tempDist) { ids[j + 1] = ids[j--]; }
ids[j + 1] = temp;
}
} else {
var median = (left + right) >> 1;
var i$1 = left + 1;
var j$1 = right;
swap(ids, median, i$1);
if (dists[ids[left]] > dists[ids[right]]) { swap(ids, left, right); }
if (dists[ids[i$1]] > dists[ids[right]]) { swap(ids, i$1, right); }
if (dists[ids[left]] > dists[ids[i$1]]) { swap(ids, left, i$1); }
var temp$1 = ids[i$1];
var tempDist$1 = dists[temp$1];
while (true) {
do { i$1++; } while (dists[ids[i$1]] < tempDist$1);
do { j$1--; } while (dists[ids[j$1]] > tempDist$1);
if (j$1 < i$1) { break; }
swap(ids, i$1, j$1);
}
ids[left + 1] = ids[j$1];
ids[j$1] = temp$1;
if (right - i$1 + 1 >= j$1 - left) {
quicksort(ids, dists, i$1, right);
quicksort(ids, dists, left, j$1 - 1);
} else {
quicksort(ids, dists, left, j$1 - 1);
quicksort(ids, dists, i$1, right);
}
}
}
function swap(arr, i, j) {
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
function defaultGetX(p) {
return p[0];
}
function defaultGetY(p) {
return p[1];
}
return Delaunator;
})));
var folder = "17_50438_37354_50534_37450/satellite/";
var levels = [0x0B132B, 0x1C2541, 0x3A506B, 0x5BC0BE, 0x6FFFE9];
var mouseDown = false;
var renderer, scene, camera, controls, loader, terrain, glsl, uniforms, root, tree;
var colors = [0xFFFFFF, 0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF];
class Node{
constructor(level_, index_, centerX_, centerY_, width_, height_, resolution_){
this.level = level_;
this.index = index_;
this.w = width_;
this.h = height_;
this.x = centerX_;
this.y = centerY_;
this.resolution = resolution_;
this.lifetime = 128;
this.edges = this.getEdges();
}
getEdges = function(){
return [
new THREE.Vector3(this.x - this.w / 2, 0, this.y - this.h / 2),
new THREE.Vector3(this.x + this.w / 2, 0, this.y - this.h / 2),
new THREE.Vector3(this.x - this.w / 2, 0, this.y + this.h / 2),
new THREE.Vector3(this.x + this.w / 2, 0, this.y + this.h / 2)
];
}
}
class Quadtree{
constructor(root_, levels_, distance_){
var this_ = this;
this.levels = levels_;
this.distance = distance_;
this.root = root_;
this.nodes = [];
this.nodes = this.splitNode(0, this.root, false);
this.generateLevels();
this.last = [...this.nodes];
this.tiles = {};
this.debug = {};
this.points = [];
}
generateLevels = function(){
for(var i = 0; i < this.levels; i++){
var tmpNodes = [];
for(var j = 0; j < this.nodes.length; j++){
tmpNodes.push(...this.splitNode(j, this.nodes[j], true));
}
this.nodes = tmpNodes;
}
}
update = function(){
var this_ = this;
this.nodes = [];
this.nodes = this.splitNode(0, this.root, false);
this.generateLevels();
this.debug = {};
this.last = [...this.nodes];
}
splitNode = function(index_, parent_, check_){
if((parent_.level < this.levels && this.sqrtDistance(parent_) < this.distance) || !check_){
var lt = new Node(parent_.level + 1, { x: parent_.index.x * 2, y: parent_.index.y * 2 }, parent_.x - parent_.w / 4, parent_.y - parent_.h / 4, parent_.w / 2, parent_.h / 2, parent_.resolution / 2);
var rt = new Node(parent_.level + 1, { x: parent_.index.x * 2, y: parent_.index.y * 2 + 1 }, parent_.x + parent_.w / 4, parent_.y - parent_.h / 4, parent_.w / 2, parent_.h / 2, parent_.resolution / 2);
var lb = new Node(parent_.level + 1, { x: parent_.index.x * 2 + 1, y: parent_.index.y * 2 }, parent_.x - parent_.w / 4, parent_.y + parent_.h / 4, parent_.w / 2, parent_.h / 2, parent_.resolution / 2);
var rb = new Node(parent_.level + 1, { x: parent_.index.x * 2 + 1, y: parent_.index.y * 2 + 1 }, parent_.x + parent_.w / 4, parent_.y + parent_.h / 4, parent_.w / 2, parent_.h / 2, parent_.resolution / 2);
return [lt, rt, lb, rb];
}
return [parent_];
}
sqrtDistance = function(node_){
var target = new THREE.Vector2(camera.position.x, camera.position.z).lerp(new THREE.Vector2(controls.target.x, controls.target.z), 1.0);
var x1 = node_.x - node_.w / 2.0;
var y1 = node_.y - node_.h / 2.0;
var x2 = node_.x + node_.w / 2.0;
var y2 = node_.y + node_.h / 2.0;
var rx = (x1 + x2) / 2.0;
var ry = (y1 + y2) / 2.0;
var rwidth = node_.w;
var rheight = node_.h;
var dx = Math.max(Math.abs(target.x - rx) - rwidth / 2, 0);
var dy = Math.max(Math.abs(target.y - ry) - rheight / 2, 0);
return Math.sqrt(dx * dx + dy * dy);
}
}
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x000000);
document.body.appendChild(renderer.domElement);
scene = new THREE.Scene();
loader = new THREE.TextureLoader();
loader.crossOrigin = "";
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 51200);
camera.position.set(-2048, 2048, -2048);
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.screenSpacePanning = false;
controls.minDistance = 8;
controls.maxDistance = 5120;
controls.maxPolarAngle = Math.PI / 2;
camera.position.set(208.48355078304965, 45.28894677815297, 310.34089790619583);
controls.target.set(233.437242880138, -1.1266992511037067e-14, 279.779814968453);
root = new Node(0, {x: 0, y: 0}, 0, 0, 2048, 2048, 64);
partition = new Quadtree(root, 5, 2048.0 / 16.0);
var points = [];
partition.nodes.forEach(function(node_){
points.push(...node_.edges);
});
var geometry = new THREE.BufferGeometry().setFromPoints(points);
var indexDelaunay = Delaunator.from(points.map(v => { return [v.x, v.z]; }) );
var meshIndex = [];
for (let i = 0; i < indexDelaunay.triangles.length; i++){ meshIndex.push(indexDelaunay.triangles[i]); }
geometry.setIndex(meshIndex);
geometry.computeVertexNormals();
var plane = new THREE.Mesh(geometry, new THREE.MeshNormalMaterial({ wireframe: true }));
scene.add(plane);
animate();
document.addEventListener("mousedown", function(){ mouseDown = true; }, false);
document.addEventListener("mouseup", function(){ mouseDown = false; }, false);
document.addEventListener("mousemove", onMouseUpdate, false);
renderer.domElement.addEventListener("wheel", onMouseUpdate, false);
function animate(){
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
function onMouseUpdate(e_){
partition.update(new THREE.Vector2(camera.position.x, camera.position.y));
var points = [];
partition.nodes.forEach(function(node_){
points.push(...node_.edges);
});
var geometry = new THREE.BufferGeometry().setFromPoints(points);
var indexDelaunay = Delaunator.from(points.map(v => { return [v.x, v.z]; }) );
var meshIndex = [];
for (let i = 0; i < indexDelaunay.triangles.length; i++){ meshIndex.push(indexDelaunay.triangles[i]); }
geometry.setIndex(meshIndex);
geometry.computeVertexNormals();
plane.geometry = geometry;
}
body { margin: 0; }
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>GLSL Intersection</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://unpkg.com/three#0.116.0/build/three.min.js"></script>
<script src="https://unpkg.com/three#0.116.0/examples/js/controls/OrbitControls.js"></script>
</head>
<body>
</body>
</html>
That's a simple sketch to TheJim01 proposal of splitting geometry render to different draw calls by geometry.addGroup method. The snippet has a crossOrigin issue, so it's just for reference.
I don't know if it's capable of doing 60-70 textures/materials for one geometry, however the following code could be used for >16 materials.
//https://hofk.de/main/discourse.threejs/2018/Triangulation/Triangulation.html
////by Mapbox https://github.com/mapbox/delaunator
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.Delaunator = factory());
}(this, (function () { 'use strict';
var EPSILON = Math.pow(2, -52);
var Delaunator = function Delaunator(coords) {
var this$1 = this;
var n = coords.length >> 1;
if (n > 0 && typeof coords[0] !== 'number') { throw new Error('Expected coords to contain numbers.'); }
this.coords = coords;
var maxTriangles = 2 * n - 5;
var triangles = this.triangles = new Uint32Array(maxTriangles * 3);
var halfedges = this.halfedges = new Int32Array(maxTriangles * 3);
this._hashSize = Math.ceil(Math.sqrt(n));
var hullPrev = this.hullPrev = new Uint32Array(n);
var hullNext = this.hullNext = new Uint32Array(n);
var hullTri = this.hullTri = new Uint32Array(n);
var hullHash = new Int32Array(this._hashSize).fill(-1);
var ids = new Uint32Array(n);
var minX = Infinity;
var minY = Infinity;
var maxX = -Infinity;
var maxY = -Infinity;
for (var i = 0; i < n; i++) {
var x = coords[2 * i];
var y = coords[2 * i + 1];
if (x < minX) { minX = x; }
if (y < minY) { minY = y; }
if (x > maxX) { maxX = x; }
if (y > maxY) { maxY = y; }
ids[i] = i;
}
var cx = (minX + maxX) / 2;
var cy = (minY + maxY) / 2;
var minDist = Infinity;
var i0, i1, i2;
for (var i$1 = 0; i$1 < n; i$1++) {
var d = dist(cx, cy, coords[2 * i$1], coords[2 * i$1 + 1]);
if (d < minDist) {
i0 = i$1;
minDist = d;
}
}
var i0x = coords[2 * i0];
var i0y = coords[2 * i0 + 1];
minDist = Infinity;
for (var i$2 = 0; i$2 < n; i$2++) {
if (i$2 === i0) { continue; }
var d$1 = dist(i0x, i0y, coords[2 * i$2], coords[2 * i$2 + 1]);
if (d$1 < minDist && d$1 > 0) {
i1 = i$2;
minDist = d$1;
}
}
var i1x = coords[2 * i1];
var i1y = coords[2 * i1 + 1];
var minRadius = Infinity;
for (var i$3 = 0; i$3 < n; i$3++) {
if (i$3 === i0 || i$3 === i1) { continue; }
var r = circumradius(i0x, i0y, i1x, i1y, coords[2 * i$3], coords[2 * i$3 + 1]);
if (r < minRadius) {
i2 = i$3;
minRadius = r;
}
}
var i2x = coords[2 * i2];
var i2y = coords[2 * i2 + 1];
if (minRadius === Infinity) {
throw new Error('No Delaunay triangulation exists for this input.');
}
if (orient(i0x, i0y, i1x, i1y, i2x, i2y)) {
var i$4 = i1;
var x$1 = i1x;
var y$1 = i1y;
i1 = i2;
i1x = i2x;
i1y = i2y;
i2 = i$4;
i2x = x$1;
i2y = y$1;
}
var center = circumcenter(i0x, i0y, i1x, i1y, i2x, i2y);
this._cx = center.x;
this._cy = center.y;
var dists = new Float64Array(n);
for (var i$5 = 0; i$5 < n; i$5++) {
dists[i$5] = dist(coords[2 * i$5], coords[2 * i$5 + 1], center.x, center.y);
}
quicksort(ids, dists, 0, n - 1);
this.hullStart = i0;
var hullSize = 3;
hullNext[i0] = hullPrev[i2] = i1;
hullNext[i1] = hullPrev[i0] = i2;
hullNext[i2] = hullPrev[i1] = i0;
hullTri[i0] = 0;
hullTri[i1] = 1;
hullTri[i2] = 2;
hullHash[this._hashKey(i0x, i0y)] = i0;
hullHash[this._hashKey(i1x, i1y)] = i1;
hullHash[this._hashKey(i2x, i2y)] = i2;
this.trianglesLen = 0;
this._addTriangle(i0, i1, i2, -1, -1, -1);
for (var k = 0, xp = (void 0), yp = (void 0); k < ids.length; k++) {
var i$6 = ids[k];
var x$2 = coords[2 * i$6];
var y$2 = coords[2 * i$6 + 1];
if (k > 0 && Math.abs(x$2 - xp) <= EPSILON && Math.abs(y$2 - yp) <= EPSILON) { continue; }
xp = x$2;
yp = y$2;
if (i$6 === i0 || i$6 === i1 || i$6 === i2) { continue; }
var start = 0;
for (var j = 0, key = this._hashKey(x$2, y$2); j < this._hashSize; j++) {
start = hullHash[(key + j) % this$1._hashSize];
if (start !== -1 && start !== hullNext[start]) { break; }
}
start = hullPrev[start];
var e = start, q = (void 0);
while (q = hullNext[e], !orient(x$2, y$2, coords[2 * e], coords[2 * e + 1], coords[2 * q], coords[2 * q + 1])) {
e = q;
if (e === start) {
e = -1;
break;
}
}
if (e === -1) { continue; }
var t = this$1._addTriangle(e, i$6, hullNext[e], -1, -1, hullTri[e]);
hullTri[i$6] = this$1._legalize(t + 2);
hullTri[e] = t;
hullSize++;
var n$1 = hullNext[e];
while (q = hullNext[n$1], orient(x$2, y$2, coords[2 * n$1], coords[2 * n$1 + 1], coords[2 * q], coords[2 * q + 1])) {
t = this$1._addTriangle(n$1, i$6, q, hullTri[i$6], -1, hullTri[n$1]);
hullTri[i$6] = this$1._legalize(t + 2);
hullNext[n$1] = n$1;
hullSize--;
n$1 = q;
}
if (e === start) {
while (q = hullPrev[e], orient(x$2, y$2, coords[2 * q], coords[2 * q + 1], coords[2 * e], coords[2 * e + 1])) {
t = this$1._addTriangle(q, i$6, e, -1, hullTri[e], hullTri[q]);
this$1._legalize(t + 2);
hullTri[q] = t;
hullNext[e] = e;
hullSize--;
e = q;
}
}
this$1.hullStart = hullPrev[i$6] = e;
hullNext[e] = hullPrev[n$1] = i$6;
hullNext[i$6] = n$1;
hullHash[this$1._hashKey(x$2, y$2)] = i$6;
hullHash[this$1._hashKey(coords[2 * e], coords[2 * e + 1])] = e;
}
this.hull = new Uint32Array(hullSize);
for (var i$7 = 0, e$1 = this.hullStart; i$7 < hullSize; i$7++) {
this$1.hull[i$7] = e$1;
e$1 = hullNext[e$1];
}
this.hullPrev = this.hullNext = this.hullTri = null;
this.triangles = triangles.subarray(0, this.trianglesLen);
this.halfedges = halfedges.subarray(0, this.trianglesLen);
};
Delaunator.from = function from (points, getX, getY) {
if ( getX === void 0 ) getX = defaultGetX;
if ( getY === void 0 ) getY = defaultGetY;
var n = points.length;
var coords = new Float64Array(n * 2);
for (var i = 0; i < n; i++) {
var p = points[i];
coords[2 * i] = getX(p);
coords[2 * i + 1] = getY(p);
}
return new Delaunator(coords);
};
Delaunator.prototype._hashKey = function _hashKey (x, y) {
return Math.floor(pseudoAngle(x - this._cx, y - this._cy) * this._hashSize) % this._hashSize;
};
Delaunator.prototype._legalize = function _legalize (a) {
var this$1 = this;
var ref = this;
var triangles = ref.triangles;
var coords = ref.coords;
var halfedges = ref.halfedges;
var b = halfedges[a];
var a0 = a - a % 3;
var b0 = b - b % 3;
var al = a0 + (a + 1) % 3;
var ar = a0 + (a + 2) % 3;
var bl = b0 + (b + 2) % 3;
if (b === -1) { return ar; }
var p0 = triangles[ar];
var pr = triangles[a];
var pl = triangles[al];
var p1 = triangles[bl];
var illegal = inCircle(
coords[2 * p0], coords[2 * p0 + 1],
coords[2 * pr], coords[2 * pr + 1],
coords[2 * pl], coords[2 * pl + 1],
coords[2 * p1], coords[2 * p1 + 1]);
if (illegal) {
triangles[a] = p1;
triangles[b] = p0;
var hbl = halfedges[bl];
if (hbl === -1) {
var e = this.hullStart;
do {
if (this$1.hullTri[e] === bl) {
this$1.hullTri[e] = a;
break;
}
e = this$1.hullNext[e];
} while (e !== this.hullStart);
}
this._link(a, hbl);
this._link(b, halfedges[ar]);
this._link(ar, bl);
var br = b0 + (b + 1) % 3;
this._legalize(a);
return this._legalize(br);
}
return ar;
};
Delaunator.prototype._link = function _link (a, b) {
this.halfedges[a] = b;
if (b !== -1) { this.halfedges[b] = a; }
};
Delaunator.prototype._addTriangle = function _addTriangle (i0, i1, i2, a, b, c) {
var t = this.trianglesLen;
this.triangles[t] = i0;
this.triangles[t + 1] = i1;
this.triangles[t + 2] = i2;
this._link(t, a);
this._link(t + 1, b);
this._link(t + 2, c);
this.trianglesLen += 3;
return t;
};
function pseudoAngle(dx, dy) {
var p = dx / (Math.abs(dx) + Math.abs(dy));
return (dy > 0 ? 3 - p : 1 + p) / 4;
}
function dist(ax, ay, bx, by) {
var dx = ax - bx;
var dy = ay - by;
return dx * dx + dy * dy;
}
function orient(px, py, qx, qy, rx, ry) {
return (qy - py) * (rx - qx) - (qx - px) * (ry - qy) < 0;
}
function inCircle(ax, ay, bx, by, cx, cy, px, py) {
var dx = ax - px;
var dy = ay - py;
var ex = bx - px;
var ey = by - py;
var fx = cx - px;
var fy = cy - py;
var ap = dx * dx + dy * dy;
var bp = ex * ex + ey * ey;
var cp = fx * fx + fy * fy;
return dx * (ey * cp - bp * fy) -
dy * (ex * cp - bp * fx) +
ap * (ex * fy - ey * fx) < 0;
}
function circumradius(ax, ay, bx, by, cx, cy) {
var dx = bx - ax;
var dy = by - ay;
var ex = cx - ax;
var ey = cy - ay;
var bl = dx * dx + dy * dy;
var cl = ex * ex + ey * ey;
var d = 0.5 / (dx * ey - dy * ex);
var x = (ey * bl - dy * cl) * d;
var y = (dx * cl - ex * bl) * d;
return x * x + y * y;
}
function circumcenter(ax, ay, bx, by, cx, cy) {
var dx = bx - ax;
var dy = by - ay;
var ex = cx - ax;
var ey = cy - ay;
var bl = dx * dx + dy * dy;
var cl = ex * ex + ey * ey;
var d = 0.5 / (dx * ey - dy * ex);
var x = ax + (ey * bl - dy * cl) * d;
var y = ay + (dx * cl - ex * bl) * d;
return {x: x, y: y};
}
function quicksort(ids, dists, left, right) {
if (right - left <= 20) {
for (var i = left + 1; i <= right; i++) {
var temp = ids[i];
var tempDist = dists[temp];
var j = i - 1;
while (j >= left && dists[ids[j]] > tempDist) { ids[j + 1] = ids[j--]; }
ids[j + 1] = temp;
}
} else {
var median = (left + right) >> 1;
var i$1 = left + 1;
var j$1 = right;
swap(ids, median, i$1);
if (dists[ids[left]] > dists[ids[right]]) { swap(ids, left, right); }
if (dists[ids[i$1]] > dists[ids[right]]) { swap(ids, i$1, right); }
if (dists[ids[left]] > dists[ids[i$1]]) { swap(ids, left, i$1); }
var temp$1 = ids[i$1];
var tempDist$1 = dists[temp$1];
while (true) {
do { i$1++; } while (dists[ids[i$1]] < tempDist$1);
do { j$1--; } while (dists[ids[j$1]] > tempDist$1);
if (j$1 < i$1) { break; }
swap(ids, i$1, j$1);
}
ids[left + 1] = ids[j$1];
ids[j$1] = temp$1;
if (right - i$1 + 1 >= j$1 - left) {
quicksort(ids, dists, i$1, right);
quicksort(ids, dists, left, j$1 - 1);
} else {
quicksort(ids, dists, left, j$1 - 1);
quicksort(ids, dists, i$1, right);
}
}
}
function swap(arr, i, j) {
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
function defaultGetX(p) {
return p[0];
}
function defaultGetY(p) {
return p[1];
}
return Delaunator;
})));
//https://webglreport.com/?v=2
//https://victorbush.com/2015/01/tessellated-terrain/
//https://spite.github.io/rstats/
var folder = "17_50438_37354_50534_37450/satellite/";
var levels = [0x0B132B, 0x1C2541, 0x3A506B, 0x5BC0BE, 0x6FFFE9];
var mouseDown = false;
var renderer, scene, camera, controls, loader, terrain, glsl, uniforms, root, tree;
var colors = [0xFFFFFF, 0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF];
class Node{
constructor(level_, index_, centerX_, centerY_, width_, height_, resolution_){
this.level = level_;
this.index = index_;
this.w = width_;
this.h = height_;
this.x = centerX_;
this.y = centerY_;
this.resolution = resolution_;
this.lifetime = 128;
this.edges = this.getEdges();
}
getEdges = function(){
return [
new THREE.Vector3(this.x - this.w / 2, 0, this.y - this.h / 2),
new THREE.Vector3(this.x + this.w / 2, 0, this.y - this.h / 2),
new THREE.Vector3(this.x - this.w / 2, 0, this.y + this.h / 2),
new THREE.Vector3(this.x + this.w / 2, 0, this.y + this.h / 2)
];
}
}
class Quadtree{
constructor(root_, levels_, distance_){
var this_ = this;
this.levels = levels_;
this.distance = distance_;
this.root = root_;
this.nodes = [];
this.nodes = this.splitNode(0, this.root, false);
this.generateLevels();
this.last = [...this.nodes];
this.tiles = {};
this.debug = {};
this.points = [];
}
generateLevels = function(){
for(var i = 0; i < this.levels; i++){
var tmpNodes = [];
for(var j = 0; j < this.nodes.length; j++){
tmpNodes.push(...this.splitNode(j, this.nodes[j], true));
}
this.nodes = tmpNodes;
}
}
update = function(){
var this_ = this;
this.nodes = [];
this.nodes = this.splitNode(0, this.root, false);
this.generateLevels();
this.debug = {};
this.last = [...this.nodes];
}
splitNode = function(index_, parent_, check_){
if((parent_.level < this.levels && this.sqrtDistance(parent_) < this.distance) || !check_){
var lt = new Node(parent_.level + 1, { x: parent_.index.x * 2, y: parent_.index.y * 2 }, parent_.x - parent_.w / 4, parent_.y - parent_.h / 4, parent_.w / 2, parent_.h / 2, parent_.resolution / 2);
var rt = new Node(parent_.level + 1, { x: parent_.index.x * 2, y: parent_.index.y * 2 + 1 }, parent_.x + parent_.w / 4, parent_.y - parent_.h / 4, parent_.w / 2, parent_.h / 2, parent_.resolution / 2);
var lb = new Node(parent_.level + 1, { x: parent_.index.x * 2 + 1, y: parent_.index.y * 2 }, parent_.x - parent_.w / 4, parent_.y + parent_.h / 4, parent_.w / 2, parent_.h / 2, parent_.resolution / 2);
var rb = new Node(parent_.level + 1, { x: parent_.index.x * 2 + 1, y: parent_.index.y * 2 + 1 }, parent_.x + parent_.w / 4, parent_.y + parent_.h / 4, parent_.w / 2, parent_.h / 2, parent_.resolution / 2);
return [lt, rt, lb, rb];
}
return [parent_];
}
sqrtDistance = function(node_){
var target = new THREE.Vector2(camera.position.x, camera.position.z).lerp(new THREE.Vector2(controls.target.x, controls.target.z), 1.0);
var x1 = node_.x - node_.w / 2.0;
var y1 = node_.y - node_.h / 2.0;
var x2 = node_.x + node_.w / 2.0;
var y2 = node_.y + node_.h / 2.0;
var rx = (x1 + x2) / 2.0;
var ry = (y1 + y2) / 2.0;
var rwidth = node_.w;
var rheight = node_.h;
var dx = Math.max(Math.abs(target.x - rx) - rwidth / 2, 0);
var dy = Math.max(Math.abs(target.y - ry) - rheight / 2, 0);
return Math.sqrt(dx * dx + dy * dy);
}
}
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x000000);
document.body.appendChild(renderer.domElement);
scene = new THREE.Scene();
loader = new THREE.TextureLoader();
loader.crossOrigin = "";
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 51200);
camera.position.set(-2048, 2048, -2048);
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.screenSpacePanning = false;
controls.minDistance = 8;
controls.maxDistance = 5120;
controls.maxPolarAngle = Math.PI / 2;
camera.position.set(208.48355078304965, 45.28894677815297, 310.34089790619583);
controls.target.set(233.437242880138, -1.1266992511037067e-14, 279.779814968453);
var points = [
new THREE.Vector3(-1024, 0, -1024),
new THREE.Vector3(0, 0, -1024),
new THREE.Vector3(-1024, 0, 0),
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(0, 0, -1024),
new THREE.Vector3(1024, 0, -1024),
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(1024, 0, 0),
new THREE.Vector3(-1024, 0, 0),
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(-1024, 0, 1024),
new THREE.Vector3(0, 0, 1024),
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(1024, 0, 0),
new THREE.Vector3(0, 0, 1024),
new THREE.Vector3(1024, 0, 1024),
];
var geometry = new THREE.BufferGeometry().setFromPoints(points);
var indices = [];
//0-1
indices.push(0, 1, 3);
indices.push(3, 2, 0);
//2-3
indices.push(4, 5, 7);
indices.push(7, 6, 4);
//4-5
indices.push(8, 9, 11);
indices.push(11, 10, 8);
indices.push(12, 13, 15);
indices.push(15, 14, 12);
geometry.setIndex( indices );
geometry.addGroup(0, 6, 0);
geometry.addGroup(6, 6, 1);
geometry.addGroup(12, 6, 2);
geometry.addGroup(18, 6, 3);
var quad_uvs =
[
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0
];
uvs = new Float32Array(quad_uvs);
geometry.setAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
geometry.computeVertexNormals();
var materials = [
new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load("0_0.jpg")}),
new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load("1_0.jpg")}),
new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load("0_1.jpg")}),
new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load("1_1.jpg")})
];
var plane = new THREE.Mesh(geometry, materials);
plane.rotation.set(Math.PI, 0, 0);
scene.add(plane);
animate();
function animate(){
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
body { margin: 0; }
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>GLSL Intersection</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://unpkg.com/three#0.116.0/build/three.min.js"></script>
<script src="https://unpkg.com/three#0.116.0/examples/js/controls/OrbitControls.js"></script>
</head>
<body>
</body>
</html>

minecraft 1.8 gui slider issues

I recently started making a minecraft mod and i have a question regarding GUI's I want to create a slide, the only issue is the ButtonList.add(new GUISlider());
I don't understand the parameters, can someone explain them to me?
Thanks! :D
ok, I figured it out, you need to create a separate slider other than the default, then call it from there.
My Slider Code:
package tutorial.generic;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.renderer.GlStateManager;
import org.lwjgl.opengl.GL11;
public class GuiSliderFixed extends GuiButton {
public float sliderValue = 1.0F;
public float sliderMaxValue = 1.0F;
public float sliderMinValue = 1.0F;
public boolean dragging = false;
public String label;
public GuiSliderFixed(int id, int x, int y, String label, float startingValue, float maxValue, float minValue) {
super(id, x, y, 150, 20, label);
this.label = label;
this.sliderValue = startingValue;
this.sliderMaxValue = maxValue;
this.sliderMinValue = minValue;
}
protected int getHoverState(boolean par1) {
return 0;
}
#Override
public void drawButton(Minecraft mc, int mouseX, int mouseY)
{
if (this.visible)
{
FontRenderer fontrenderer = mc.fontRendererObj;
mc.getTextureManager().bindTexture(buttonTextures);
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
this.hovered = mouseX >= this.xPosition && mouseY >= this.yPosition && mouseX < this.xPosition + this.width && mouseY < this.yPosition + this.height;
int k = this.getHoverState(this.hovered);
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
GlStateManager.blendFunc(770, 771);
this.drawTexturedModalRect(this.xPosition, this.yPosition, 0, 46 + k * 20, this.width / 2, this.height);
this.drawTexturedModalRect(this.xPosition + this.width / 2, this.yPosition, 200 - this.width / 2, 46 + k * 20, this.width / 2, this.height);
this.mouseDragged(mc, mouseX, mouseY);
int l = 14737632;
if (packedFGColour != 0)
{
l = packedFGColour;
}
else if (!this.enabled)
{
l = 10526880;
}
else if (this.hovered)
{
l = 16777120;
}
this.drawCenteredString(fontrenderer, this.displayString, this.xPosition + this.width / 2, this.yPosition + (this.height - 8) / 2, l);
}
}
protected void mouseDragged(Minecraft par1Minecraft, int par2, int par3) {
if (this.enabled && this.visible && this.packedFGColour == 0) {
if (this.dragging) {
this.sliderValue = (float) (par2 - (this.xPosition + 4)) / (float) (this.width - 8);
if (this.sliderValue < 0.0F) {
this.sliderValue = 0.0F;
}
if (this.sliderValue > 1.0F) {
this.sliderValue = 1.0F;
}
}
this.displayString = label + ": " + (int) (sliderValue * sliderMaxValue);
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
this.drawTexturedModalRect(this.xPosition + (int) (this.sliderValue * (float) (this.width - 8)), this.yPosition, 0, 66, 4, 20);
this.drawTexturedModalRect(this.xPosition + (int) (this.sliderValue * (float) (this.width - 8)) + 4, this.yPosition, 196, 66, 4, 20);
}
}
public boolean mousePressed(Minecraft par1Minecraft, int par2, int par3) {
if (super.mousePressed(par1Minecraft, par2, par3)) {
this.sliderValue = (float) (par2 - (this.xPosition + 4)) / (float) (this.width - 8);
if (this.sliderValue < 0.0F) {
this.sliderValue = 0.0F;
}
if (this.sliderValue > 1.0F) {
this.sliderValue = 1.0F;
}
this.dragging = true;
return true;
} else {
return false;
}
}
public void mouseReleased(int par1, int par2) {
this.dragging = false;
}
}
My GUI Code:
package tutorial.generic;
import java.awt.Color;
import java.io.IOException;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiSlider;
import net.minecraft.client.gui.GuiTextField;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StatCollector;
import net.minecraft.world.World;
public class guiGenericTileEntity extends GuiScreen{
public static NBTTagCompound nameTag = new NBTTagCompound();
private int x, y, z;
private EntityPlayer player;
private World world;
private int xSize, ySize;
public static GuiTextField textField;
public static GuiSliderFixed mySlider;
public static NBTTagCompound maxSpeedTag = new NBTTagCompound();
public guiGenericTileEntity(EntityPlayer player, World world, int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
this.player = player;
this.world = world;
xSize = 176;
ySize = 214;
}
private ResourceLocation backgroundimage = new ResourceLocation(Generic.MODID.toLowerCase() + ":" + "textures/gui/guiBackGenericTileEntity.png");
#Override
public void drawScreen(int mouseX, int mouseY, float renderPartialTicks) {
this.mc.getTextureManager().bindTexture(backgroundimage);
int x = (this.width - xSize) / 2;
int y = (this.height - ySize) / 2;
drawTexturedModalRect(x, y, 0, 0, xSize, ySize);
fontRendererObj.drawString("MTTA System", (int) (width / 2 - (width / 13)), height / 15, 8);
fontRendererObj.drawString("Train Name :", (int) (width / 2 - (width / 13)), (int) (height / 7.8), 8);
fontRendererObj.drawString("Max Speed :", (int) (width / 2 - (width / 13)), (int) (height / 3.5), 8);
textField.drawTextBox();
super.drawScreen(mouseX, mouseY, renderPartialTicks);
}
#Override
public boolean doesGuiPauseGame() {
return false;
}
#Override
public void updateScreen(){
textField.updateCursorCounter();
super.updateScreen();
}
#Override
protected void keyTyped(char typedChar, int keyCode) throws IOException{
textField.textboxKeyTyped(typedChar, keyCode);
super.keyTyped(typedChar, keyCode);
}
#Override
public void initGui(){
buttonList.add(new GuiButton(1, (int) (xSize / 3 * 2.35), ySize - (ySize / 18), xSize - 20, height / 12, "Save And Close"));
mySlider = new GuiSliderFixed(3, width / 2 - 75, height / 3, "MPH ", 1.0F, 100.0F, 1.0F);
buttonList.add(mySlider);
mySlider.sliderValue = maxSpeedTag.getFloat("MaxSpeed");
textField = new GuiTextField(width / 2, fontRendererObj, width / 2 - 50, (int) (height / 6), 100, 20);
textField.setMaxStringLength(30);
textField.setText(nameTag.getString("Name"));
textField.setFocused(true);
textField.setCanLoseFocus(false);
super.initGui();
}
#Override
protected void actionPerformed(GuiButton guibutton) {
//id is the id you give your button
switch(guibutton.id) {
case 1:
player.closeScreen();
nameTag.setString("Name", textField.getText());
maxSpeedTag.setFloat("MaxSpeed", mySlider.sliderValue);
genericTileEntity.processActivate(player, world);
player.addChatMessage(new ChatComponentText("Saved the current settings for " + textField.getText() + "!"));
break;
}
//Packet code here
//PacketDispatcher.sendPacketToServer(packet); //send packet
}
}
Calling the new Slider works like this:
create a new GuiSliderFixed in the GUI code ---> example: ---> GuiSliderFixed mySlider = new GuiSliderFixed();
set the Parameters to this (int id, int x, int y, String label, float statingValue, float maxValue, float minValue) ---> example: ---> GuiSliderFixed mySlider = new GuiSliderFixed(3, width / 2 - 75, height / 3, "MPH ", 1.0F, 100.0F, 1.0F);
add it to buttonList ---> example ---> buttonList.add(mySlider);
Hope This Helps!

Resources