Unity TerrainData not compatible with absolute elevations? - unity3d

Is it possible for the Unity TerrainData structure to take absolute elevations? I have a terrain generator that generates absolute elevations, but they are huge. The perlin octave with the highest amplitude is the one that decides what altitude the entire map is at, with an amplitude of 2500 and wavelength 10000. In order for my map to tile properly and transition between altitudes seamlessly, I need to be able to use this system of absolute altitude. I would scale down my generator's output to fit in the limited space (between 0 and 1), and stretch the y scale of the TerrainData, but it will lose too much precision.
What can I do? Is there a way I can use elevations that may vary by as much as 2500 meters?
One thing that might be important is that there will never be that much variation in the space of a single Terrain object, but across many, many Terrain objects, it is possible for the player to traverse that kind of altitude.

I've tested changing different variables, and I've reached the following conclusion...
Heightmap Resolution does not mean precision of data (some people I asked believed it determined the number of possible height values). It means the number of samples per row and column. This, along with size determines how far apart samples are, and effectively how large the polygons of the terrain are. It's my impression that there is no way to improve precision, although I now know how to increase the height of the terrain object. Instead, since I will never have 2500 meters of elevation difference in the same terrain object, each piece of terrain generated by my generator I will put in a terrain object that is positioned and sized to contain all of the data in that square. The data will also have to be converted so that it will fit, but other than that, I see no drawbacks to this method.
Important note: Resolution must be 2^n + 1 where n is any number. If you provide a different value for resolution, the next permitted value down will be selected (always the one below your choice).

Related

Change the scale of pixels to non-square dimensions in GEE

I want to export an image in Google Earth Engine and I want the pixel size to match some in-situ plots with dimensions 2mx30m. How can I set the scale parameter to match this diamesions?
What I currently have (for pixel size 30mx30m):
var myimage= sat_image.reduceRegions(my_points, ee.Reducer.first(),30)
print(myimage)
Export.table.toDrive(myimage,
"pts30",
"insitu_points")
Instead of specifying the scale parameter, specify a crsTransform parameter. It is a “a row-major ordering of the 3x2 transform matrix”, as the documentation puts it, which means that you should specify a list of numbers like
crsTransform=[xScaling, 0, 0, 0, yScaling, 0]
Note that these numbers are not the same as the scale parameter. The scale parameter specifies meters of nominal scale per pixel. These number specify distance in the projection's coordinate system per pixel. For example, if the projection's numerical units are degrees, then the crsTransform factors are degrees per pixel. Thus, it is usually a good idea to specify a crs together with crsTransform so that you know what projection you're measuring with.
Also, this may not be the best option for such very non-square pixels. Consider, instead of using reduceRegions on points, converting your points to rectangle features and then using reduceRegion with a mean reducer. This will have a similar effect, but lets you choose the exact shape you want to sample with.
I'm not sure how well either option will work or whether there are further issues to deal with — I haven't done anything like this myself. But I looked around and there is very little discussion crsTransform at all, so I figured it was worth writing up.

3d reconstruction from 2 views

I'm doing some study on the 3d reconstruction from two views and fixed known camera focal length. Something that is unclear to me is does triangulation gives us the real world scale of an object or the scale of the result is different to the actual one? If the scale is different than the actual size, how can I find the depth of points from it? I was wondering if there is more information that I need to create a real world scale of object.
Scale is arbitrary in SfM tasks so the result may be different in every reconstruction since points are initially projected on a random depth value.
You need at least one known distance in your scene to recover the absolute (real-world) scale. You can include one object with known size in your scene so you will be able to convert your scale afterwards.

Hashing a graph to find duplicates (including rotated and reflected versions)

