Soft Volumes

This document is based in part on examination of the PyPRP source code, in part on forum discussion, and in part on my own empirical research. The latter parts contain generalizations from my experimental results that may turn out to be inaccurate. If you observe behavior that contradicts what’s stated here, and can come up with a theory that explains your observation, while not clashing too severely with the rest of this document, you are welcome to amend it.

What is a Soft Volume?

Soft volumes are a way of associating a numerical value with each point in space. That value shall be called field strength for the rest of this article. In contrast to regions, which divide space abruptly into an “on” part and an “off” part, the field strength of a soft volume can vary smoothly over space, hence the name soft. A usual arrangement is to have a constant value of 1.0 in a confined part of space, a smooth fade from 1.0 to 0.0 in a border area around that space, and a constant value of 0.0 everywhere else.

Soft volumes can be used to spatially confine the effect of lamps on avatars, the audibility of sounds, and the visibility of objects depending on the camera position.

Simple Soft Volumes

The simplest possible soft volume is created by making a mesh with a single face in Blender (e.g. by choosing Mesh > Plane from the Add menu), then setting its type property to softvolume, either using the Logic buttons panel or in AlcScript. The extent of the face is ignored by PyPRP, it will be expanded to a whole infinite plane that divides space into two half-spaces. The half-space on the side where the normal of the face points is considered the inside of the volume, the field strength is 1.0 here. On the other side of the plane, the outside, the field strength diminishes linearly until it reaches 0.0 at a certain distance from the plane, then stays at 0.0 for all the rest of space. That distance, the thickness of the soft zone, is called softdist and is 5 units by default, but it can be set to other values (including 0 to get an abrupt transition) in AlcScript:

MySoftVolumeMesh:
type: softvolume
softvolume:
type: convex # 'convex' is the default, so this line could be left away
softdist: 2.0

If your mesh has more faces, each of them is interpreted as another such plane, and Plasma uses the intersection of their “inside” half-spaces as the inside of the volume: To determine the field strength at a certain point, the strength with respect to each individual plane is computed, and the smallest of these numbers is used as the resulting field strength. That way, only points that are on the inside of all planes get a field strength of 1.0.

Therefore, if you use a closed mesh, the soft volume ends up confined to a finite portion of space. Any convex volume can be approximated this way (which is why the AlcScript type is called convex). Keep in mind that in this case, according to the definition above, the face normals must point inward, which is the opposite of what they do by default when you create a new mesh in Blender. While in edit mode, use the Draw Normals button in the Mesh Tools More panel in the Editing buttons to check, and if necessary use Normals > Recalculate Inside from the Mesh menu to correct the normals. If you created the mesh using the Add > PyPRP Soft Volumes script, the normals are already set correctly.

Compatibility Note: With PyPRP 1.5.0 and earlier, soft volume meshes that have a scale or rotation don’t export correctly. Check the Transform Properties window (Object menu), and use Object > Clear/Apply > Apply Scale/Rotation to ObData if necessary to get the rotation angles to 0 and the scale factors to 1.

Using the instrength and outstrength AlcScript properties, the default field strength values of 1.0 for the inside and 0.0 for the outside of the volume can be changed:

Setting instrength smaller than outstrength is possible and has the expected effect of inverting the volume.

Complex Soft Volumes

For creating more complicated soft volumes—e.g. concave shapes, different softdist values on different sides, different constant field strengths in different regions of space—the simple soft volumes described above can be arbitrarily combined by inverting, uniting, and intersecting them. This is done by defining a new soft volume with type invert, union, or intersect, collectively called a complex soft volume, that refers to the other soft volumes that it combines.

Since this new soft volume doesn’t need a mesh or any other Blender scene object for its definition, the question arises, where do we define it in the AlcScript file, since AlcScript can only add information to existing Blender scene objects, not create new PRP objects out of thin air? The answer is that it is possible to define multiple soft volume objects on any Blender object with AlcScript type softvolume, by making the softvolume property not a dictionary (as in the example above) but a list of dictionaries (examples below). This leaves two possibilities: 1. reuse one of the mesh objects used to define the simple soft volumes, 2. add a new Empty Blender object to the scene and give it a type: softvolume property. Multiple soft volume objects defined on the same Blender object will get the same name in the PRP file (the name of the Blender object), which is permissible as long as they have different PRP types, since the names of PRP objects only need to be unique per type. For soft volumes, four different PRP types exist, corresponding to simple (convex) softvolumes, unions, intersections, and inverses.

Invert

Using the invert type, a new soft volume can be defined as the inverse of another (simple or complex) soft volume. (The same effect can also be achieved by using swapped instrength and outstrength values on the original soft volume.) What mathematically happens is that the field strength of the inverse soft volume is defined as one minus the field strength of the original soft volume.

Example of an inverted soft volume, defined on the same mesh object as the original simple soft volume:

When multiple references are put into the list of regions, PyPRP will export them that way, but only the first one is used by Plasma and the rest is ignored.

Union

Using the union type, a new soft volume can be defined as the union of several other (simple or complex) soft volumes. The field strength of the union is defined as the largest of the field strengths of the components. That way, a point gets a field strength of 1.0 if it is inside of any of the component soft volumes (assuming that all in- and outstrengths are at their default values).

