I am working to reduce size of an Equirectangular map, losslessly. Upon optimizing the SVG images with use of an online tool I am unsure whether any of the shapes overlap (hereby in this state of matter asserting a reality that is either conflicting or less relevant). Regardless of any one of the processing methods which applies to this image, I am simply assuming that multiplicity of straight(ened) lines among coordinates on the given map are best optimized with use of polynomial functions, composites and/or derivates thereof (such as splines or bezier curves, as defined with XML/SVG).
I am looking for a list of mathematical methods to use -- in order to figure out points where any of the neighbouring SVG polygons overlap. I expect to transform shapes upon discovering the most proper mathematics, so that two polynoms of any two shapes on map will only intersect in one point, at most (most likely so). In other words, any intersection will not exceed an area of zero and will match properties of either a zero-dimensional object (a point), or an infinite and limited series thereof (a line).
// See me write best code, because this is like the yellow cake topping of global standards
Import {
Uniform_Resource_Identifier as URI,
Uniform_Resource_Locator as URL
} from "#jsonion/RegularExpressions://wikipedia/en";
Import {
QualifiedName as QName
} from "#jsonion://www.w3.org/2001/tag/doc/qnameids"
Import {
Optional as Opt
} from "#jsonion://github.com/aldeed/simpl-schema"
Import { parseType, evaluateArgs, oneOf } from "jsonion/lib"
//
// Behind the scenes is a seamless SVGn archive of ```js onion ˙˙˙ sliced domesticated codebase from the interwebs
// … the sky's an umbrella term to everything we know & it comes in the shape of thy heartest sun -- there really is no end to it
//
// Look, a meteor shower surrounds a light source and its satellite
// .* //
var jsonion = {
loadRes: function (args, inputSchema = {
expr: "loadResource",
__location: {
uri: [URI, QName, oneOf],
href: [URL],
...oneOf
},
mirror: [URL, Opt]
})
{
/* … */
return ( var err = evaluateArgs( args, inputSchema )
? err.push("Li{B")
: "undefined" // … brb, get me a postMessage() method native to foreignObject
},
findMeOverlappingShapes: ( args = {
asd: "sdf",
foo: "bar"
}) =>
{
}
}
May I kindly request for this favour -- so to compile a JS fiddle or a Git commit which I can recall with ease of mind and think about, even while I do seemingly unrelated stuff (ie. slicing onions for a vegan pizza).
Can you please forward to me some of the fine online sources, whether be it aligned with any or all of the following... one that you would cite yourself; one with a good example (and corridors to lead through gaps of interlaced but distinct knowledge bodies); one that you expect to stay online and maintained for the longer period of time (with a disambiguation protocol for future reference)
I don't spell out mathematics as much as I do web coding, so thank you all so much!
PS, I will share my recipe for a cheese pizza topping which doesn't boil in a heated oven, embedded in the forementioned code pen/snippet, as promised
… that's a fully vegan or an ovo-vegetarian recipe, but of course I'll choose one of these types only after I study and understand sources in reference
Related
A few months ago I made a small terrain generator, like Minecraft, for a school project.
The way I did this was by using multiple chunks. Each chunk contained a 3-dimensional array that stored the blocks.
Every position in this array corresponded with the position of the block it contained.
blocks[x, y, z] = new Block();
Now I would like to add different sizes if blocks. However, I can't do that with the way I am storing the blocks right now, because bigger blocks would have to be spread over multiple positions in the 3-dimensional array.
An example of a game with different sizes of blocks (and different shapes) is LEGO Worlds. How does a game like this store all these little blocks?
I hope someone can help me with this.
The language I am using is Javascript in combination with WebGL.
Thanks in advance!
In my experience there are a few different ways of tackling an issue like this, but the one I'd recommend would depend on the amount of time you have to work on this and the scope (how big) you wanted to make this game.
Your Current Approach
At the moment I think your using what most people would consider the most straightforward approach by storing the voxels in a 3D grid
[Source].
But two problems you seem to be having is that there isn't an obvious way to create blocks that are bigger then 1x1 and that a 3D grid for a world space is fairly inefficient in terms of memory usage (As for an array you have to have memory allocated for every cell, including empty space. JavaScript is no different).
An Alternative Approach
An alternative to using a 3D array would be to instead use a different data structure, the full name being a sparse voxel octree.
This to put it simply is a tree data structure that works by subdividing an area of space until everything has been stored.
The 2D form of this where a square sub divides into four smaller quadrants is called a quad tree and likewise a 3D equivalent divides into eight quadrants, called an octree. This approach is generally preferable when possible as its much more efficient because the trees only occupy more memory when its absolutely essential and they can also be packed into a 1D array (Technically a 3D array can be too).
A common tactic used with quad/octrees in some block based games is to take a region of the same kind of voxel that fit into one larger quadrant of the tree is to simply stop sub division there, as there's no reason to go deeper if all the data is the same.
The other optimization they can make is called sparse where regions of empty space (air) are simply deleted since empty space doesn't do anything special and its location can be inferred.
[SVO Source]
[Z Order Curve Source]
Recommended Approach
Unless you have a few months to complete your game and you're at university I seriously wouldn't recommend an SVO (Though reading up about could impress any teachers you have). Instead I'd recommend taking the same approach that Minecraft appears to visibly has. E.G. A door is 1X2 but blocks can only be 1x1, then just make it two blocks.
In the example of a door you would have four unique blocks in total, two for the upper and lower half, and two variations of each being opened or closed.
E.G.
var cubeProgram; // shader program
var cubeVBO; // vertex buffer (I recommend combining vertex & UV coords)
var gl; // rendering context
// Preset list of block ID's
var BLOCK_TYPES = {
DOOR_LOWER_OPEN: 0,
DOOR_UPPER_OPEN: 1,
DOOR_LOWER_CLOSED: 2,
DOOR_UPPER_CLOSED: 3,
}
var BLOCK_MESHES = {
GENERIC_VBO: null,
DOOR_UPPER_VBO: null
DOOR_LOWER_VBO: null
}
// Declare a Door class using ES6 syntax
class Door {
// Assume X & Y are the lower half of the door
constructor(x,y,map) {
if (y - 1 > -1) {
console.error("Error: Top half of the door goes outside the map");
return;
}
this.x = x;
this.y = y;
map[x][y ] = BLOCK_TYPES.DOOR_LOWER_OPEN;
map[x][y-1] = BLOCK_TYPES.DOOR_UPPER_OPEN;
}
}
With the prototype code below I'm adding a lot of features in steps into an osm.
I'm loading about 8500 multipolygon features into it. Some of them have a lot of coordinates so that's round about 150MB of textual data in total.
Loading them one by one leads to a crash of the browser. Loading it in chunks works but it is not fast either. Especially if you want to scroll or zoom after the loading has finished.
I'm a bit shy about loading it all in one go as that's 150MB of data.
What options do I have to improve the experience? To be clear: I'm not talking about the loading itself. I'm talking about the rendering of the map with the features.
Here is the code stub:
addToMap = function (id, totalCount) {
var idTo = id+99;
jQuery.get('getData.php', {id: id, idTo: idTo}, function (result) {
var geojson;
function onEachFeature(feature, layer) {
layer.on({
mouseover: highlightFeature,
mouseout: resetHighlight,
click: zoomToFeature
});
}
function resetHighlight(e) {
geojson.resetStyle(e.target);
info.update();
}
geojson = L.geoJson(result, {
style: getStyle,
onEachFeature: onEachFeature
}).addTo(map);
if (id < totalCount) {
jQuery('#count').html(idTo+' of '+totalCount);
addToMap(idTo+1, totalCount);
} else {
jQuery('#loader').remove();
}
}, 'json');
}
The secret to render a lot of stuff very very fast is... to not render a lot of stuff.
This might seem contradictory, but in reality it's very simple. You don't need to render everything, you just need to render:
Stuff which is inside the screen (plus a bit of an out-of-the-screen margin)
Stuff which measures less than one pixel (because nobody will ever notice subpixel artifacts)
By default, Leaflet does in fact simplify the vector geometries to save some time (douglas-peucker up to a couple of pixels), but it simplifies all the geometries (which is computationally expensive) and renders based only in the geometries' bounding boxes (which renders big geometries which are not visible, and renders all the points of big geometries for which only a tiny bit is visible).
Fortunately a couple of recent developments help with that: vector tiles and geojson-vt. Do read https://www.mapbox.com/blog/introducing-geojson-vt/
The general idea is that the dataset is subject to a precomputation step (which takes a non-trivial amount of time but can be done off-thread), slicing the data up into tiles. Slicing in tiles means that only the visible part of big geometries will be shown, saving huge amounts of time. It will also run some line simplification, depending on the level of the tile pyramid.
These map tiles follow the same standard than raster tiles, so the visibility algorithms can be shared around.
To the best of my knowledge, there is only one working implementation of geojson-vt and Leaflet: Leaflet.VectorGrid (or you can check the plugins list, which might contain more related plugins in the future). I suggest you have a look at it.
In addition to the other answers:
Convert your GeoJson to TopoJson to reduce the size of it. Here is one utility to do it - https://github.com/topojson/topojson
Based on your zoom level, display only parts of the features that are important or large enough. (as IvanSanchez wrote)
Well, how much of your stuff needs to be a feature? I'm getting around the same problem by rendering features as raster map tiles with transparency and then displaying them in a stack. This way users can still switch off certain things. Since you're rendering them from vector, it will still look great at any zoom level. It's also far more efficient!
I am writing a text based game where I want users to be able to manipulate any item.
I want the user to be able to say, for example, "I throw the bottle of oil at the monster."
Now when this happens [throw] will be an action, [bottle of oil] is an inventory item with the property [contains oil], and the monster will be the nearest monster in the room unless specified further.
Code needs to analyze the various properties of all these things and then pick actions that cause those things to interact.
When i write the Game story code it will be like follows
*room.darkroom.1 "wake up" [...] everything appears blurry, the voice sounds strange as if echoing down a long tunnel. From what you can see you can tell [you are in a dark room] your vision blurs from white to dark. [pc is inside very dark room. Inside this room everything is hidden in darkness. The northern wall has a locked thick wooden door. the southern wall has a barrel full of oil containing a bottle of oil. In the eastern side of the room are 2 medium sized crates one crate contains flint and rusty dagger. In the western side of the room a [small window] */room.darkroom.1
The script will take all those words and apply properties to them randomizing certain elements that are left unstated. So if you then say "chair" it will go to the chair properties and randomly assign unstated properties. One property of chair will be material. If its not stated that its an oak chair then the script should pick from any of the material properties and assign them. This new chair will pick up a few properties and be saved for future reference on the database with all properties.
Another property would be an action. A chair would not necessarily have an action .. but it might break. The script needs to know if the chair is breakable. But I am thinking that could be nested into another property like [toughness].
Many things will have many of the same properties: chair, night stand, table would all be similar in many ways. But they would also have different outcomes depending on the actions applied to them.
How do I specify for instance when "broken" contains chair legs and scrap material? The chair legs and the scrap material would both need to inherit the properties of the chair that was destroyed, such as oak / flammable / breakable. Obviously, as stated before, it might not have to inherit flammable or breakable if oak is the part that holds that value.
I want to make it easy to access the array that stores properties and that might include a script that effects behavior and descriptions of things.
I started to just create a keyed array which would be looped through... But now I am thinking that I should utilize the object based element of JavaScript.
Here is what i have started to do but I stopped right away:
var language = {
// key currentmodifyers possible modifyers action/condition description of item
item: ";medium,material;;its a thing thats not a person",
chair: "item,chair_Legs;;pile_of.#scraps.collection.chairlegx3/broken,#[chair ]scraps/destroyed; and someone could sit on it. ",
chair_leg:"item,blunt,light,"
}
I have so many definitions to write so it would be a shame to start writing it all and then have to do it over when I discover the best way.
I am looking at various ways to build objects in JavaScript, but would like the best way from someone experienced.
Understanding the complexity of my problem, what is the best way to store and apply properties?
There are actually two good thoughts in your question:
But now I am thinking that I should utilize the object based element of JavaScript.
You definitely need to use objects instead of arrays, the OOP ideas can be directly applied to your descriptions.
Some objects are composed of smaller parts (the "composition" in OOP) and some inherit properties of other objects (the "inheritance").
So you could have some base Item class which defines basic operations and properties for all objects (like they have different properties and can do some things).
Then you can add objects like StaticItem (will be base for chairs, night stands, etc) and LiveBeeing (monsters, etc).
And now you can actually create the Chair (pseudocode):
StaticItem extends Item
this.material = oak // oak is an object of OakMaterial
// is this static item flamable?
this.isFlamable = function() {
// we "redirect" flamability detection to the material
return this.material.flamable();
}
Chair extends Static
// break this chair!
this.break = function() {
// when it is broken we return a HeapOfCrap, it is a
// Static subclass which contains some sub-items
// In this case the heap contains 4 chair legs of the
// same material as the chair
return HeapOfCrap([
new ChairLeg(this.material), new ChairLeg(this.material),
new ChairLeg(this.material), new ChairLeg(this.material)
])
}
And so on, you need to plan you object structure carefully and there is a good field to apply some of the design patterns.
The example above is just what came in my mind immediately, while actual design should take much more time and thinking.
The second good thought in your question is about the huge amount of work:
I have so many definitions to write so it would be a shame to start writing it all and then have to do it over when I discover the best way.
You absolutely right here, would you select to use objects or arrays, or anything else - don't try to describe all your game right away.
Select few basic elements, like "Room", "Door", "Chair", "Monster", "Player" and try to code the minimal game with only these elements.
Play with the structure to find the good design and once you are sure it is good - go on and add more elements to the game.
On this example we can move inside a field of spheres but into certain limits. I want to be able to move infinitely among them. How can I do that ?
The trick is to reuse the spheres that are behind the camera and put them in front of it. Look at how it is done in this example. Here the programmer knows that the user will continue in the same direction so he removes the trees that come at a certain position.
If you use something like the example you quoted, you cannot know which direction the user will take. And so, you can use the same trick, but have to code it an other way. The most obvious is to check the distances with all the spheres regularly, if the user moves. If one sphere is too far behind the camera, you mirror it so it faces the camera, behind the fog.
'Regularly' can mean two things depending on your real number of spheres in your scene :
If you have a small scene and few spheres you can check those distances in your render loop. Neither cheap nor useful, 60 per seconds, but that can be the first coding step
Then the best way would be to use a web worker : you send the positions of the camera and those of the spheres, you let the worker compute all the stuff in its thread, and send instructions back : 'move those spheres to those positions'. Every seconds is more reasonable in the threejs example, but up to you to decide that depending on your scene.
NOTE : if you have a lot of spheres, or any meshes you use instead, like more than 20-30, having a mesh for each of them will slower performances. With few trees on the examples i linked it is ok, but with more objects and/or a heavier scene,
think about merging them all in a single geometry. You can check which sphere is where by deducing from the vertices indices, or adding an attribute that defines each sphere.
this will also impact the worker delay : it will have more to compute so it will need more time.
NOTE 2 : Note 1 would of course delete the level of details that the example aims to illustrate :) (Unless you also implement your own while checking the distances of the spheres....)
If you want to have an illusion of infinite world then you could:
Break your world space into regions (for example cubes).
Detect which region you are currently in.
Make sure you have objects (spheres) in neighbour regions. If some of regions are empty - fix it.
Clear regions which are not needed anymore.
For this you might want to have some class like this:
Class Region {
bool isEmpty = true;
Vector3 center;
float radius; // or 'range'
Array<Sphere> = null; // storage of your objects
// constructors / destructor
generateObjects(params); // perlin noise might be helpful there
removeObjects();
}
and do something like this periodically:
void updateRegions() {
computeClosestGridCoord(myPosition); // which is center of your current region
lookForNeighbourRegions(regionsArray); // and add new Region if needed
deleteOldRegionsStuff(regionsArray);
}
I am creating a video game based on Node.js/WebGL/Canvas/PIXI.js.
In this game, blocks have a generic size: they can be circles, polygons, or everything. So, my physical engine needs to know where exactly the things are, what pixels are walls and what pixels are not. Since I think PIXI don't allow this, I create an invisible canvas where I put all the wall's images of the map. Then, I use the function getImageData to create a function "isWall" at (x, y):
function isWall(x, y):
return canvas.getImageData(x, y, 1, 1).data[3] != 0;
However, this is very slow (it takes up to 70% of the CPU time of the game, according to Chrome profiling). Also, since I introduced this function, I sometimes got the error "Oops, WebGL crashed" without any additional advice.
Is there a better method to access the value of the pixel? I thought about storing everything in a static bit array (walls have a fixed size), with 1 corresponding to a wall and 0 to a non-wall. Is it reasonable to have a 10-million-cells array in memory?
Some thoughts:
For first check: Use collision regions for all of your objects. The regions can even be defined for each side depending on shape (ie. complex shapes). Only check for collisions inside intersecting regions.
Use half resolution for hit-test bitmaps (or even 25% if your scenario allow). Our brains are not capable of detecting pixel-accurate collisions when things are moving so this can be taken advantage of.
For complex shapes, pre-store the whole bitmap for it (based on its region(s)) but transform it to a single value typed array like Uint8Array with high and low values (re-use this instead of getting one and one pixels via the context). Subtract object's position and use the result as a delta for your shape region, then hit-testing the "bitmap". If the shape rotates, transform incoming check points accordingly (there is probably a sweet-spot here where updating bitmap becomes faster than transforming a bunch of points etc. You need to test for your scenario).
For close-to-square shaped objects do a compromise and use a simple rectangle check
For circles and ellipses use un-squared values to check distances for radius.
In some cases you can perhaps use collision predictions which you calculate before the games starts and when knowing all objects positions, directions and velocities (calculate the complete motion path, find intersections for those paths, calculate time/distance to those intersections). If your objects change direction etc. due to other events during their path, this will of course not work so well (or try and see if re-calculating is beneficial or not).
I'm sure why you would need 10m stored in memory, it's doable though - but you will need to use something like a quad-tree and split the array up, so it becomes efficient to look up a pixel state. IMO you will only need to store "bits" for the complex shapes, and you can limit it further by defining multiple regions per shape. For simpler shapes just use vectors (rectangles, radius/distance). Do performance tests often to find the right balance.
In any case - these sort of things has to be hand-optimized for the very scenario, so this is just a general take on it. Other factors will affect the approach such as high velocities, rotation, reflection etc. and it will quickly become very broad. Hope this gives some input though.
I use bit arrays to store 0 || 1 info and it works very well.
The information is stored compactly and gets/sets are very fast.
Here is the bit library I use:
https://github.com/drslump/Bits-js/blob/master/lib/Bits.js
I've not tried with 10m bits so you'll have to try it on your own dataset.
The solution you propose is very "flat", meaning each pixel must have a corresponding bit. This results in a large amount of memory being required--even if information is stored as bits.
An alternative testing data ranges instead of testing each pixel:
If the number of wall pixels is small versus the total number of pixels you might try storing each wall as a series of "runs". For example, a wall run might be stored in an object like this (warning: untested code!):
// an object containing all horizontal wall runs
var xRuns={}
// an object containing all vertical wall runs
var yRuns={}
// define a wall that runs on y=50 from x=100 to x=185
// and then runs on x=185 from y=50 to y=225
var y=50;
var x=185;
if(!xRuns[y]){ xRuns[y]=[]; }
xRuns[y].push({start:100,end:185});
if(!yRuns[x]){ yRuns[x]=[]; }
yRuns[x].push({start:50,end:225});
Then you can quickly test an [x,y] against the wall runs like this (warning untested code!):
function isWall(x,y){
if(xRuns[y]){
var a=xRuns[y];
var i=a.length;
do while(i--){
var run=a[i];
if(x>=run.start && x<=run.end){return(true);}
}
}
if(yRuns[x]){
var a=yRuns[x];
var i=a.length;
do while(i--){
var run=a[i];
if(y>=run.start && y<=run.end){return(true);}
}
}
return(false);
}
This should require very few tests because the x & y exactly specify which array of xRuns and yRuns need to be tested.
It may (or may not) be faster than testing the "flat" model because there is overhead getting to the specified element of the flat model. You'd have to perf test using both methods.
The wall-run method would likely require much less memory.
Hope this helps...Keep in mind the wall-run alternative is just off the top of my head and probably requires tweaking ;-)