Jump to content

Is there a mathematician in the house?


ChinRey
 Share

You are about to reply to a thread that has been inactive for 415 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

This is a bit embarrasing but my head is a bit mushy right now and high school maths is many years away.

I have a wedge like this

image.png.c6a214e2fdd4c04e71e07a18d07b9079.png

and I need to calculate the height of any given point of the top surface. Or more precisely: I need to calculate the height above each vertice of the ground the wedge covers.

So far it's dead easy, my brain isn't so mushy it can't do simple additions and subtractions. 😉

But what if I rotate the wegde?

image.png.d29306537c35bc720d0a50e3ffa6de3c.png

and what if it's a semisphere rather than a wedge?

image.png.6955a84b0c92247d9a5f7018fb9fc80e.png

In case you wonder why I'm asking, I have these plant groups with several plants in a single mesh specially made to cover slopes and hilltops. It saves a lot of LI and lag compared to using single plants but getting the ground to match can be a real pain. I'm trying to come up with a script that does the terraforming automatically.

Link to comment
Share on other sites

What about using raycast instead of trying to do the math yourself? It would work for any kind of complex surface.

Edit: Oh, I misunderstood. It's a single-mesh set of plants, so it can't adjust to the ground, instead you want to adjust the ground to the plants.

Actually, even in that case you should be able use raycast to figure out the distance to the ground, and raise it by that amount.

Or is the problem still about being able to create a correct slope, or pick the correct spots to raycast from?

Edited by Wulfie Reanimator
  • Like 2
Link to comment
Share on other sites

3 hours ago, Wulfie Reanimator said:

Or is the problem still about being able to create a correct slope, or pick the correct spots to raycast from?

The problem is that those meshes don't have solid bottom surfaces and there are bits and pieces sticking up all over them. I can of course add a template mesh or prim that matches the bottom of the mesh and raycast that template but that's a complication I'd rather avoid if possible.

Link to comment
Share on other sites

28 minutes ago, ChinRey said:

The problem is that those meshes don't have solid bottom surfaces and there are bits and pieces sticking up all over them. I can of course add a template mesh or prim that matches the bottom of the mesh and raycast that template but that's a complication I'd rather avoid if possible.

If you reject physical, non-physical, and phantom objects for the raycast, it'll only detect the ground without fear of hitting itself. Raycast won't hit the visual mesh either, only the physics shape. 🙂

And you don't need a solid bottom for the plants, you can just pick an arbitrary spot near the bottom of the plant where you want the ground to be, and cast down towards the ground from there. (I'd post code but I'm writing from mobile.)

Edited by Wulfie Reanimator
Link to comment
Share on other sites

9 minutes ago, Wulfie Reanimator said:

If you reject physical, non-physical, and phantom objects for the raycast, it'll only detect the ground without fear of hitting itself.

Yes but I think you misunderstand me a bit. I have no need for raycasting the existing ground level, I need to determing the level the ground needs to be raised to.

Look at this group of bare shrubs for example:

image.png.f9f9158ba12758f7ffad6663f3a68c83.png

It needs a ground level something like this prim:

image.thumb.png.46c945f538c8ab5a5c1bdb2289c04de9.png

One solution is of course to put a prim like that on tha spot, raycast it, remove it and then rez the plants on top of the new ground. But that soultion is seriously awkward, especially if the plant group is to be resized and/or rotated.

  • Like 1
Link to comment
Share on other sites

1 hour ago, ChinRey said:

Yes but I think you misunderstand me a bit. I have no need for raycasting the existing ground level, I need to determing the level the ground needs to be raised to.

Yes, this is exactly what I'm talking about -- raising the LL ground up to the static (sloped) mesh. Just turn your mental image upside-down.

Let's say the top if your plants are at height 28 meters. So you raycast from <x, y, 28> down to the ground. The ground is at height 12, so you can calculate the height difference: 28 - 12 = 6. The ground needs to be raised 6 meters.

The plants don't need a solid bottom because that's where you're starting from, and you don't need math because the starting point can be a hardcoded relative offset (from the root), which you can rotate by llGetRot.

That lets you rotate the plants and still find a correct height difference to the ground, especially since you don't have to rotate the end point for each raycast (because you always want to test straight down).