Example of the union of the simple soft volume from the example at the top and the inverted soft volume from the preceding example, defined on an empty Blender object named MySoftVolUnion:

Intersection

Using the intersect type, a new soft volume can be defined as the intersection of several other (simple or complex) soft volumes. Like for the individual planes that make up a simple soft volume, the field strength of the intersection is defined as the smallest of the field strengths of the components.

Example of the intersection between the union from the preceding example and a new simple soft volume, both defined on the mesh object of that simple soft volume:

In- and Outstrength on Complex Soft Volumes

The instrength and outstrength properties may be set on complex soft volumes as well. What they do is the following: After computation of the inverse, maximum, or minimum of the component field strengths, that number is subjected to the linear function that maps 0 to outstrength and 1 to instrength (x → x*instrength + (1-x)*outstrength) to yield the final field strength.

Example Summary

Together, the examples from the sections above create the following 6 PRP objects that refer to each other as indicated by the arrows. Blocks of the same color indicate that the objects were defined on the same Blender object and thus have the same name, but are still distinguished by type (block shape).

Short-Hand Syntax for Complex Soft Volumes

Any AlcScript property that accepts a reference to a soft volume (enumerated under Applications below) also accepts an expression in a special syntax that allows you to define complex soft volumes in a single line, without having to explicitly name all their intermediate components as separate objects, as done above. Only the simple soft volumes that form the initial components still need to be present as Blender mesh objects, obviously.

where vol, vol1 etc. are either nested subexpressions in the same syntax, or the names of simple soft volumes.

In this notation, the final svintersect:MySoftVolumeMesh3 from the examples above could be written as

I(U(MySoftVolumeMesh, !(MySoftVolumeMesh2)), MySoftVolumeMesh3)

Space characters are ignored in such expressions.

Note: when such an expression that starts with ‘!’ is specified as an AlcScript value, it must be put in quotation marks because an unquoted exclamation point at the beginning of a value has a special meaning in YAML.

The disadvantages of this method are that there is no control over optional properties like instrength, and that there is no way to use the same complex soft volume object in several places - using the same expression several times will create several independent copies of all involved complex soft volumes.

Applications

In the following descriptions, soft volume reference means either an expression in the short-hand syntax for complex soft volumes, or an actual reference to a (simple or complex) soft volume. For the latter, reference type softvolume is assumed by default, so in the usual case where they are simple softvolumes, you can simply use their names, without prepending “softvolume:”.

Lamps

Using the lamp.softvolume AlcScript property, the effect of a lamp on the avatar can be spatially confined:

Sun:
lamp:
softvolume: soft volume reference

The avatar is fully lit at a field strength of 1.0, and unaffected by the light at 0.0. Feet, legs, torso, hands, and head of the avatar are treated separately when he is partially inside the soft volume. From a field strength of 0.2 on upwards, the avatar’s shadow is visible (assuming that the lamp casts shadows). It does not fade proportionally to field strength, but appears and disappears abruptly at 0.2.

Further research topic: Does this only affect the avatar, or also kickables or any other objects?

Sounds

MySound:
sound:
softvolume: soft volume reference

This makes the sound volume proportional to the soft volume field strength at the camera position. For instance, if the default instrength and outstrength are used, the sound will fade in as you enter the softvolume region and is a bit more exact than 3D sound settings.

To reverse the effect (fade sounds out when entering), simply alter the script as follows:

MySound:
sound:
softvolume: "!(soft volume reference)"

This is useful when entering an enclosed room from the outdoors in an Age and need to decrease or silence outdoor ambient noises. Use an instrength in your softvolume AlcScript of something less than 1.0 if you don't want the sound to fade out completely.

Visregions

Visregions allow you to remove objects from the scene depending on the camera position. This is mainly used to improve rendering performance by removing objects that wouldn’t be visible anyway because they are obscured by something else.

The object is only visible as long as the camera is inside any of the specified soft volumes. More specifically, the object is visible exactly if any of the field strengths of the specified soft volumes are >= 1.0.

Jonnee reports that you should better not use this for objects you want to interact with, like buttons or sitting mods. They are unfunctional after they are hidden and shown again.

Setting wavesets to VisRegions seems to be fine with the current version of PyPRP (1.6.1) - Doobes.

Compatibility Note: This definition is reversed in PyPRP 1.5 and earlier: when exported with these versions, the object becomes invisible when the camera is inside any of the soft volumes, i.e. visible exactly if all of the field strengths are < 1.0.

Lamp visregions only remove the effect of the lamp on avatars, not on the rest of the scene. Their effect is similar to lamp soft volumes in this regard, only based on the position of the camera, not of the avatar, and abrupt, not gradual.

Compatibility Note: There is a bug in PyPRP 1.5.0 and earlier that prevents complex soft volume expressions from working in visregions. Only actual references to soft volume objects work.

Technical detail note about the kIsNot flag, for those who like to hack PyPRP or hand-edit their PRP files (since it is currently not accessible from AlcScript): this flag marks a visregion as “negative”. With “interior” defined as the region where soft volume field strength is >= 1.0: The object will be visible from the union of the interiors of its “positive” visregions minus the union of the interiors of its “negative” visregions, with the exception that if all visregions have the flag set (which is the case produced by PyPRP 1.5.0), they are subtracted from all of space, not from the empty set.

Hopefully in the future it will be possible to set flags per-visregion.