I am making a game that involves solving a path through graphs. Depending on the size of the graph this can take a little while so I want to cache my results.
This has me looking for an algorithm to hash a graph to find duplicates.
This is straightforward for exact copies of a graph, I simply use the node positions relative to the top corner. It becomes quite a bit more complicated for rotated or even reflected graphs. I suspect this isn't a new problem, but I'm unsure of what the terminology for it is?
My specific case is on a grid, so a node (if present) will always be connected to its four neighbors, north, south, east and west. In my current implementation each node stores an array of its adjacent nodes.
Suggestions for further reading or even complete algorithms are much appreciated.
My current hashing implementation starts at the first found node in the graph which depends on how i iterate over the playfield, then notes the position of all nodes relative to it. The base graph will have a hash that might be something like: 0:1,0:2,1:2,1:3,-1:1,
I suggest you do this:
Make a function to generate a hash for any graph, position-independent. It sounds like you already have this.
When you first generate the pathfinding solution for a graph, cache it by the hash for that graph...
...Then also generate the 7 other unique forms of that graph (rotated 90deg; rotated 270deg; flipped x; flipped y; flipped x & y; flipped along one diagonal axis; flipped along the other diagonal axis). You can of course generate these using simple vector/matrix transformations. For each of these 7 transformed graphs, you also generate that graph's hash, and cache the same pathfinding solution (which you first apply the same transform to, so the solution maps appropriately to the new graph configuration).
You're done. Later your code will look up the pathfinding solution for a graph, and even if it's an alternate (rotated, flipped) form of the graph you found the earlier solution for, the cache already contains the correct solution.
I spent some time this morning thinking about this and I think this is probably the most optimal solution. But I'll share the other over-analyzed versions of the solution that I was also thinking about...
I was considering the fact that what you really needed was a function that would take a graph G, and return the "canonical version" of G (which I'll call G'), AND the transform matrix required to convert G to G'. (It seemed like you would need the transform so you could apply it to the pathfinding data and get the correct path for G, since you would have just stored the pathfinding data for G'.) You could, of course, look up pathfinding data for G', apply the transform matrix to it, and have your pathfinding solution.
The problem is that I don't think there's any unambiguous and performant way to determine a "canonical version" of G, because it means you have to recognize all 8 variants of G and always pick the same one as G' based on some criteria. I thought I could do something clever by looking at each axis of the graph, counting the number of points along each row/column in that axis, and then rotating/flipping to put the more imbalanced half of the axis always in the top-or-left... in other words, if you pass in "d", "q", "b", "d", "p", etc. shapes, you would always get back the "p" shape (where the imbalance is towards the top-left). This would have the nice property that it should recognize when the graph was symmetrical along a given axis, and not bother to distinguish between the flipped versions on that axis, since they were the same.
So basically I just took the row-by-row/column-by-column point counts, counting the points in each half of the shape, and then rotating/flipping until the count is higher in the top-left. (Note that it doesn't matter that the count would sometimes be the same for different shapes, because all the function was concerned with was transforming the shape into a single canonical version out of all the different possible permutations.)
Where it fell down for me was deciding which axis was which in the canonical case - basically handling the case of whether to invert along the diagonal axis. Once again, for shapes that are symmetrical about a diagonal axis, the function should recognize this and not care; for any other case, it should have a criteria for saying "the axis of the shape that has the property [???] is, in the canonical version, the x axis of the shape, while the other axis will be the y axis". And without this kind of criteria, you can't distinguish two graphs that are flipped about the diagonal axis (e.g. "p" versus "σ"/sigma). The criteria I was trying to use was again "imbalance", but this turned out to be harder and harder to determine, at least the way I was approaching it. (Maybe I should have just applied the technique I was using for the x/y axes to the diagonal axes? I haven't thought through how that would work.) If you wanted to go with such a solution, you'd either need to solve this problem I failed to solve, or else give up on worrying about treating versions that are flipped about the diagonal axis as equivalent.
Although I was trying to focus on solutions that just involved calculating simple sums, I realized that even this kind of summing is going to end up being somewhat expensive to do (especially on large graphs) at runtime in pathfinding code (which needs to be as performant as possible, and which is the real point of your problem). In other words I realized that we were probably both overthinking it. You're much better off just taking a slight hit on the initial caching side and then having lightning-fast lookups based on the graph's position-independent hash, which also seems like a pretty foolproof solution as well.
Based on the twitter conversation, let me rephrase the problem (I hope I got it right):
How to compare graphs (planar, on a grid) that are treated as invariant under 90deg rotations and reflection. Bonus points if it uses hashes.
I don't have a full answer for you, but a few ideas that might be helpful:
Divide the problem into subproblems that are independently solvable. That would make
How to compare the graphs given the invariance conditions
How to transform them into a canonical basis
How to hash this canonical basis subject to tradeoffs (speed, size, collisions, ...)
You could try to solve 1 and 2 in a singe step. A naive geometric approach could be as follows:
For rotation invariance, you could try to count the edges in each direction and rotate the graph so that the major direction always point to the right. If there is no main direction you could see the graph as a point cloud of its vertices and use Eigenvectors and Priciple Compoment Analysis (PCA) to obtain the main direction and rotate it accordingly.
I don't have a smart solution for the reflection problem. My brute force way would be to just create the reflected graph all the time. Say you have a graph g and the reflected graph r(g). If you want to know if some other graph h == g you have to answer h == g || h == r(g).
Now onto the hashing:
For the hashing you probably have to trade off speed, size and collisions. If you just use the string of edges, you are high on speed and size and low on collisions. If you just take this string and apply some generic string hasher to it, you get different results.
If you use a short hash, with more frequent collisions, you can get achieve a rather small cost for comparing non matching graphs. The cost for matching graphs is a bit higher then, as you have to do a full comparison to see if they actually match.
Hope this makes some kind of sense...
best, Simon
update: another thought on the rotation problem if the edges don't give a clear winner: Compute the center of mass of the vertices and see to which side of the center of the bounding box it falls. Rotate accordingly.

