POV-Ray : Newsgroups : povray.general : Need a way to make a semi random "landscape". : Re: Need a way to make a semi random "landscape". Server Time
27 Apr 2024 18:47:54 EDT (-0400)
  Re: Need a way to make a semi random "landscape".  
From: Patrick Elliott
Date: 6 Oct 2010 22:37:28
Message: <4cad3268@news.povray.org>
Any idea why Thunderbird sometimes completely screws up some messages? I 
had to go to the web view to see this at all, since the copy in 
Thunderbird was completely empty...

Worse.. Somehow, the "reply to" for this went to you, rather than the 
group... Resending it so it ends up there.. Very odd.. Wonder if it is 
some glitch with trying to read an email "while" its still downloading, 
or something.


 >> Well, I suppose I could constrain the area to test to a space within Y =
 >> 0 -> 255, Y = 0 -> 255, for sake of getting results. The problem with
 >> trying to store the coordinates, instead of using something like trace,
 >> is the object I am placing "may" land some place better the grid points.
 >> Storing 65356 points is bad enough, without having to subdivide that by
 >> some fraction as well.

 > Of course, you can also use the trace function with a height_field
 > to take care of the correct interpolation between grid points. Just
 > use #declare POS = trace(TERRAIN,<px,100,pz>,-y)

Hmm. Yeah, wasn't real sure how that worked, so was unclear how to 
manage it. I kind of hoped it would be the equivalent of what the 
world's own functions do, which is seems it would be. Those are llWater 
and llGround. Since I am going to be effectively substituting llWater 
for llGround, in cases where the later is lower than the former, one 
solution I thought about was to have a height field, then "clip" that, 
using a plane. For the purposes of visualizing the result, I don't need 
to know where one or the other is. That part is easy enough to work out, 
without testing. If the "base" comes up the same as the higher of the 
two, the code for it works. If not, then its not working. lol

 >> Like I said, I already have code I wrote to generate my points, I just
 >> can't "visualize" the result, or really test it visually in the
 >> environment I want to use it in.

 > If you already have coordinates, you can use them directly to
 > generate 3d objects in POV Ray, e.g., by writing an SDL include
 > file from your Basic program containing an array of coordinates
 > or a union of spheres.

 > What kind of sample data do you already have to test your
 > algorithm in Basic? Do you already have a 3d "terrain"? Or
 > do you wish to generate test data in POV-Ray?

Planned to generate the test data in POV-Ray. And, no I don't really 
have the coordinates *until runtime* either. The following is the test 
code I used to get the general concept working, mind, its messy, and I 
am adding some commentary to clear up what is happening, which the 
original doesn't have. But, initially, I just wanted to see if I could 
get "one" group to generate, within the parameters set for it. In the 
real situation I am actually going to be producing at least 3, perhaps 4 
such groups, with slightly different rules, for each one, depending on 
which type is involved.

// This declaration and the function are replaced with the inbuilt,
// llVecDist(<vector1>,<vector2>) function for the environment.
DECLARE FUNCTION vecdist! (x1!, x2!, y1!, y2!, z1!, z2!)

// Wish I could do this.. The language supported in the environment
// won't allow it, so I am going to have to either serialize the data,
// or use several arrays.
TYPE vects
   x AS SINGLE
   y AS SINGLE
   z AS SINGLE
   r AS SINGLE
   t as integer
END TYPE

DIM plist(6) AS vects

//For ease of identification. In POVRay this would be a color,
//while in the environment its intended for, it would be just
//a number, representing what effect getting too close has.
atyp$ = "FPRETO"

CLS
RANDOMIZE TIMER

//For simplisity sake, I use names that match the functions I will
//use here. For POVRay, these might be replaced with a plane + height
//field, and a call to the trace function, to get the height.
llground = 40
llwater = 37

//This is an arbitrary "height" for the scripts source object.
//All it does is define the max height something "can" be, based
//on the presumed "average" height of the landscape. I might decide
//to replace this with a set range of possible values, based on the
//radius of the "container" sphere.
posz = 120

//Determine where the "container" sphere is going to be, and how big.
//In world, this is the equivalent of 20-40 meters, within an area
//that *must not* allow a contained object to fall outside the 0-255
//coordinate limit in either direction.
rad = (RND(1) * 20) + 20
posx = RND(1) * (255 - ((rad + 1) * 2)) + rad
posy = RND(1) * (255 - ((rad + 1) * 2)) + rad

//This is all just to figure out where the "ground" actually is, i.e.,
//is it the ground level, or the water level?
gnd = llground
water = llwater
IF gnd < water THEN
   gnd = water
END IF

//Knowing which we will be using, we now determine what the
//range if heights this this is likely to occupy.
//For the test code, I assumed that "all" groups could be
//as much as 50 meters "over" the average land height.
//In cases where the ground was "below" this, the range becomes
//the difference between the real ground and the average + 50
//meters. It may be better, thinking on it, to either not use
//this, or only use it in cases it makes sense to (some types
//may reasonably do this, while others wouldn't).
//
IF gnd <= posz THEN
   bas = (posz - gnd) + 50
ELSE
   bas = 50