I'll post a script you can try out later today. 🙂

Edited by Wulfie Reanimator
  • Like 1
Link to comment
Share on other sites

Kay, here's the idea:

default
{
    touch_start(integer n)
    {
        list heights; // Just for output.

        // Local points where ground is checked
        list points = [
            <0.000000, -1.847900, 0.765400>,
            <0.000000, 0.000000, 0.000000>,
            <0.000000, 1.847900, -0.765400>
        ];

        integer i;
        integer max;
        for (max = llGetListLength(points); i < max; ++i)
        {
            vector down = <0, 0, -5>;

            // Rotate each point by the object's rotation!
            vector point = llGetPos() + llList2Vector(points, i) * llGetRot();
          
            // Cast from the local point, straight down towards the ground.
            list data = llCastRay(point, (point + down), [RC_REJECT_TYPES, RC_REJECT_PHYSICAL | RC_REJECT_NONPHYSICAL]);

            integer status = llList2Integer(data, -1);
            if (status < 1)
            {
                llOwnerSay("Move me closer to the ground!");
                return;
            }

            vector ground = llList2Vector(data, 1);
            // Here we have the height difference between the ground and the plants.
            // This can be used to raise the ground to meet the plants.
            heights += point.z - ground.z;
        }

        llOwnerSay("Ground needs to be raised by: " + llList2CSV(heights));
    }
}

Here's my mock-up for the plants and the raycast points: (The large square is the bounding box of the mesh, the white boxes represent each raycast point.)

rc.png.192f74468fca8df9ec7588e2f894a98d.png

3 hours ago, ChinRey said:

those meshes don't have solid bottom surfaces

Just to reiterate, this is the reason why we cast from the plants into the ground, instead of trying to hit the plants from below.

Edited by Wulfie Reanimator
  • Like 1
Link to comment
Share on other sites

Thanks a lot but there is one problem here:

1 hour ago, Wulfie Reanimator said:
           // Here we have the height difference between the ground and the plants.
            // This can be used to raise the ground to meet the plants.
            heights += point.z - ground.z;
        }

        llOwnerSay("Ground needs to be raised by: " + llList2CSV(heights));
    

There is no lsl function that allows you to raise or lower the ground by a specific amount. If I remember correctly, llModifyLand()'s LAND_RAISE and LAND_LOWER actions only raises/lowers the ground way up into the sky or way down to the bottom of the ocean and as far I know they have no practical use whatsoever. It's either that or they jsut produce a tiny little barely noticeable bump in the terrain. In any case, there's certainly no way to use them to set a specific level, neither absolute nor relative to the starting point.

The only even theoretically possible way to do this in SL is to use a separate prim that moves from point to point using the LAND_LEVEL action like this:

 llModifyLand(LAND_LEVEL,0);

