Hi Y'all,
Sorry, I'm really late to the party here...(and I'll try to jump in on connectivity when I can), but I have a few strong opinions about this.
HIGH VS LOW LEVEL ABSTRACTION
First, we have to decide if this extension is meant to be a high level or low level abstraction.
Low level: Saying "the bump map comes from slopybumps.png" is a low level abstraction - the behavior is completely determined by the spec - a compliant renderer is going to go use a bump map. If the renderer substitutes something else for slopybumps.png, that's a hack, it's not going to be portable to all uses of the meta directive, and it risks being broken in the future. The flexibility is on the part developer's side.
High level: Saying "the surface properties of this face should be the rough texture of a real-world slope brick 45 2x2." The renderer has to cope with this somehow, perhaps using bump maps, perhaps using a BDRF, perhaps using povray directives. The flexibility is in the renderer; part creators get to pick this surface or not.
We have already gone with low level for part shape and texturing and this is clearly the sane decision. But I would argue that for material roughness, a high level approach is actually correct! Here's why.
- There are a lot of ways to render a material - and there is no one right way. I am -cringing- when I hear people go "bump maps"...bump maps are not a great fit for this problem. (We can have a separate discussion on that, but suffice it to say, not all rendering code developers are going to agree on how to show this rough surface.)
- There are not -that- many unique materials in the particular real world part set we are simulating. The fact that we don't have this feature at all right now is because most parts share the same uniform smooth glossy ABS plastic finish.
So to me this is a good candidate to simply enumerate the small number of real world material surfaces and let programs then implement this - whether it's by changing the OpenGL lighting parameters, providing custom BDRFs, using bump maps, or creating some kind of directives for Povray. The small axis here is the real world phenomenon, the wide axis is the client code.
ORTHOGONALITY
We have to decide which properties can be present on a surface -at the same time-. For example, if there are two types of bumpiness for slope bricks (I'm not enough of an expert, and my son's legos are in his room while he sleeps) then one quad or triangle can't be both of those bumpinesses at the same time. A face that has this bumpy slope surface also no longer has the "default" surface, which is an implicit surface that all parts have until tagged otherwise.
So I think we need to define the -scope- of the data we are adding - it has nothing to do with sloped bricks - it has to do with whatever it is we want to define. (I would call it "surface texture" - if texture wasn't such an overloaded word in computer graphics.)
I think we want to define a new meta that specifies a subsequent 'surface' and can either set it to one or more newly defined and enumerated surfaces, or set it back to the default, e.g. instead of
0 !SLOPE_TEXTURE BEGIN
<faces that have slope texture>
0 !SLOPE TEXTURE END
We'd have
0 !SURFACE BUMPY_SLOPE
<faces that have bumpy slope texture>
0 !SURFACE DEFAULT
<faces that have normal "glossy and smooth" texture>
This leaves the possibility of adding more mutually exclusive surface textures as we find a need for them.
CHILD RULES
Assuming that this meta directive affects sub-parts/sub-files (which pretty much all of the modern extensions do), I would like to see an extension where it is _not_ possible to _override_ the surface decision of a child part once it is made. This would be different from some of our other extensions, but this is a direction I'd like to consider for new extensions.
The problem with overriding is that it makes it impossible for a program that processes LDraw files to fully process a sub-part without knowing its -complete- inclusion in a super-part.
In a scheme where the child cannot be overruled (the child's rule is the final rule) a sub-part is in one of two categories:
- It contains _no_ surface information and surface information will come from the thing including it or
- It contains surface information and that is final.
This is a scheme where a sub-part can be fully optimized. For example, if a sub-part contains no surface changes within the part (and is thus completely uniform in surface) it can be optimized as such.
In a scheme where the child can be overruled, the sub-part has to be kept around in a representation equivalent to the LDraw file format itself, pre-transformation-for-rendering-tech, until the LDraw directives can be fully resolved using their complete inclusion and context. This means that part assembly from sub-parts (e.g. inserting 2304 studs into a 48x48 baseplate) has to be done in terms of LDraw file directives (creating a soup of who-knows-how many tris and lines) rather than working on the level of finished fully optimized sub-objects.
This restriction would limit what part authors can do - I think we need to think a bit about whether it's good practice or bad practice to author parts by overriding the surfaces of the sub-part. (My gut feeling is that if you have to override the surface, the library is "badly factored" and new primitives should be identified, but I don't make parts...others who actually are in the trenches should be trusted with this!)
cheers
Ben
Sorry, I'm really late to the party here...(and I'll try to jump in on connectivity when I can), but I have a few strong opinions about this.
HIGH VS LOW LEVEL ABSTRACTION
First, we have to decide if this extension is meant to be a high level or low level abstraction.
Low level: Saying "the bump map comes from slopybumps.png" is a low level abstraction - the behavior is completely determined by the spec - a compliant renderer is going to go use a bump map. If the renderer substitutes something else for slopybumps.png, that's a hack, it's not going to be portable to all uses of the meta directive, and it risks being broken in the future. The flexibility is on the part developer's side.
High level: Saying "the surface properties of this face should be the rough texture of a real-world slope brick 45 2x2." The renderer has to cope with this somehow, perhaps using bump maps, perhaps using a BDRF, perhaps using povray directives. The flexibility is in the renderer; part creators get to pick this surface or not.
We have already gone with low level for part shape and texturing and this is clearly the sane decision. But I would argue that for material roughness, a high level approach is actually correct! Here's why.
- There are a lot of ways to render a material - and there is no one right way. I am -cringing- when I hear people go "bump maps"...bump maps are not a great fit for this problem. (We can have a separate discussion on that, but suffice it to say, not all rendering code developers are going to agree on how to show this rough surface.)
- There are not -that- many unique materials in the particular real world part set we are simulating. The fact that we don't have this feature at all right now is because most parts share the same uniform smooth glossy ABS plastic finish.
So to me this is a good candidate to simply enumerate the small number of real world material surfaces and let programs then implement this - whether it's by changing the OpenGL lighting parameters, providing custom BDRFs, using bump maps, or creating some kind of directives for Povray. The small axis here is the real world phenomenon, the wide axis is the client code.
ORTHOGONALITY
We have to decide which properties can be present on a surface -at the same time-. For example, if there are two types of bumpiness for slope bricks (I'm not enough of an expert, and my son's legos are in his room while he sleeps) then one quad or triangle can't be both of those bumpinesses at the same time. A face that has this bumpy slope surface also no longer has the "default" surface, which is an implicit surface that all parts have until tagged otherwise.
So I think we need to define the -scope- of the data we are adding - it has nothing to do with sloped bricks - it has to do with whatever it is we want to define. (I would call it "surface texture" - if texture wasn't such an overloaded word in computer graphics.)
I think we want to define a new meta that specifies a subsequent 'surface' and can either set it to one or more newly defined and enumerated surfaces, or set it back to the default, e.g. instead of
0 !SLOPE_TEXTURE BEGIN
<faces that have slope texture>
0 !SLOPE TEXTURE END
We'd have
0 !SURFACE BUMPY_SLOPE
<faces that have bumpy slope texture>
0 !SURFACE DEFAULT
<faces that have normal "glossy and smooth" texture>
This leaves the possibility of adding more mutually exclusive surface textures as we find a need for them.
CHILD RULES
Assuming that this meta directive affects sub-parts/sub-files (which pretty much all of the modern extensions do), I would like to see an extension where it is _not_ possible to _override_ the surface decision of a child part once it is made. This would be different from some of our other extensions, but this is a direction I'd like to consider for new extensions.
The problem with overriding is that it makes it impossible for a program that processes LDraw files to fully process a sub-part without knowing its -complete- inclusion in a super-part.
In a scheme where the child cannot be overruled (the child's rule is the final rule) a sub-part is in one of two categories:
- It contains _no_ surface information and surface information will come from the thing including it or
- It contains surface information and that is final.
This is a scheme where a sub-part can be fully optimized. For example, if a sub-part contains no surface changes within the part (and is thus completely uniform in surface) it can be optimized as such.
In a scheme where the child can be overruled, the sub-part has to be kept around in a representation equivalent to the LDraw file format itself, pre-transformation-for-rendering-tech, until the LDraw directives can be fully resolved using their complete inclusion and context. This means that part assembly from sub-parts (e.g. inserting 2304 studs into a 48x48 baseplate) has to be done in terms of LDraw file directives (creating a soup of who-knows-how many tris and lines) rather than working on the level of finished fully optimized sub-objects.
This restriction would limit what part authors can do - I think we need to think a bit about whether it's good practice or bad practice to author parts by overriding the surfaces of the sub-part. (My gut feeling is that if you have to override the surface, the library is "badly factored" and new primitives should be identified, but I don't make parts...others who actually are in the trenches should be trusted with this!)
cheers
Ben