Okay so I managed to script load/import terrain assets in batch, compile 16 bit heightmap images, but a couple things, apparently for the mosaic loading pattern things don't quite mesh well for the terrains, even using (as in my previous post) the mentioned terrain edge boundary algorithm. Namely the corners still have discontinuities between edges, and the reason for this in my program is related to sequencing the measurement of points on a given edge boundary while neither accounting for any given change when measuring for another edge boundary. It would appear I also needed have a fixed point for the corners of the world mosaic maps. Even so visually the results appear precisely matched except for inside the terrain edge matching threshold regions at the corners.
What I've managed as a solution to this is by creating a fixed point on a given corner but projecting this fixed points edge difference in so far as the interpolated region on a neighboring map, which in turn should lead to a new projection on the next neighboring map, and so forth.
For instance, at a given intersection I have 4 maps. I start with map 4, and I choose the corner point of this map. Then I compute the cspline interpolated translation curve on neighboring map 3's edge boundary. I use the old edge difference points from map 3 as related to the map 1 neighbor and then I add the differences as computed with the cspline interpolated difference on map 3's edge along our defined threshold region. I again, following the process of using a fixed point in map 4 do the same for map 3, and compute an cspline interpolated region on map 1, and then repeat this procedure to readjust values on map 2, until I lead back into map 4.
I can reverse this process likewise. We are still left with the problem as I've mentioned in a given threshold region for cspline translation of points for terrain boundary matching namely going from map 2 back into 4, and this would lead to a readjustment of points back in map 3, so we can diagonalize or linearly vary the threshold length of points on the threshold boundary region (this would be like creating a custom diagonal miter for a picture frame). So that by folding a translation of points into the given mesh region this would not effect edge boundary differences of points as originally measured say from map 4 to map 3 (hence mitering the threshold region).
Here are some results shown visually after correction:
Some added improvements. We can still slightly see seam on the a given edge. Added approximating methods could smooth over these I imagine but definitely smooth.
Example with texture loading. I've again batch automated texture loading.
Something to keep in mind when importing height map. You'd definitely want to know the orientation of the map itself. Unfortunately, I've had issues reading raw 16 bit grey scale height maps. Why, for instance, I had created a height map binary reader, but also in terms of image formatting another issue which should include, for instance rotating an image. I actually created a fairly simple algorithm to rotate bit map image coordinates. Pretty simple really, using your favorite linear algebra math package, you'd need to first convert to local terrain coordinates. Where the local coordinate position sets the terrains local point of origin to the center of its map. This is terrain.width/2 for x height and terrain.height/2. Then you'd need to convert any position (from previous post see 16 bit binary map loading script) x y to local prime coordinates. To do this I used a linear algebra package, and created 2d vectors for the original x,y coordinate position, and the a 2d vector for the new local coordinate's point of origin, I'll label this V2. Subtract these two vectors and the resultant vector determines the coordinate position on the prime axis, call this V3. Now, again you'd need to generate a 2x2 rotation matrix (see http://en.wikipedia.org/wiki/Rotation_matrix ). So you need a supplying angle. If you have this in degrees, you'll need to convert this to radians (Math.Pi/180.0 * degree). Then build the matrix coefficients using the rotation matrix formulation provided at the link above. Next, you'll take the supplied x', y' (local coordinate) positions and multiply the rotation matrix M*vec(x',y') this resultant vector is the x', y' coordinate after rotation, call this V3', now you'll need to reconvert from prime coordinates back into original global point of origin, so you take this resultant vector and add it to the local point so take V2+V3' and this returns the new coordinate positions x, y post rotation. This rotates the terrain grid around its centroid which is what we want to ensure that we have proper indexing values for our terrain. If you did it like me, to avoid fretting over problems of trig, you'll need to cast convert from integer coordinate positions (for unity) to doubles or floats or whatever your linear algebra package runs from and then convert back to integer positions. This is fine by the way for square (90 degree, 180, 270, and 360 rotations). Technically we can't set up terrain grids rotated in other ways (without truncating the map on the square) since Unity allows rectangle terrain grids that are not skew. Although I am sure if you really wanted to hobby around you could find a way of overlapping terrain grids to create skew tile ways of arranging terrain grids. The math though gets tedious with these non standard rotations since you'd need to figure out how to preserve all integer based coordinate positions with a rotation conversion on a double that is converted back to an integer , Unity forces this coordinate position integer type for Terrain building, a problem likely involving scaling, or interpolating point positions and heights.
Using the binary height map importer algorithm (previous post a few back on my blog), I've found when using the World Terrain generator program which can produce both height map and terrain texture images, that using a North South world terrain row position, and West to East world terrain column position, that I needed to rotate height map images by -90 degrees and Texture images by +90 degrees. This generally resolved issues without the need in modifying my overall importation build algorithms, such as translating terrain tiles differently relative to the build indexing using the North/South/West/East formulation but changing the indexing of the maps so that they align properly because the binary reader builds the maps with its local north pointed, for instance west or east instead of true north on the local coordinate build.
What I've managed as a solution to this is by creating a fixed point on a given corner but projecting this fixed points edge difference in so far as the interpolated region on a neighboring map, which in turn should lead to a new projection on the next neighboring map, and so forth.
For instance, at a given intersection I have 4 maps. I start with map 4, and I choose the corner point of this map. Then I compute the cspline interpolated translation curve on neighboring map 3's edge boundary. I use the old edge difference points from map 3 as related to the map 1 neighbor and then I add the differences as computed with the cspline interpolated difference on map 3's edge along our defined threshold region. I again, following the process of using a fixed point in map 4 do the same for map 3, and compute an cspline interpolated region on map 1, and then repeat this procedure to readjust values on map 2, until I lead back into map 4.
I can reverse this process likewise. We are still left with the problem as I've mentioned in a given threshold region for cspline translation of points for terrain boundary matching namely going from map 2 back into 4, and this would lead to a readjustment of points back in map 3, so we can diagonalize or linearly vary the threshold length of points on the threshold boundary region (this would be like creating a custom diagonal miter for a picture frame). So that by folding a translation of points into the given mesh region this would not effect edge boundary differences of points as originally measured say from map 4 to map 3 (hence mitering the threshold region).
Here are some results shown visually after correction:
Some added improvements. We can still slightly see seam on the a given edge. Added approximating methods could smooth over these I imagine but definitely smooth.
Example with texture loading. I've again batch automated texture loading.
Something to keep in mind when importing height map. You'd definitely want to know the orientation of the map itself. Unfortunately, I've had issues reading raw 16 bit grey scale height maps. Why, for instance, I had created a height map binary reader, but also in terms of image formatting another issue which should include, for instance rotating an image. I actually created a fairly simple algorithm to rotate bit map image coordinates. Pretty simple really, using your favorite linear algebra math package, you'd need to first convert to local terrain coordinates. Where the local coordinate position sets the terrains local point of origin to the center of its map. This is terrain.width/2 for x height and terrain.height/2. Then you'd need to convert any position (from previous post see 16 bit binary map loading script) x y to local prime coordinates. To do this I used a linear algebra package, and created 2d vectors for the original x,y coordinate position, and the a 2d vector for the new local coordinate's point of origin, I'll label this V2. Subtract these two vectors and the resultant vector determines the coordinate position on the prime axis, call this V3. Now, again you'd need to generate a 2x2 rotation matrix (see http://en.wikipedia.org/wiki/Rotation_matrix ). So you need a supplying angle. If you have this in degrees, you'll need to convert this to radians (Math.Pi/180.0 * degree). Then build the matrix coefficients using the rotation matrix formulation provided at the link above. Next, you'll take the supplied x', y' (local coordinate) positions and multiply the rotation matrix M*vec(x',y') this resultant vector is the x', y' coordinate after rotation, call this V3', now you'll need to reconvert from prime coordinates back into original global point of origin, so you take this resultant vector and add it to the local point so take V2+V3' and this returns the new coordinate positions x, y post rotation. This rotates the terrain grid around its centroid which is what we want to ensure that we have proper indexing values for our terrain. If you did it like me, to avoid fretting over problems of trig, you'll need to cast convert from integer coordinate positions (for unity) to doubles or floats or whatever your linear algebra package runs from and then convert back to integer positions. This is fine by the way for square (90 degree, 180, 270, and 360 rotations). Technically we can't set up terrain grids rotated in other ways (without truncating the map on the square) since Unity allows rectangle terrain grids that are not skew. Although I am sure if you really wanted to hobby around you could find a way of overlapping terrain grids to create skew tile ways of arranging terrain grids. The math though gets tedious with these non standard rotations since you'd need to figure out how to preserve all integer based coordinate positions with a rotation conversion on a double that is converted back to an integer , Unity forces this coordinate position integer type for Terrain building, a problem likely involving scaling, or interpolating point positions and heights.
Using the binary height map importer algorithm (previous post a few back on my blog), I've found when using the World Terrain generator program which can produce both height map and terrain texture images, that using a North South world terrain row position, and West to East world terrain column position, that I needed to rotate height map images by -90 degrees and Texture images by +90 degrees. This generally resolved issues without the need in modifying my overall importation build algorithms, such as translating terrain tiles differently relative to the build indexing using the North/South/West/East formulation but changing the indexing of the maps so that they align properly because the binary reader builds the maps with its local north pointed, for instance west or east instead of true north on the local coordinate build.
No comments:
Post a Comment