That means there is no need for the script to know the ground altitude before the process so raycasting becomes irrelevant. All the script needs to know is the exact height of the mesh exactly above each vertice on the ground underneath. (Or maybe exactly between four vertices but that'll be a trivial issue to sort out.)

And then of course I'll have to figure out a way to smooth out the terrain without lowering it. LlModify land doesn't manipulate individual vertices but only groups of 4, 16 or 64 so the result won't be a smooth slope but rather a series of sharp steps. Maybe this is a bad idea and I'm just wasting your time and mine here. 😞

 

Edited by ChinRey
Link to comment
Share on other sites

1 hour ago, ChinRey said:

There is no lsl function that allows you to raise or lower the ground by a specific amount. If I remember correctly, llModifyLand()'s LAND_RAISE and LAND_LOWER actions only raises/lowers the ground way up into the sky or way down to the bottom of the ocean and as far I know they have no practical use whatsoever. There's certainly no way to use them to set a specific level, neither absolute nor relative to the starting point.

OH. Oh no. I hadn't even looked at what functions were available in LSL for that.

1 hour ago, ChinRey said:

The only even theoretically possible way to do this in SL is to use a separate prim that moves from point to point using the LAND_LEVEL action like this:

 llModifyLand(LAND_LEVEL,0);

That means there is no need for the script to know the ground altitude before the process so raycasting becomes irrelevant. All the script needs to know is the exact height of the mesh exactly above each vertice on the ground underneath. (Or maybe exactly between four vertices but that'll be a trivial issue to sort out.)

And then of course I'll have to figure out a way to smooth out the terrain without lowering it. LlModify land doesn't manipulate individual vertices but only groups of 4, 16 or 64 so the result won't be a smooth slope but rather a series of sharp steps. Maybe this is a bad idea and I'm just wasting your and my time here. 😞

It does remove the need for the raycast, but using LAND_LEVEL just once doesn't bring it up to the prim's height immediately, it seems to do the same thing as LAND_RAISE (besides stopping at the same level)... about 0.2 meters per raise? I don't know what's going on with the terrain physics when land is modified, llCastRay didn't seem to see the update until a random period of time (seconds or minutes).

It doesn't create a flat surface (at least with the smallest brush), and the gradual raises mean that it doesn't create sharp edges either. You can totally have a script create gradual slopes -- not perfect, but maybe it's good to have a little bit of variance in nature? (Just grasping at straws here. The owner might want to clean up the result.)

I was testing things at the Builder's Brewery sandbox. (Builders Resource, North-East corner, gotta join the group to terraform.)

Addendum: This is what I did to raise the ground based on the height difference. It seems arbitrary to me, but it worked. if llModifyLand is called from a linked prim, it will raise the ground under that link. (This function is terrible, though.)

for (h = point.z - ground.z; h > 0; h -= 0.2) {
    llModifyLand(LAND_RAISE, 0);
}

 

Edited by Wulfie Reanimator
  • Like 1
Link to comment
Share on other sites

20 hours ago, ChinRey said:

If I remember correctly, llModifyLand()'s LAND_RAISE and LAND_LOWER actions only raises/lowers the ground way up into the sky or way down to the bottom of the ocean and as far I know they have no practical use whatsoever.

I was wrong. It turns out the open source land editing script I've been using runs llModifyLand() inside an infinite loop which is why it always maxes out the effect applied. Applying the function a single time does, as Wulfie observed, cause aproximately 0.2 m of change.

 

20 hours ago, Wulfie Reanimator said:

It doesn't create a flat surface (at least with the smallest brush), and the gradual raises mean that it doesn't create sharp edges either. You can totally have a script create gradual slopes -- not perfect, but maybe it's good to have a little bit of variance in nature? (Just grasping at straws here. The owner might want to clean up the result.)

Yes, I don't think it will be close enough to be worth the bother, especially with all the headache trying to get llModifyLand() to do the job.

However, your suggestion using raycasting gave me an idea for a completely different project. Look at this:

image.png.920676486f5b4339d4fe3d83fb3e9244.png

Just a pile of prims on a flat ground. Raycast and apply to the terrain and I get this:

image.png.5cf087f1042ab3cadcb3ad3b6f98780c.png

It only really works on opensim, not in SL, since opensim does have a straightforward way to position terrain vertices individually and precisely. But even so, this is going to be really useful, thanks a lot Wulfie! 🙂

Edited by ChinRey
  • Like 1
Link to comment
Share on other sites

18 minutes ago, Love Zhaoying said:

How about:

- Have a "landscaper prim" move "up and down and all around" your Landscape Mesh on its top-side.

- As it does so, have it (the "landscaper prim") call the LSL functions to modify the land, to its current height. (Or "current height - mesh thickness factor).

Yes, that's the way it would have to be done in SL. It's still frustratingly complex though. You need a way to define the boundaries for the landscaper prim, you probably need some way to pause the script regularly since doing it this way in one go may well overload the scripting engine and above all, llModifyLand(() simply isn't suitable for the task. LAND_RAISE and LAND_LOWER won't give the precision needed whilst LAND_LEVEL will create steps rather than smooth transitions.

The reason it works on opensim is that osl has a function, osSetTerrainHeight that can be called from anywhere in the sim (so no need to move the editor around) and sets the elevation for individual terrain vertices. Maybe we shuold campaign for a similar function to lsl? Or maybe not. There is a reason why the osl docs marks the function as "High Threat Level".

  • Thanks 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 415 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...