Spatial data visualization level of detail

I have a 3D point cloud data set with different attributes that I visualize as points so far, and I want to have LOD based on distance from the set. I want to be able to have a generalized view from far away with fewer and larger points, and as I zoom in I want a more points correctly spaced out appearing automatically.
Kind of like this video below, behavior wise: http://vimeo.com/61148577
I thought one solution would be to use an adaptive octree, but I'm not sure if that is a good solution. I've been looking into hierarchical clustering with seamless transitions, but I'm not sure which solution I should go with that fits my goal.
Any ideas, tips on where to start? Or some specific method?
Thanks
The video you linked uses 2D metaballs. When metaballs clump together, they form blobs, not larger circles. Are you okay with that?
You should read an intro to metaballs before continuing. Just google 2D metaballs.
So, hopefully you've read about metaball threshold values and falloff functions. Your falloff function should have a radius--a distance at which the function falls to zero.
We can achieve an LOD effect by tuning the threshold and the radius. Basically, as you zoom out, increase radius so that points have influence over a larger area and start to clump together. Also, adjust threshold so that areas with insufficient density of points start to disappear.
I found this existing jsfiddle 2D metaballs demo and I've modified it to showcase LOD:
LOD 0: Individual points as circles. (http://jsfiddle.net/TscNZ/370/)
LOD 1: Isolated points start to shrink, but clusters of points start to form blobs. (http://jsfiddle.net/TscNZ/374/)
LOD 2: Isolated points have disappeared. Blobs are fewer and larger. (change above URL to jsfiddle revision 377)
LOD 3: Blobs are even fewer and even larger. (change above URL to jsfiddle revision 380)
As you can see in the different jsfiddle revisions, changing LOD just requires tuning a few variables:
threshold = 1,
max_alpha = 1,
point_radius = 10,
A crucial point that many metaballs articles don't touch on: you need to use a convention where only values above your threshold are considered "inside" the metaball. Then, when zoomed far out, you need to set your threshold value above the peak value of your falloff function. This will cause an isolated point to disappear completely, leaving only clumps visible.
Rendering metaballs is a whole topic in itself. This jsfiddle demo takes a very inefficient brute-force approach, but there's also the more efficient "marching squares".

fractal microscope simulator

I've done work on software used for controlling imaging hardware, such as microscopes, that are sometimes hard to get time on. This means it is difficult to test out new/different algorithms which would require access to the instrument. I'd like to create a synthetic instrument that could be used for some of these testing purposes, and I was thinking of using some kind of fractal image generation to create the synthetic images. The key would be to be able to generate features at many different 'magnifications' and locations in some sort of deterministic manner. This is because some of the algorithms being tested may need to pan/zoom and relocate previously 'imaged' areas. Onto these base images I can then apply whatever instrument 'defects' are appropriate (focus, noise, saturation, etc.).
I'm at a bit of a loss on how to select/implement a good fractal algorithm for the base image. Any help would be appreciated. Preferably it would have the following qualities:
Be fast at rendering new image areas.
Fairly wide 'feature' coverage at as many locations and scales as possible.
Be deterministic (but initialized from random starting parameters).
Ability to tune to make images look more like 'real' images.
Item 2 is important, for example a mandelbrot set, with its large smooth/empty regions, might not be good since the software controlling the synthetic scope might fall into one of these areas.
So far I've thought of using something like a mandelbrot, but randomly shifting/rotating/scaling and merging two or more fractal sets to get more complete 'feature' coverage.
I've also seen images of the fractal flame algorithms and they seem to generate images that might be useful (and nice to look at).
Finally, I've thought of using some sort of paused particle simulation run to generate images that are more cell-like (my current imaging target), but I'm not sure if this approach can be made to work with the other requirements.
Edit:
#Jeffrey - So it sounds like some kind of terrain generation might be the way to go, as long as I have complete control over the PSRNG. Perhaps I can use some stored initial seed + x position + y position to generate my random numbers? But then I am unsure of how to consistently generate the terrains across scales, except, as you mentioned, to create the base terrain at the coursest scale, and at certain pre-determined 'magnifications' add new deterministic pseudo-random variations to this base. I'd also have to be careful about when to generate the next level of terrain, since if I'm too aggressive I'd have to generate and integrate the results appropriately for display at the coarser level... This is why I initially was leaning toward a more 'traditional' fractal, since this integration from finer scales would be handled more implicitly (I think).
The idea behind a fractal terrain creation algorithm is to build the image at each scale separately. For a landscape it's easy: just make a small array of height values, and set them randomly. Then scale it up to a larger array, averaging the values so that the contour is smooth, and then add small random amounts to those values. Then scale it up, etc. The original small bumps have become mountains, and they are filled with complex terrain.
There are two particular difficulties with the problem posed here, though. First, you don't want to store any of these values, since it would be potentially huge. Secondly, the features at each scale are of a different kind than the features at other scales.
These problems are not insurmountable.
Basically, you would divide the image up into a grid, and using deterministic psedorandom numbers establish the key features of each square in the grid. For example, each square could have a certain density of cell types.
At the next level of magnification, subdivide each square into another grid, apply a gradiant of values across the grid that is based on the values of the containing square and its surrounding squares. Then apply pseudorandom variations to that seeded with the containing square's grid coordinates. For the random seed, always use the coordinates of the immediately containing square of the subdivision under consideration regardless of where the image is cropped, in order to ensure that it is recreated correctly accross multiple runs.
At some level of magnification the random values go from being densities of paticles types to particle locations. Then for each particle, there are partical features. Then features on those features.
Although arbitrary left/right and up/down scrolling will be desired, the image at all levels of magnification above the current scene will have to be calculated each time the frame is shifted to ensure that all necessary features are included. This way the image can be scrolled from one cell to another without loss of consistancy. Partical simulations can be used to ensure that cells or cell features don't overlap. This could be done in a repeatable, deterministic manner.
And don't forget to apply a smoothing gradient based on averages of surrounding squares at higher levels before adding in the random variations. Otherwise, the abrupt changes will make the squares themselves appear in the images!
This answer is somewhat rambling and probably confusing, but that is best I can explain it right now. I hope it helps!