END IF
top = gnd + bas - rad
bottom = gnd + rad
PRINT
PRINT bas, rad
PRINT bottom, top
DO
   // Work out where our group actually is vertically, now that we have
   // the range it can show up in.
   //
   // Note: Types include >
   // 1. Fire - Probably ground only.
   // 2. Psi - Any range.
   // 3. Radiation - Probably ground only.
   // 4. Electrical - Any range.
   // 5. Poison - Any range.
   // 6. Tomoe (Hard to explain) - Probably ground only.
   // The "ground only" ones would replace "both" centerz, and the
   // z for each object as centerz = gnd, and posz = gnd,
   // respectively.
   //
   centerz = gnd + rad + RND(1) * (bas - (rad * 2))
   PRINT
   PRINT "center "; posx, posy, centerz
   count = 0
   tests = 0
   // Pick a type. Likely needs to be done "prior" to the centerz,
   // in the final version.
   mt = cint(rnd(1) * 6)

   // Now for the fun part.. We pick, at least, 7 points, possibly more,
   // if we end up overlapping any of the radii, and add them to our
   // list of coordinates.
   DO
     ncr = 1 + RND(1) * (rad / 5)
     DO
       ncx = posx + (RND(1) * (rad * 2)) - rad
       ncy = posy + (RND(1) * (rad * 2)) - rad
       ncz = centerz + (RND(1) * (rad * 2)) - rad

       // Assumes a flat plane. Since gnd is the same "everyplace"
       // in the test. In the POVRay version, and the real use for
       // the code, we need to check where the ground/water is here
       // too, since it may not be the same as for the container.
       if ncz < gnd then
         ncz = gnd
       end if

     // This is an example of the sloppy stuff here. I could do a lot
     // of complex math, using a rotation of A,B,C, and a radius
     // equal of lower than that of the container, but "may" waste
     // script time, it also may not work right in the final code.
     //
     // Why? Well, the final environment uses quarternions. So, I
     // either need some valid way to make a random one of those,
     // and I suspect that doing "<llFrand(1), llFrand(1), llFrand(1),
     // llFrand(1)> * (llFrand(1) * Radius)" won't cut it..
     // I am fairly certain that something like <1, .54435, .235, 1> is
     // **not** a valid quarternion, nor what the system would do with
     // such a number. OR I have to do "llEuler2Rot(<llFrand(TWOPI),
     // llFrand(TWOPI), llFrand(TWOPI)>) * llFrand(1) * Radius", and
     // hope that gimble lock doesn't frack up the whole process...
     //
     // I have yet to run tests to see if *either* will work. So,
     // checking to see if the position is "inside" based on distance
     // seemed the simplest option for testing.
     LOOP UNTIL vecdist(posx, ncx, posy, ncy, centerz, ncz) <= rad
     tests = tests + 1
     LOCATE 5, 1

     // Just to make things more interesting, its possible for "some"
     // of the types to end up different than the main one for the
     // whole set. Obviously, as per the prior list, the z coordinate
     // will need to be set to ground, or the selection ignored if that
     // is too far below, for some of them.
     if (rnd(1) < 0.012 then
       nt = cint(rnd(1) * 6)
     else
       nt = mt
     end if
     PRINT "newpos "; ncx, ncy, ncz, ncr
     PRINT "tests "; tests; " count "; count; "      "
     IF count = 0 THEN
       plist(count).x = ncx
       plist(count).y = ncy
       plist(count).z = ncz
       plist(count).r = ncr
       plist(count).t = nt
       count = count + 1
     ELSE
       FOR t = 0 TO count - 1
         IF vecdist(plist(count).x, ncx, plist(count).y, ncy, 
plist(count).z, ncz) > plist(count).r + ncr THEN
           plist(count).x = ncx
           plist(count).y = ncy
           plist(count).z = ncz
           plist(count).r = ncr
       plist(count).t = nt
           count = count + 1
           EXIT FOR
         END IF
       NEXT
     END IF
   LOOP UNTIL count = 7
   REM PRINT
   REM PRINT "dist "; vecdist(posx, ncx, posy, ncy, centerz, ncz)

   // Print my new list of positions.
   PRINT
   FOR t = 0 TO 6
     PRINT plist(t).x, plist(t).y, plist(t).z, plist(t).r, mid$(atyp$, 
plist(t).t, 1)
   NEXT
   DO
     ak$ = INKEY$
   LOOP UNTIL ak$ <> ""
LOOP UNTIL LCASE$(ak$) = "q"

FUNCTION vecdist (x1, x2, y1, y2, z1, z2)
   vecdist = SQR((x1 - x2) ^ 2 + (y1 - y2) ^ 2 + (z1 - z2) ^ 2)
END FUNCTION

Now, obviously, this only produces "one" set, not 3 or more. And, in the 
end, its all just a data generator, which needs to be tuned. Ultimately, 
once I know it is producing usable data, every time the system resets, 
it would produce a random number of these data sets, and someone 
entering the sim, while wearing a device that can talk to the script, 
will get a copy of the list. There will be three forms of this device:

1. Can spawn items, if you get close to one, and tracks things happening 
to you, if you wander through an area with one of these oddities in it.

2. Spawns items, and can warn you that you are getting close to something.

3. The final version uses "all" of the data, showing you what, where, 
etc. something is, based on how close you are, and which direction you 
are facing.

But, to finish that part of the project, I need something that can 
produce data, to feed it. And that is the point of trying it in POVRay 
first. ;)

Yeah. A real landscape would almost be nicer to work with, though I 
tried playing with a few things for making them, and.. they are damned 
annoying to get anything useful out of. But, they might be usable, as 
long as I can get a +- range of say.. 300 meters/units out of them, 
enough interesting variation to test this well. The "pit" in the example 
I attached, for example, is an interesting case, since it could 
constrain where in the sphere an object can even appear. The code I have 
above doesn't account for that at all, since it assumes a flat plane, 
and never checks if the height under an object is the same as under the 
center of its container. In the real implementation, this "has to" happen.


-- 
void main () {

     if version = "Vista" {
       call slow_by_half();
       call DRM_everything();
     }
     call functional_code();
   }
   else
     call crash_windows();
}

<A HREF='http://www.daz3d.com/index.php?refid=16130551'>Get 3D Models, 
3D Content, and 3D Software at DAZ3D!</A>


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.