This page collects information about implementation status of VRML constructs, with respect to VRML 1.0, 2.0 (aka VRML 97) and 3.0 (aka X3D) specifications. It also collects some details about handling of some nodes. If you want to know what is supported besides the things required by VRML specifications, you should read the other page about VRML extensions implemented.
No limits: VRML 97 and X3D specifications define various limits that must be satisfied by VRML browsers to call themselves "conforming" to VRML specification. For example, only 500 children per Group have to be supported, only SFString with 30,000 characters have to be supported etc. My units generally don't have these limits (unless explicitly mentioned below). So any number of children in Group node is supported, SFString may be of any length etc. VRML authors are limited only by the amount of memory available on user system, performance of OpenGL implementation etc.
Contents:
All nodes from all components of X3D edition 2 specification are included in the engine. This doesn't mean that they are meaningfully handled, but they are at least parsed correctly (and converting from X3D XML to classic VRML preserves them correctly).
All field types, including new X3D double-precision and matrices, are supported, with the exception of MFImage. MFImage should be implemented as soon as I see some usage of this, for now no X3D specification nodes actually use this.
We support fully both XML and classic encodings.
The table below sums up our X3D component support. Since the whole X3D standard is divided into components (and it includes also all VRML 2.0 features), this table may actually be considered a concise summary of our "VRML / X3D implementation status".
A word "practically" below means that the component is not absolutely 100% supported on given level, but most important parts (99% of usage) of given level are supported.
| Component | Supported level |
|---|---|
| Core | 2 (all) |
| Time | 2 (all) (practically) |
| Networking | 1 (+ all level 2 features except http: protocol) |
| Grouping | 3 (all) |
| Rendering | 3 (practically) |
| Shape | 1 |
| Geometry3D | 4 (all) |
| Geometry2D | |
| Text | 1 (all) (practically) |
| Sound | |
| Lighting | 3 (all) (practically) |
| Texturing | 3 (all) (practically: some bits of level 2 nodes are missing) |
| Interpolation | 3 (practically) |
| Pointing device sensor | (TouchSensor supported, but that's it for now) |
| Key device sensor | 1 |
| Environmental sensor | 1 |
| Navigation | 1 (+ most, but not all, features up to level 3) |
| Environmental effects | 2 |
| Geospatial | |
| H-Anim | 1 (all) (practically) |
| NURBS | |
| DIS | |
| Scripting | 1 (all) (practically; although no ECMAScript / Java, only KambiScript / compiled protocols) |
| Event utilities | 1 (all) |
| Shader | 1 (all) (basically; GLSL language) |
| CAD geometry | 1 |
| Texturing3D | 2 (all) |
| Cube map environmental texturing | 3 (all) |
| Layering | |
| Layout | |
| Rigid body physics | |
| Picking sensor | |
| Followers | |
| Particle systems |
Besides all VRML 97 features (see lower on this page for VRML 2.0 status), X3D things implemented now are:
|
| This movie shows GLSL shaders by our engine. You can also get AVI version with much better quality (12.742 MB). |
Programmable shaders component is implemented: ComposedShader and ShaderPart nodes allow you to write shaders in GLSL language.
Basic example.
Add inside Appearance node VRML code like
shaders ComposedShader {
language "GLSL"
parts [
ShaderPart { type "VERTEX" url "glsl_phong_shading.vs" }
ShaderPart { type "FRAGMENT" url "glsl_phong_shading.fs" }
]
}
See Kambi VRML test suite, directory x3d/shaders/ for working demos of this.
Inline shader source code.
You can directly place shader source code inside of an URL. We recognize URL as containing direct shader source if it has any newlines and doesn't start with any URL protocol, example: shaders_inlined.x3dv.
This is a non-standard extension (although compatible at least with InstantPlayer).
Passing values to to GLSL shader uniform variables.
You can also set uniform variables for your shaders from VRML, just add lines like
inputOutput SFVec3f UniformVariableName 1 0 0to your ComposedShader node. These uniforms may also be modified by VRML events (when they are inputOutput or inputOnly), for example here's a simple way to pass current VRML time (in seconds) to your shader:
# ......
# somewhere within Appearance:
shaders DEF MyShader ComposedShader {
language "GLSL"
parts [
ShaderPart { type "VERTEX" url "my_shader.vs" }
ShaderPart { type "FRAGMENT" url "my_shader.fs" }
]
inputOnly SFTime time
}
# ......
# somewhere within grouping node (e.g. at top-level of VRML file)
DEF MyTimer TimeSensor { loop TRUE }
ROUTE MyTimer.time TO MyShader.time
Setting uniform values this way, from VRML fields/events, is supported for all required by spec types. So you can use VRML/X3D vector/matrix types to set GLSL vectors/matrices, you can use VRML/X3D multiple-value fields to set GLSL array types and such.
TODO: SFImage, MFImage field types are not supported yet.
Passing textures to to GLSL shader uniform variables.
You can also specify texture node (as SFNode field, or an array of textures in MFNode field) as a uniform field value. Engine will load and bind the texture and pass to GLSL uniform variable bound texture unit. This means that you can pass in a natural way VRML texture node to a GLSL sampler2D, sampler3D, samplerCube, sampler2DShadow and such.
shaders ComposedShader {
language "GLSL"
parts [
ShaderPart { type "FRAGMENT" url
" uniform sampler2D texture_one;
uniform sampler2D texture_two;
void main()
{
gl_FragColor = gl_Color *
max(
texture2D(texture_one, gl_TexCoord[0].st),
texture2D(texture_two, gl_TexCoord[1].st));
}
" }
]
initializeOnly SFNode texture_one ImageTexture { url "one.png" }
initializeOnly SFNode texture_two ImageTexture { url "two.png" }
}
A full working version of this example can be found in Kambi VRML test suite (look for file x3d/shaders/simple_multitex_shaders.x3dv), or see it here.
When using GLSL shaders in X3D you should pass all needed textures to them this way. Normal appearance.texture is ignored when using shaders. However, in our engine, we have a special case to allow you to specify textures also in traditional appearance.texture field: namely, when ComposedShader doesn't contain any texture nodes, we will still bind appearance.texture. This e.g. allows you to omit declaring texture nodes in ComposedShader field if you only have one texture, it also allows renderer to reuse OpenGL shader objects more (as you will be able to DEF/USE in X3D ComposedShader nodes even when they use different textures). But this feature should not be used or depended upon in the long run.
Note that for now you have to pass textures in VRML/X3D events. Using inputOnly event to pass texture node to GLSL shader will not work.
TODO
TODO: attributes for shaders in VRML are not yet passed. They are implemented in the engine classes of course, it's only a matter of implementing link between VRML and them. If you have some interesting VRML / X3D models that use these programmable shaders features, feel free to contact me and I'll implement them in our engine.
(I mean, I will implement them anyway some day, but it's always much more interesting to implement features when you actually have a real use for them... In other words, I'm just dying to see some beautiful VRML/X3D models that heavily use programmable shaders :).
TODO: activate event doesn't work to relink the GLSL program now. (isSelected and isValid work perfectly for any X3DShaderNode.)
StaticGroup
(Although it doesn't make any extra optimization. This is not needed for our engine, as we initially treat pretty much everything as if it would be inside StaticGroup, that is we assume that model will be mostly static. Although it greatly depends on renderer optimization chosen.)
OrthoViewpoint
TODO: Although it's handled, some fields are ignored for now: jump, retainUserOffsets, centerOfRotation.
New X3D rendering primitives implemented:
IndexedTriangleSet, TriangleSet, IndexedQuadSet, QuadSet
IndexedTriangleFanSet, TriangleFanSet, IndexedTriangleStripSet, TriangleStripSet
LineSet (IndexedLineSet is also handled, this is part of VRML 2.0)
TODO: missing is only the implementation of new X3D fields attrib and fogCoord.
TODO: for TriangleFanSet and TriangleStripSet, a special constraint is present: if you will use colors (colors are always per-vertex on these primitives, according to X3D spec) and request generation of per-face normals at the same time, for the same lit (with material) node, then shading results will be slightly incorrect. Like this:
#X3D V3.0 utf8
PROFILE Interchange
Shape {
appearance Appearance { material Material { } }
geometry TriangleFanSet {
coord Coordinate { point [ 0 0 0, 1 0 0, 1 1 0, 0.5 1.5 0.5 ] }
fanCount 4
color Color { color [ 1 0 0, 0 1 0, 0 0 1, 1 1 1 ] }
normalPerVertex FALSE
}
}
Unfortunately, this is quite unfixable without falling back to worse rendering methods. Shading has to be smooth to interpolate per-vertex colors, and at the same time the same vertex may require different normals on a different faces. So to render this correctly one has to decompose triangle fans and strips into separate triangles (like to IndexedTriangleSet) which means that rendering is non-optimal.
Ideas how to implement this without sacrificing rendering time are welcome. Eventually, a fallback to internally convert fans and strips to IndexedTriangleSet in such special case will be implemented some day.
Note: As far as I see, X3D specification doesn't specify what to do for triangle/quad sets when appearance specify a texture but no texCoord is given. Our engine currently takes the IndexedFaceSet approach for automatic generation of texture coords in this case, let me know if this is wrong for whatever reason.
solid field added to many simple nodes (like Box, Sphere) is handled, allows to you to turn on or off back-face culling for them.
TextureProperties
minificationFilter, magnificationFilter, anisotropicDegree are supported. TODO: rest is not.
KeySensor
The first sensor node actually implemented :)
TODO: keyPress/Release generate only 8-bit ASCII characters now.
All event utilities: BooleanFilter, BooleanToggle, BooleanTrigger, IntegerTrigger, TimeTrigger, BooleanSequencer, IntegerSequencer
Rectangle2D, Circle2D
HAnim nodes:
Humanoid, Joint, Segment, Site, Displacer
HAnimHumanoid, HAnimJoint, HAnimSegment, HAnimSite, HAnimDisplacer (X3D version)
We have the basic HAnim support, which means that we can correctly render your human designed with HAnim nodes and efficiently animate it through VRML interpolators.
As you see, X3D version has exactly the same nodes, working the same way, but with HAnim prefix before node name. (I have no idea why this prefix was added in X3D specification, but it's supported.) Actually we allow both versions (with HAnim prefix and without) in all VRML and X3D versions (with our enfgine you can generally mix VRML versions). But VRML authors/generators should not overuse this, and try to conform to appropriate spec where possible.
The implementation takes some care to handle all existing VRML versions: HAnim 1.0, HAnim 1.1, HAnim 200x.
Animating transformations of Joint nodes and such is optimized, just like for Transform node, be sure to select roSeparateShapeStatesNoTransform method.
TextureTransformMatrix3D, TextureTransform3D,
TextureCoordinate3D, TextureCoordinate4D,
ImageTexture3D, ComposedTexture3D, PixelTexture3D
3D textures, coordinates for 3D textures, transforming coordinates for 3D textures — all done.
Note that 3D and 4D (homogeneous) coordinates, and transformations in 3D space / by 4x4 matrix, may be used to transform 2D textures as well. In case of 2D textures, the 3rd component is just ignored and the 4th is normal divisor (as usual for homogeneous coordinates).
DDS file format to specify 3d (volume) textures is supported by ImageTexture3D.
Note that PixelTexture3D with RGBA values has a problematic behavior because it uses MFInt32 field for colors. When you encode RGBA colors (following SFImage specification), the most significant byte of Int32 may have to be non-zero, which means that you will have to write negative values inside PixelTexture3D.image. (Of course we handle it correctly, I'm just signalling there's a strangeness here. For normal SFImage fields this problem doesn't exist because our lexer can actually understand integer values outside of int32 range, so when parsing SFImage this is handled Ok, without going through int32.)
Automatic 3D texture coord generation for primitives (Box, Sphere, Cone, Cylinder) is done (according to X3D spec, 33.2.4 Texture coordinate generation for primitive objects). TODO: Although it's reversed on the bottom disk of Cone and Cylinder for now.
TODO: modes MODULATEALPHA_ADDCOLOR, MODULATEINVALPHA_ADDCOLOR, MODULATEINVCOLOR_ADDALPHA are temporarily not supported.
TODO: source values "DIFFUSE" and "SPECULAR" are treated the same, as PRIMARY_COLOR (in the sense of OpenGL ARB_texture_env_combine extension). Primary color contains material ambient, diffuse and specular factors, multiplied by lighting properties, summed over all lights. I don't know of any way to efficiently implement separate diffuse / specular sources — please report if you do, otherwise there's no way this can be fixed (note that engine's multi-texturing must work without shaders too).
TODO: function field is not supported for now. It's somewhat uncomfortable, corresponding OpenGL settings (GL_OPERANDx) operate before normal texture unit calculations are done, while X3D spec requires function to act afterwards. To implement it generally, I'd have to use 1 more texture unit than requested (if the last texture unit will use any non-default function).
See clarifications to X3D multi-texturing specification below for more details about multi-texture handling.
Supported modes are now "SPHERE", "COORD", "COORD-EYE", "CAMERASPACEPOSITION", "CAMERASPACENORMAL", "CAMERASPACEREFLECTIONVECTOR".
Note that "CAMERASPACEPOSITION" and "COORD-EYE" are exactly the same thing. Google confirms it (e.g. this source code also treats them as equal and in this old bitmanagement spec they mention they are equal).
As an extension, we also allow "WORLDSPACEREFLECTIONVECTOR" and "WORLDSPACENORMAL" texture generation modes.
TODO: not implemented modes: "SPHERE-LOCAL", "NOISE", "NOISE-EYE", "SPHERE-REFLECT", "SPHERE-REFLECT-LOCAL".
Orientation notes: The images are expected to be oriented just like for the VRML/X3D Background node. This is suggested by the drawing in the spec, although the spec doesn't specify exact orientation of the images. We use Background node orientation, as this is definitely sensible. See Background node spec, paragraph with words "... when viewed from the origin looking down the negative Z-axis ...".
Size notes: Texture size for cube maps is automatically adjusted to be power of two, square, and within OpenGL limits (GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB). So your textures do not necessarily have to be provided with required sizes (if you don't mind a little quality loss because of scaling).
You still must provide equally sized images for all six cube map sides. Our engine makes sure to scale them to be square and power-of-two, but we currently do not attempt to make all six textures equal — so you have to provide textures already satisfying this.
We add textureProperties field to the ComposedCubeMapTexture node, intended for TextureProperties child, working just like in other texture nodes (you can use it to set minification / magnification filter, anisotropy and such). Although X3D 3.2 specification doesn't mention this, it seems natural, and instantreality also uses this. We support for cube maps all normal texture filterings, including mipmaps.
DDS file format to specify cube maps (including S3TC compressed cube maps) is supported.
Texture is rendered from the middle 3D point of bounding box of the shape using this texture. You cannot reUSE the same GeneratedCubeMapTexture node for various shapes (as then we would not know from which shape to generate).
The texture before generation (e.g. if you have update = 'NONE' at the start) has pink color (RGB(255, 0, 255)), so you can easily recognize it.
All the generated textures are rendered in a separate pass before actual rendering, and during this generation other shapes use existing values of their textures. This means that recursive mirrors, i.e. mirror that can be seen in another mirror, works to any level (each frame rendered uses textures generated in the previous frame). You can see recursive mirrors in some examples in Kambi VRML test suite (see x3d/cubemap_generated_recursive.x3dv x3d/cubemap_generated_in_dynamic_world.x3dv).
Provided size will automatically be adjusted to be power of two, and within OpenGL limits (GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB).
Current player camera doesn't affect how cube map is generated. This is good, it means that generated texture is usable for as long as the scene remains unchanged, and doesn't have to be regenerated each time when the player moves.
When update = "ALWAYS", this optimization is automatically used under the hood. Texture is internally not updated every frame — when we know nothing visible changed on the scene, we do not regenerate the texture (since it would be generated the same). Note that using the headlight, or any other geometry/light following the player, makes this optimization less effective (as then every camera move changes the look of the scene, so rendered textures have to be regenerated on every camera move).
This also means that generated cube map texture is similar to static (from ImageCubeMapTexture and ComposedCubeMapTexture), and you usually want to use "WORLDSPACEREFLECTIONVECTOR" texture generation to simulate mirror. When using cube maps with GLSL shaders, this often forces the need to transform directions from eye-space to world-space, you can obtain appropriate matrix easily by Viewpoint.cameraRotationInverseMatrix output event.
To allow different texture modes for RGB and for alpha channel, you should just write two mode names inside one string, and separate them by a comma or slash (additional whitespace around is allowed). For example, mode [ "MODULATE / REPLACE" ] means that on the 1st texture unit, RGB is modulated and alpha is replaced. Contrast this with mode [ "MODULATE" "REPLACE" ], that means to modulate (both RGB and alpha) on the 1st texture unit, and then to replace (both RGB and alpha) on the 2nd texture unit.
This way we keep the interpretation that "one string on the mode field always describes full behavior of exactly one texture unit". Of course, some modes are not available for alpha channel (these are the OpenGL constraints).
Table below describes precise behavior and disallowed situations for all mode names. Treat this as a corrected and precise version of the similar table in X3D spec of MultiTexture (see text down for details where and why it's corrected, short version: specification is simply poor and inconsistent). In table below,
| Mode name | Behavior when used alone (like "REPLACE") |
Behavior when used for only RGB channel (like "REPLACE / ...") |
Behavior when used for only alpha channel (like "... / REPLACE") |
|---|---|---|---|
| MODULATE | Output.RGBA := Arg1.RGBA * Arg2.RGBA | Output.RGB := Arg1.RGB * Arg2.RGB | Output.A := Arg1.A * Arg2.A |
| MODULATE2X | Output.RGBA := Arg1.RGBA * Arg2.RGBA * 2 | Output.RGB := Arg1.RGB * Arg2.RGB * 2 | Output.A := Arg1.A * Arg2.A * 2 |
| MODULATE4X | Output.RGBA := Arg1.RGBA * Arg2.RGBA * 4 | Output.RGB := Arg1.RGB * Arg2.RGB * 4 | Output.A := Arg1.A * Arg2.A * 4 |
| REPLACE or SELECTARG1 | Output.RGBA := Arg1.RGBA | Output.RGB := Arg1.RGB | Output.A := Arg1.A |
| SELECTARG2 | Output.RGBA := Arg2.RGBA | Output.RGB := Arg2.RGB | Output.A := Arg2.A |
| ADD | Output.RGBA := Arg1.RGBA + Arg2.RGBA | Output.RGB := Arg1.RGB + Arg2.RGB | Output.A := Arg1.A + Arg2.A |
| ADDSIGNED | Output.RGBA := Arg1.RGBA + Arg2.RGBA - 0.5 | Output.RGB := Arg1.RGB + Arg2.RGB - 0.5 | Output.A := Arg1.A + Arg2.A - 0.5 |
| ADDSIGNED2X | Output.RGBA := (Arg1.RGBA + Arg2.RGBA - 0.5) * 2 | Output.RGB := (Arg1.RGB + Arg2.RGB - 0.5) * 2 | Output.A := (Arg1.A + Arg2.A - 0.5) * 2 |
| SUBTRACT | Output.RGBA := Arg1.RGBA - Arg2.RGBA | Output.RGB := Arg1.RGB - Arg2.RGB | Output.A := Arg1.A - Arg2.A |
| OFF | Texture stage is simply turned off. | Not allowed. | |
| DOTPRODUCT3 | NewArg1.RGB := (Arg1.RGB - 0.5) * 2; NewArg2.RGB := (Arg2.RGB - 0.5) * 2; Output.RGBA := dot(NewArg1.RGB, NewArg2.RGB) |
... (calculate NewArg* same as on the left)... Output.RGB := dot(NewArg1.RGB, NewArg2.RGB) |
Not allowed. |
| BLENDDIFFUSEALPHA | Output.RGBA := Arg1 * PRIMARY_COLOR.Alpha + Arg2 * (1 - PRIMARY_COLOR.Alpha) |
Not allowed. | |
| BLENDTEXTUREALPHA | Output.RGBA := Arg1 * Arg1.A + Arg2 * (1 - Arg1.A) |
Not allowed. | |
| BLENDFACTORALPHA | Output.RGBA := Arg1 * MULTI_TEXTURE_CONSTANT.Alpha + Arg2 * (1 - MULTI_TEXTURE_CONSTANT.Alpha) |
Not allowed. | |
| BLENDCURRENTALPHA | Output.RGBA := Arg1 * PREVIOUS_STAGE.Alpha + Arg2 * (1 - PREVIOUS_STAGE.Alpha) |
Not allowed. | |
In the same spirit, you can specify separate sources for RGB and alpha channels, just separate them by comma or slash within a single string. For example, source string "DIFFUSE / FACTOR" says to take diffuse color as a source for Arg2.RGB and constant factor (MultiTexture.alpha field) for Arg2.Alpha.
Note that the empty string is also a source name (it means to take color from previous texture stage). So source string like "/ FACTOR" is also Ok (takes RGB from previous stage, and alpha from constant factor), and "FACTOR /" is Ok (takes RGB from constant factor MultiTexture.color, and alpha from previous stage).
An example: suppose you have two textures that you want to subtract on RGB (tex2 - tex1) channel, and you want to set resulting alpha channel to 1.0 (regardless of any texture value). This will work:
MultiTexture {
texture [
ImageTexture { url "tex1.png" }
ImageTexture { url "tex2.png" }
]
mode [ "REPLACE" "SUBTRACT / SELECTARG2" ]
source [ "" " / FACTOR" ]
alpha 1.0
}
# Calculations on texture unit 1:
# Stage1Output.RGBA := Tex1.RGBA;
# Calculations on texture unit 2:
# Output.RGB := Tex2.RGB - Stage1Output.RGB;
# Output.A := Arg2.A := 1.0;
Unfortunately, X3D specification is awfully ambiguous when talking about multi-texturing modes. Below is my list of spotted problems, and an explanation how we handle it in our engine (for a short summary, modes table in section above should also be informative). I tried to make my implementation following common-sense, hopefully it will be somewhat compatible to other implementations and at the same time comfortable to users.
Please report if any other VRML/X3D browser treats it differently, although it doesn't necessarily mean that I will fix to be compatible (I know that Octaga seems to revert the order of textures, for starters, which seems to contradict the spec... No wonder people get this messed up, since specification is so poor at this point.)
(And if you have any power over the spec, please fix issues mentioned below in the next version. It seems I'm not the only one confused by specs. I posted on forum asking for input about this, without any answer so far.)
The mode field may contain an additional blending mode for the alpha channel. — this is the most troublesome part of the specification. It contradicts most of the remaining specification for MultiTexture node — other parts clearly suggest that exactly one mode string corresponds to one texture unit, for example 1. it's mentioned explicitly that if the mode.length is less than texture.length, remaining modes should be assumed as "modulate" 2. many modes are clearly used over both RGB and Alpha channels, and they specify results for both RGB and Alpha channels.
This means that the meaning of mode=["MODULATE","REPLACE"] is not clear.
What did the authors meant by the word may in the sentence "may contain an additional blending mode"? Expecting two mode strings for one texture unit clearly contradicts the spec, expecting only 1 mode means that no mode specific for alpha channel is available. Doing some smart detection when to expect the next mode to be for alpha channel seems very risky — since the specification says absolutely nothing about it. Should I expect separate mode for alpha channel only when the texture in current unit has some alpha channel? This isn't as sensible on the 2nd look, since operating on alpha channel in multi-texturing makes sense even if current texture unit doesn't provide any (after all, alpha may come from previous unit, or constant).
Not to mention that some modes are clearly not possible for alpha channel.
Our interpretation: One string inside the mode field always describes behavior for both RGB and alpha channel. So one string inside mode field always corresponds to one texture unit, Ok?.
To allow different modes for RGB and alpha channel, you should just write two mode names inside one string, and separate them by a comma or slash. Like "MODULATE / REPLACE". See the modes table in previous section for a list of all possible values.
In Table 18.3 - Multitexture modes, "REPLACE" mode is specified as "Arg2", which makes no sense. Arg2 comes by default from previous unit (or material color), this is implicated by the sentence "The source field determines the colour source for the second argument". So mode "REPLACE" interpreted as "Arg2" would then 1. completely ignore current texture unit 2. contradict the normal meaning of "REPLACE", which is explicitly mentioned in specification at paragraph before this table ("REPLACE for unlit appearance"). An example with alpha (although ambiguous on it's own, more about this in previous point) clearly shows that "REPLACE" takes from 1st argument.
Our interpretation: "REPLACE" copies the "Arg1" (that is, current texture unit values). IOW, it's equivalent to "SELECTARG1". To make it absolutely clear, it would also help if the spec would clearly say something along the lines "Arg1 is the current texture unit, Arg2 is what is determined by the source field (by default, it's previous tex unit (or mat color for 1st unit))".
The meaning of "ADDSIGNED" and "ADDSIGNED2X" is unsure. Spec doesn't give the exact equation, and from the wording description it's not clear whether the -0.5 bias is applied to the sum, or each component.
Note that no interpretation results in the output range of values in -0.5 ... 0.5, so it's not clear what is the "effective" range they talk about in "ADDSIGNED" spec.
Our interpretation: I interpret it as "-0.5 bias is added to the sum", this follows OpenGL GL_ADD_SIGNED constant, so I guess this was the intention of the spec.
Although some modes say explicitly what happens with alpha channel, some do not. This is especially visible with "subtract" mode, that will subtract alphas making resulting alpha = 0 for the most common situation when both textures have alpha = 1.
Our interpretation: I interpret this all as operating on all RGBA channels the same way. Comparing with Octaga, results for "subtract" seem equal this way: with default alphas = 1, result gets alpha = 0.
If you don't like this behavior, you can specify separate mode names for RGB and alpha channel, separating them by a slash. For example, "SUBTRACT / MODULATE" will subtract RGB but modulate alpha.
It's not specified what channels are inverted by function="COMPLEMENT" value. Only RGB seems most sensible (that's what would seem usually useful), but it's not written explicitly.
Our interpretation: I plan to treat it as "only RGB", that is not invert alpha channel. Although for now "function" field is not handled.
Oh, by the way: the paragraphs for MultiTextureTransform (texture coordinates for channel 0 are replicated...) and MultiTextureCoordinate (identity matrices are assumed...) should be swapped in the spec :)
Another note: MODULATEINVCOLOR_ADDALPHA mentions that another mode, somehow forgotten, should exist: MODULATECOLOR_ADDALPHA (that doesn't invert the color).
Implementation history:
Cube maps in DDS are supposed to be oriented as usual for DDS:
Which means that they match Direct X "positive/negative x/y/z". For OpenGL rendering we swap positive/negative Y faces (because Direct X has left-handed coordinate system, see here for drawing of DirectX cube map images orientation and compare with OpenGL cube map orientation).
It's also a different orientation then the one of X3D ComposedCubeMap specification (left/right, bottom/top, front/back, with bottom/top on Y axis; X3D orientation needs rotating left,right,front,back images by 180 degrees for OpenGL orientation).
Images in DDS are supposed to be written from top to bottom row, as is the standard in DDS. (One particular tool, AMD CubeMapGen, allows to invert rows of the DDS images to match OpenGL bottom-to-top ordering; don't use this — we expect rows ordered as is standard in DDS, top-to-bottom.) Internally, our engine just inverts the rows for OpenGL (yes, this is doable also for S3TC compressed images.)
Pixel formats supported:
Absolutely all uncompressed non-float pixel formats are supported.
Details:
The formats that are currently loaded optimally are ABGR8, BGR8, AL8, L8. They translate to RGBA8, RGB8 etc. OpenGL formats (reversed order, as DDS color masks are little-endian). Popular ARGB8 and RGB8 are also loaded very fast.
Grayscale (luminance) images are allowed. AL8 and L8 are optimized. Note that grayscale images aren't officially allowed by DDS docs, but at least GIMP-DDS plugin can write it (just sets all R, G and B masks equal, and doesn't set any of DDPF_RGB, DDPF_FOURCC, DDPF_PALETTEINDEXED8).
Also only-alpha images are allowed (another undocumented DDS feature, GIMP-DDS can write it, for now they will result in grayscale(white) with alpha image).
Compressed texture formats handled: DXT1, DXT3, DXT5 are supported. Texture with DXT1 is always treated like a texture with simple (yes/no) alpha channel (so it will be rendered with alpha testing) and DXT3 / DXT5 are always treated like a texture with full range alpha channel (so they will be rendered with blending).
Both normal (2D) textures and cube maps may be compressed. (There is no compression possible for 3D textures — neighter DDS format allows it, nor do common graphic cards.)
Float textures are for now not supported, so our DDS reader also doesn't support them.
If DDS file includes mipmaps, and mipmaps are required for texture minification filter, we will use DDS mipmaps (instead of generating mipmaps automatically). Works for all 2D, 3D, cubemap DDS files.
All nodes from VRML 2.0 specification are correctly parsed. The list below lists nodes that are actually handled, i.e. they do things that they are supposed to do according to "Node reference" chapter of VRML spec.
TODO for all nodes with url fields: for now all URLs are interpreted as local file names (absolute or relative). So if a VRML file is available on WWW, you should first download it (any WWW browser can of course download it and automatically open view3dscene for you), remembering to download also any texture/background files used.
Nodes listed below are fully (except when noted with TODO) supported :
Note: VRML 2.0 SpotLight.beamWidth idea cannot be translated to a standard OpenGL spotlight, so if you set beamWidth < cutOffAngle then the light will not look exactly VRML 2.0-spec compliant. Honestly I don't see any sensible way to fix this (as long as we talk about real-time rendering using OpenGL). And other open-source VRML implementations rendering to OpenGL also don't seem to do anything better.
VRML 2.0 spec requires that at least 8 lights are supported. My units can support as many lights as are allowed by your OpenGL implementation, which is at least 8.
Background, Fog
NavigationInfo
Various details about how we handle NavigationInfo node in view3dscene:
When no NavigationInfo node is present in the scene, we try to intelligently guess related properties. (We try to guess "intelligently" because simply assuming that "no NavigationInfo node" is equivalent to "presence of default NavigationInfo" is not good for most scenes).
WorldInfo
Note: WorldInfo.title, if set, is displayed by view3dscene on window's caption.
Switch, Group, Transform
Including special optimizations for animating transformations, be sure to select roSeparateShapeStatesNoTransform method.
Sphere, Box, Cone, Cylinder
Shape, Appearance, Material
TextureTransform, PixelTexture, ImageTexture
Note: ImageTexture allows various texture formats, including JPEG, PNG, BMP, PPM, RGBE. GIF format is supported by running convert program from ImageMagick package "under the hood". See glViewImage documentation for more detailed list.
Note about alpha channel: alpha channel of the textures is fully supported, both a simple yes-no transparency (done by alpha_test in OpenGL) and full range transparency (done by blending in OpenGL, just like partially transparent materials). See "override alpha channel detection" extension description for details. The bottom line is: everything will magically work fast and look perfect.
Note about REPLACE vs MODULATE modes: VRML 2 / X3D specifications say that RGB textures should REPLACE the color (as opposed to MODULATE the color from lighting calculations, material etc.). The problem with that is that this makes RGB textures nearly useless in typical 3D world (when you usually expect textured surfaces to be properly lit, regardless of RGB or grayscale format). That's why the default engine behavior contradicts the specification: it's MODULATE, making an RGB texture modulated by lighting just like a grayscale texture.
I didn't decide it lightly (noone likes to deliberately contradict the specification...), but I think this case is justified --- MODULATE behavior is much more useful and usually desired, IMO. Feel welcome to send me emails and argument against this. After all, I'm trying to fit the needs of most people with default behavior. If many people think that specification is right and I'm dumb, and the default behavior should follow the spec and be REPLACE, I'll obey :)
You have menu item in view3dscene RGB Textures Color Mode -> GL_REPLACE to change this (from code, use Scene.Attributes.TextureModeRGB := GL_REPLACE;).
MovieTexture
TODO: for now, the sound of the movie is not played.
Notes:
Current implementation keeps the whole encoded video in memory (images may be discarded after loading (by TVRMLScene.FreeResources feature), but still the textures for all frames are kept in memory). The disadvantage is that this makes it impractical to load "real" movies, normal 2-hour movie will most usually eat all of your memory. The advantage is that once the movie is loaded, the playback is super-fast, just like you would display normal nodes with static textures. Since there's no streaming, decoding etc. in the background while you browse your models.
In other words, this is quite perfect for movie textures with game effects, like smoke or flame. But it's not a substitute for your "real" multimedia movie player.
ffmpeg must be installed and available on $PATH to actually open any movie format. See instructions for installing ffmpeg in view3dscene docs. Thanks to ffmpeg, we can handle probably any movie format you will ever need to open.
We can also open movies from images sequence. This doesn't require ffmpeg, and allows for some tricks (movie texture with alpha channel). See "Movies from images sequence" extension description.
Inline, InlineLoadControl
Yes, this includes handling of InlineLoadControl features to react to load, url and generate children events. For X3D, basic Inline node already has load, url features and they also work perfectly.
LOD
Note: We do not have any automatic LOD calculation implemented now, which means that your supplied range, and only your supplied range, controls which LOD is chosen. This means that forceTransitions value is simply ignored, and when range is empty, we simply always use the first (highest-detail) version. This is Ok, spec allows this.
Anchor
TODO: parameter field is ignored, everything else is handled (according to X3D spec).
Text, FontStyle
Most important properties (size, spacing, justify, family, style) are handled fully.
TODO: But some properties are ignored for now:
Text is "clickable" within
Anchor and TouchSensor nodes.
Although I didn't find any mention in the specifications that I should
do this, many VRML models seem to assume this.
We make an ultra-simple triangulation of the text
(just taking 2 triangles to cover whole text, you don't want
to produce real triangles for text node, as text node would have
a lot of triangles!).
TODO: unfortunately, for now these triangles also participate
in collision detection, while spec says that text shouldn't collide.
Viewpoint
Note: view3dscene displays also nice menu allowing you to jump to any defined viewpoint, displaying viewpoints descriptions. Extensive tests of various viewpoint properties, including fieldOfView, are inside my VRML test suite in vrml_2/viewpoint_*.wrl files.
Animating viewpoint's position and orientation (directly or by it's transformations) works perfectly.
TODO: visibilityLimit may be ignored if shadow volumes are allowed (We use frustum with z-far in infinity then.)
PointSet, IndexedLineSet, IndexedFaceSet, Coordinate, Color, Normal, TextureCoordinate
Billboard
TODO: Not really handled: it just works like a Group. Often that's enough for it to look sensible, but it's hardly a real support...
Collision
Most things work: grouping (children property, in particular), allows to control collision detection by honoring enabled (named collide in VRML 97) and proxy fields.
bboxCenter/Size is currently simply ignored, our engine always calculates and updates the bounding boxes where needed.
TODO: collideTime and isActive out events are not implemented yet.
ElevationGrid
TODO: when colors are present and colorPerVertex is different than normalPerVertex (from field or calculated based on creaseAngle) then shading results may be incorrect. Reasons for this — see comments about X3D [Indexed]TriangleFan/StripSet above on this page.
TODO: creaseAngle is not fully handled: we always generate all flat normals (if creaseAngle = 0) or all smooth normals (if creaseAngle <> 0).
Extrusion
Works fully.
ColorInterpolator, PositionInterpolator, PositionInterpolator2D (X3D), ScalarInterpolator, OrientationInterpolator
CoordinateInterpolator, CoordinateInterpolator2D (X3D), NormalInterpolator
TODO: Interpolation of ColorInterpolator simply interpolates 3D vectors, so it interpolates in RGB space (while spec says to interpolate in nice HSV space).
Interpolation of OrientationInterpolator simply interpolates 4D vectors, instead of a nice interpolation on the unit sphere.
Interpolation of NormalInterpolator simply interpolates 3D vectors (and normalizes afterwards), instead of a nice interpolation on the unit sphere.
TimeSensor
All common X3DTimeDependentNode things are implemented. enabled is honored. time is generated.
TODO: fraction_changed simply generates elapsedTime / cycleInterval value. This is quite Ok for most uses.
As for "time origin" in our engine, this follows VRML standard (time origin is "January 1, 1970"), but it can be changed by our extension KambiNavigationInfo.timeOriginAtLoad.
TouchSensor
TODO: hitTexCoord_changed is not working, and hitNormal_changed generates only the flat (per-face) normal. Everything else works perfectly, which should be Ok for typical uses.
ProximitySensor
TODO: centerOfRotation_changed are not generated. Rest works Ok, according to spec. Timestamps for isActive, enter/exitTime are not interpolated (they are simply timestamps when this was detected), this shouldn't be a problem in typical uses.
Script
We handle special script protocols compiled: (to link scripts with handlers written in compiled language (ObjectPascal)) and kambiscript: (simple scripting language specific to our engine).
TODO: no standard scripting language, like ECMAScript, is implemented now. directOutput field of script node is ignored (compiled: scripts have always direct access to whole VRML scene, kambiscript: has never access to VRML nodes).
mustEvaluate is also ignored for now. This is non-optimal but valid behavior. Our current scripting protocols have no "loading" overhead (we don't initialize any scripting engine, kambiscript: and compiled: scripts are just tightly built-in the engine) so this doesn't hurt us in practice.
Prototypes (both external and not) are 100% done and working :) External prototypes recognize URN of standard VRML 97 nodes, i.e. urn:web3d:vrml97:node:Xxx and standard X3D nodes (urn:web3d:x3d:node:Xxx), see also our extensions URN on Kambi VRML extensions.
Events, routes mechanism is implemented since 2008-08-11 :)
TODO: Some general features not implemented yet are listed below. They all are parsed correctly and consciously (which means that the parser doesn't simply "omit them to matching parenthesis" or some other dirty trick like that). But they don't have any effect on the scene. These are:
I consider VRML 1.0 status as "almost complete". All nodes and features are handled, with the exception of:
VRML 1.0 features that will probably never be implemented, as they are replaced with much better mechanisms in newer VRML versions:
AsciiText node's triangles and vertexes are not counted when writing triangles and vertexes counts of the scene. This is actually somewhat Ok, as later VRML specs say explicitly that Text nodes do not participate in collision detection (so they do not have triangles/vertexes for collision detection, only for rendering).
Clicking on WWWAnchor doesn't work (use VRML >= 2.0 Anchor instead, implementing old VRML 1.0 anchor is not worth the trouble and would unnecessarily obfuscate the code).
I'm always rendering the nearest (first) child of VRML 1.0 LOD node. Therefore I'm potentially losing some optimization if the scene has reasonably designed LOD nodes.
Reason: this is caused by possible "leaking" of properties in VRML 1.0. Change of LODs choice could potentially change the look of the whole scene (that is, different LOD children may cause the other nodes, following LOD node, to have different meaning). That's why implementing LOD node correctly and fast is very very hard in VRML 1.0. So much that it's not worth the trouble.
For the same reason, changing VRML 1.0 Switch.whichChoice is not optimized and works slow. Although you will probably not notice this, since there's no event mechanism in pure VRML 1.0.
Note that VRML >= 2.0 LOD node is working fast and switches between children, according to spec. Also Switch.whichChoice changing is optimized and instantly fast in VRML >= 2.0. So just upgrade to VRML 2.0 (aka 97) or X3D if you need these features.
Camera focalDistance is also ignored, but this is allowed by specification. And honestly VRML 1.0 specification is so ambiguous about this feature (browser should adjust flying speed to reach that point in a reasonable amount of time, perhaps the browser can use this as a hint...) that I see no reliable way to handle focalDistance.
Fortunately, VRML 2.0 replaced this with NavigationInfo.speed feature, with clear meaning (basically, it's just a distance per second), so please use this instead. (For my engine, you can use NavigationInfo node even in VRML 1.0 models.)
Extensibility features (isA and fields) are not handled fully, although you probably will not notice. For built-in nodes, isA and fields are correctly parsed but ignored. For unknown nodes, they are simply omitted up to the matching closing parenthesis.
This means that the only case when you will notice something doesn't work is when you use non-standard VRML node but point to a standard node with isA declaration. Then my engine will ignore isA declaration, while it should use it to interpret your node and (at least partially, when possible) handle it.
Finishing of handling this VRML 1.0 feature has rather low priority, since this mechanism was completely dropped in later VRML versions. VRML 2.0 and X3D replaced this by fantastic prototypes mechanism, which is basically an extra-powerful and elegant way of doing what VRML 1.0 tried to do with isA and fields feature (and VRML prototypes are already handled 100% by our engine).
MFString field with strings not enclosed in double quotes will not be parsed correctly. Moreover, parsing SFStrings not enclosed in double quotes is implemented rather as a "quick & dirty hack" than as a nice solution. Really, it's a weird "feature" of VRML 1.0 (fortunately eliminated in VRML 97) to allow strings not enclosed in double quotes. And I know about only one program that utilizes it (Blender) and this program uses it only in SFString field (Texture2.filename). So I doubt I will ever fix this to MFString — I would consider it a waste of time, since it's really a VRML-1.0-specific totally useless and uncommon syntax feature.
Note that some unclear parts of VRML 1.0 specification are handled according to VRML 97 specification. Also, our ray-tracer uses lighting model defined for VRML 97 (since VRML 1.0 didn't define any lighting model precisely).
Tested on our Kambi VRML test suite.
Examples from VRML 2.0 specification and The Annotated VRML 97 Reference were tested.
Files generated by Blender VRML 2.0 exporter are handled. I think that I support fully everything that can be generated by this exporter.
From Chaco's VRML Test Suite passes every file (that exists on server — some are missing, although I fixed missing texture for tests) besides recurse.wrl — it's an incorrect file, we should produce better error message for it.
NIST VRML Test Suite results are below.
Each test was classified as "pass" only if it passed fully. Which is a good objective measure, but also means that many tests failed because unrelated features are not implemented. For example, don't be discouraged by many failures in PROTO category. Prototypes were 100% working in all tests, and I consider their implementation as practically finished. But unrelated things like missing Script support for ECMAScript prevented the tests in PROTO category from passing completely.
Cases are marked above as "success" (+) only if they succeed completely. The style of table below was modeled after similar page OpenVRML Conformance Test Results.
| Node Group | Node | Test Number | Result | Notes |
|---|---|---|---|---|
| Appearance | Appearance | 1 | + | |
| 2 | + | |||
| 3 | + | |||
| 4 | + | |||
| 5 | + | |||
| 6 | + | |||
| 7 | + | |||
| 8 | + | |||
| 9 | + | |||
| 10 | + | You have to set RGB Textures Color Mode -> GL_REPLACE to get 100% correct result. | ||
| 11 | + | |||
| 12 | + | |||
| FontStyle | 1 | + | ||
| 2 | + | |||
| 3 | + | Note that the test looks strange because the X axis line starts at X = -200. This is an error in the test file. | ||
| 4 | + | |||
| 5 | + | |||
| 6 | - | For horizontal text test passes, but vertical text is not implemented yet. | ||
| 7 | - | Handling ECMAScript not implemented yet. | ||
| ImageTexture | 1 | + | ||
| 2 | + | |||
| 3 | + | |||
| 4 | + | |||
| 5 | + | |||
| 6 | + | |||
| 7 | + | |||
| 8 | + | |||
| 9 | + | |||
| 10 | + | |||
| 11 | + | |||
| 12 | + | |||
| 13 | - | The texture top is not aligned precisely with text top. | ||
| 14 | + | |||
| 15 | + | |||
| 16 | + | |||
| 17 | + | |||
| 18 | + | |||
| 19 | + | |||
| 20 | - | Like case 13: The texture top is not aligned precisely with text top. | ||
| 21 | + | |||
| 22 | + | |||
| 23 | + | |||
| 24 | + | |||
| 25 | + | |||
| 26 | + | |||
| 27 | + | |||
| 28 | + | |||
| 29 | + | |||
| 30 | + | |||
| 31 | + | |||
| 32 | + | |||
| 33 | + | |||
| 34 | + | |||
| Material | 1 | + | ||
| 2 | + | |||
| 3 | + | |||
| 4 | + | |||
| 5 | + | |||
| 6 | + | |||
| 7 | + | You have to set RGB Textures Color Mode -> GL_REPLACE to get 100% correct result. | ||
| 8 | + | |||
| 9 | + | |||
| 10 | + | |||
| 11 | + | |||
| 12 | + | |||
| 13 | + | |||
| 14 | + | |||
| 15 | + | |||
| 16 | + | |||
| 17 | + | |||
| 18 | + | |||
| 19 | + | |||
| 20 | + | |||
| 21 | + | |||
| 22 | + | |||
| 23 | + | |||
| 24 | + | |||
| 25 | + | |||
| 26 | + | |||
| 27 | + | |||
| 28 | + | |||
| 29 | + | |||
| MovieTexture | 1 | + | ||
| 2 | - | Audio from MovieTexture is not played yet | ||
| 3 | - | |||
| 4 | + | |||
| 5 | + | |||
| 6 | + | |||
| 7 | + | |||
| 8 | + | |||
| 9 | + | |||
| 10 | + | |||
| 11 | + | |||
| 12 | + | |||
| 13 | + | |||
| 14 | + | |||
| 15 | + | |||
| 16 | + | The movie text.mpg is still (5 identical frames, according to ffmpeg, gstreamer and xine) | ||
| 17 | + | |||
| 18 | + | |||
| 19 | + | |||
| PixelTexture | 1 | + | ||
| 2 | + | |||
| 3 | + | |||
| 4 | + | |||
| 5 | + | |||
| 6 | + | |||
| 7 | + | |||
| 8 | + | |||
| 9 | + | |||
| 10 | + | |||
| 11 | + | |||
| 12 | - | Texture top is not aligned precisely with Text top | ||
| 13 | + | |||
| 14 | + | |||
| 15 | + | |||
| 16 | + | |||
| 17 | + | |||
| TextureTransform | 1 | + | ||
| 2 | + | |||
| 3 | + | |||
| 4 | + | |||
| 5 | + | |||
| 6 | + | |||
| 7 | + | |||
| 8 | + | |||
| 9 | + | |||
| 10 | + | |||
| 11 | + | |||
| 12 | + | |||
| 13 | + | Results look a little different, but matching precisely Xj3D and OpenVRML results. | ||
| 14 | + | |||
| 15 | + | |||
| 16 | + | |||
| 17 | + | |||
| 18 | + | |||
| 19 | + | |||
| 20 | + | |||
| 21 | + | |||
| 22 | + | |||
| 23 | + | |||
| 24 | + | |||
| 25 | + | |||
| 26 | + | |||
| 27 | + | |||
| 28 | + | |||
| 29 | + | |||
| 30 | + | |||
| 31 | + | |||
| 32 | + | |||
| 33 | + | |||
| 34 | + | |||
| 35 | + | |||
| 36 | + | |||
| 37 | + | |||
| 38 | + | |||
| 39 | + | |||
| 40 | + | |||
| 41 | + | |||
| 42 | + | |||
| 43 | + | |||
| 44 | + | |||
| 45 | + | |||
| 46 | + | |||
| 47 | + | Results look slightly incorrect, but matching precisely Xj3D and OpenVRML results. I think this is a shortcoming of my GPU (ATI Mobility Radeon X1600), precisely transforming small textures may make small errors? | ||
| 48 | + | |||
| ...here I skipped some tests, to be checked later... | ||||
| Geometry | Box | 1 | + | This links to Text test, that passes (but has nothing to do with Box) |
| 2 | + | |||
| 3 | + | |||
| 4 | + | |||
| 5 | + | |||
| 6 | + | |||
| Cone | 1 | + | This links to Text test, that passes (but has nothing to do with Cone) | |
| 2 | + | Again, tests linking to unrelated testcases for Box node (that pass) | ||
| 3 | + | |||
| 4 | + | |||
| 5 | + | |||
| 6 | + | |||
| 7 | + | |||
| 8 | + | Unrelated Box test... (that passes) | ||
| Cylinder | 1 | + | Unrelated Text test again... | |
| 2 | + | Unrelated tests for Box again... | ||
| 3 | + | |||
| 4 | + | |||
| 5 | + | |||
| 6 | + | |||
| 7 | + | |||
| 8 | + | Unrelated Cone test... | ||
| 9 | + | Unrelated Box test... | ||
| ElevationGrid | 1 | + | Note that by default ElevationGrid is not smoothed (creaseAngle = 0), this is following the spec. | |
| 2 | + | |||
| 3 | + | |||
| 4 | + | |||
| 5 | + | |||
| 6 | + | |||
| 7 | + | |||
| 8 | + | |||
| 9 | + | The reference image of the test is bad. The result should be more obvious (whole rows of quads have the same normal), and it is — with our engine. | ||
| 10 | + | |||
| 11 | + | Although we use two-sided lighting. | ||
| 12 | - | Although we do generate smooth normals, they are not used since colorPerVertex forces us to use smooth shading. | ||
| 13 | + | |||
| 14 | + | |||
| Extrusion | 1 | + | ||
| 2 | + | Reference images show the incorrect non-uniform scaling of the caps. We handle it right. | ||
| 3 | + | |||
| 4 | + | |||
| 5 | + | |||
| 6 | + | |||
| 7 | + | |||
| 8 | + | |||
| 9 | + | |||
| 10 | + | |||
| 11 | + | |||
| 12 | + | |||
| 13 | + | |||
| 14 | - | While generally looks Ok, it seems that our triangulating algorithm can't handle this particular shape perfectly. | ||
| 15 | + | |||
| 16 | - | This links to ElevationGrid creaseAngle test, that fails... Has nothing to do with Extrusion actually. (And we do handle creaseAngle on Extrusion correctly!) | ||
| 17 | + | |||
| IndexedFaceSet | 1 | + | ||
| 2 | + | |||
| 3 | + | |||
| 4 | + | |||
| 5 | + | |||
| 6 | + | |||
| 7 | + | |||
| 8 | + | |||
| 9 | + | |||
| 10 | + | |||
| 11 | + | |||
| 12 | + | You have to set RGB Textures Color Mode -> GL_REPLACE to get 100% correct result. | ||
| 13 | + | |||
| 14 | + | |||
| 15 | + | |||
| 16 | + | |||
| 17 | + | |||
| 18 | + | |||
| 19 | + | |||
| 20 | + | |||
| 21 | + | |||
| IndexedLineSet | 1 | + | ||
| 2 | + | |||
| 3 | + | |||
| 4 | + | (These tests have nothing to do with IndexedLineSet, they are for IndexedFaceSet.) | ||
| 5 | + | |||
| 6 | + | |||
| 7 | + | (These tests have nothing to do with IndexedLineSet, they are for IndexedFaceSet.) | ||
| 8 | + | |||
| 9 | + | |||
| 10 | + | |||
| PointSet | 1 | + | ||
| 2 | + | |||
| 3 | + | |||
| 4 | + | |||
| 5 | + | |||
| Shape | 1 | + | ||
| 2 | + | |||
| 3 | + | |||
| 4 | + | |||
| 5 | + | |||
| Sphere | 1 | + | Unrelated Text tests... | |
| 2 | + | Unrelated Box tests... | ||
| 3 | + | |||
| 4 | + | |||
| 5 | + | |||
| 6 | + | |||
| Text | 1 | + | ||
| 2 | + | |||
| 3 | + | |||
| 4 | + | |||
| 5 | - | Text.length is not supported yet | ||
| 6 | - | |||
| 7 | - | |||
| 8 | - | Text.maxExtent is not supported yet | ||
| 9 | - | |||
| 10 | + | |||
| 11 | + | |||
| 12 | - | Texture mapping is a little incorrect, text is too small | ||
| ...here I skipped some tests, to be checked later... | ||||
| Misc | EXTERNPROTO | 1 | + | |
| 2 | + | |||
| 3 | + | |||
| 4 | + | |||
| 5 | + | |||
| 6 | + | |||
| 7 | + | |||
| 8 | - | Currently, base URL for EXTERNPROTO is from the file where EXTERNPROTO is written, not from the file where it's instantiated. | ||
| 9 | - | ECMAScript is not supported yet. Also, the DEF declaration inside a script causes known problem with cycles in VRML graph. | ||
| 10 | - | |||
| 11 | - | Scripts are not supported yet. | ||
| 12 | - | |||
| 13 | + | |||
| 14 | + | |||
| 15 | + | |||
| 16 | + | |||
| 17 | + | |||
| 18 | + | |||
| PROTO | 1 | + | ||
| 2 | + | |||
| 3 | + | |||
| 4 | + | |||
| 5 | + | |||
| 6 | + | (It links to unrelated Text test that works?) | ||
| 7A | + | Result is Ok, but we do not handle SphereSensor, Sound, AudioClip nodes (yet). | ||
| 7B | - | Static result seems Ok, but we do not handle VisibilitySensor (yet). Also Billboard is crude, although this is not noticeable here. | ||
| 7C | - | Static result seems Ok, but we do not handle VisibilitySensor and Collision.collideTime is not generated (yet). | ||
| 7D | + | |||
| 7E | + | |||
| 7F | + | Result is Ok, although actually we do not handle PlaneSensor (yet). | ||
| 7G | + | |||
| 7H | + | Result is Ok, although actually we do not handle ECMAScript (yet). | ||
| 7I | + | |||
| 7J | + | |||
| 7K | + | |||
| 8 | - | Although the tested features work Ok, there is a problem (unrelated to protos) with activating TouchSensor when SphereSensor is also enabled. We should activate them both simultaneously, currently only one (SphereSensor in this case, since it's first) is activated. | ||
| 9 | - | Tested features work perfectly. But VisibilitySensor is not handled (yet), so animation doesn't start (you can replace it by e.g. ProximitySensor with large sizes, and animation will work). | ||
| 10 | + | |||
| 11 | + | |||
| 12 | + | |||
| 13 | + | |||
| 14 | + | |||
| 15 | + | |||
| 16 | + | |||
| 17 | + | |||
| 18 | + | |||
| 19 | + | |||
| 20 | + | |||
| ... here I again skipped some tests ... | ||||
| Special_Groups | LOD | 1 | + | |
| 2 | + | Note that switching between Viewpoints in these tests has very strange VRML code. Namely there are interpolators with two equal keys (so they don't actually make any change, and this is correctly optimized in the engine). Moreover, they are connected to time sensors with 2 seconds cycle. This causes strange effects when clicking fast on various touch sensors, as many interpolators conquer to change the same Transform.position values. I'll emphasize: we handle it correctly, and optimize correctly, we have to evaluate simultaneous changes to the same field from various routes... The test is just strange, without any purpose. | ||
| 3 | + | |||
| 4 | + | |||
| 5 | + | |||
| 6 | + | |||
| Switch | 1 | + | This is actually an Anchor bound-500 test, that passes. (Possibly, wget messed up my local copy of NIST tests... Online server with NIST tests is broken, so I can't check). | |
| 2 | + | |||
| 3 | + | |||
| 4 | + | |||
| 5 | + | |||
| 6 | + | |||
| That's enough for now... I don't have time to check all the tests. If someone wants to do the work and do the remaining tests (and document results just like above), please contact us by vrmlengine-main mailing list. | ||||