A minimalist rendering library.

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

Re: A minimalist rendering library.

Postby Julio Jerez » Fri Oct 03, 2025 12:09 pm

wit the Latters commit? Nice!!!! :mrgreen:
Julio Jerez
Moderator
Moderator
 
Posts: 12451
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: A minimalist rendering library.

Postby Julio Jerez » Fri Oct 03, 2025 2:39 pm

Ahh David, I forgot to mention one important side effect of using the preconditioned solver: the tire model becomes much more accurate, and its behavior aligns closely with the description in Giancarlo Genta’s book.

For years, I struggled with vehicle tires never behaving satisfactorily. Instead of using the Pacejka tire model, I went with the analytical brush model, but even then, the results weren’t great.
I had to “fake” the tire lateral and longitudinal stiffness by factor of ten of more to get reasonably traction, and that was kind of a black art magic.

One of the worst issues was that rear-wheel-drive vehicles ended up understeering, which is the exact opposite of what vehicle dynamics theory says (rear-wheel drive should oversteer, while front-wheel drive understeers).
This puzzled me for a long time, until I tried the preconditioned solver. Suddenly, vehicles became extremely oversteering. At first, I thought it was a bug and spent time debugging, but then I discovered the real issue.

In Newton 4, the vehicle is modeled as a multibody system, with tires driven by a powertrain built from joints and rigid bodies.
These power train axles bodies are orders of magnitude lighter than the chassis and tires (differences of 100x or more are common).
Because these joints form loops, they’re handled by the LCP part of the skeleton solver.
The problem was that the mass matrix was so stiff that the solver never converged, and since vehicles change so much frame to frame, it never had time to converge properly across simulation frames.

That’s why artificially increasing the stiffness produced more traction, but it wasn’t realistic tire dynamics, just proportional scaling. Once I realized this, I had to undo all my old hacks.
The vehicles behaved better, but still not great, because the brush model is fundamentally a steady-state model, so whenever vehicle state changes the tire parameters should change as well of its validity breaks down.

The next step was trying the Pacejka model, which doesn’t depend directly on the normal force or tire stiffness. This model works far better for simulation.
And voilà—rear-wheel-drive cars started oversteering as the theory predicts.
Weight transfer and distribution also lined up correctly with vehicle dynamics literature.

I bring this up because I noticed someone mentioned tire slip in your bike project.
Maybe we could collaborate to develop a realistic bike demo, it would be a great application of this improved approach.
Julio Jerez
Moderator
Moderator
 
Posts: 12451
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: A minimalist rendering library.

Postby Dave Gravel » Fri Oct 03, 2025 5:45 pm

Yes, the video was made with last night’s commit.

For years, I struggled with vehicle tires never behaving satisfactorily. Instead of using the Pacejka tire model, I went with the analytical brush model, but even then, the results weren’t great.
I had to “fake” the tire lateral and longitudinal stiffness to get reasonably traction, and that was kind of a black art magic.


Yes, I saw the changes. The version of Newton I was using wasn’t that old, but you still had time to change quite a few things and some logic.

In the video, the motorcycle isn’t using ndModel. I only built the joints and added the controls to handle everything.

I need to update everything for my motorcycle ndModel, but at least I’m happy to see that it works quite well with just a simple joint construction without a model, even if it’s not a very precise or safe method.

I also need to update both of my motocross demos, and for the car, I had a multiplayer monster truck demo but none of my demos using ndModel and vehicle work anymore.

I’ve seen the changes I need to make, but I still have to read through your test demos to better understand certain parts. I’ll probably work on that over the weekend to rebuild a truck and remake the motorcycle model.

But to be honest, if you have some free time and feel like trying out a motorcycle in the Newton SDK, I’d be happy to assist, test, and also work on the implementation on my side.

It’s not something important for me, I’m just doing it for fun. But I’ve wanted to play around with a motorcycle in a physics engine for a long time hehe. And I’d like to have both a realistic approach and maybe a slightly more arcade-style version.
You search a nice physics solution, if you can read this message you're at the good place :wink:
OrionX3D Projects & Demos:
https://orionx3d.sytes.net
https://www.facebook.com/dave.gravel1
https://www.youtube.com/user/EvadLevarg/videos
User avatar
Dave Gravel
 
Posts: 808
Joined: Sat Apr 01, 2006 9:31 pm
Location: Quebec in Canada.

Re: A minimalist rendering library.

Postby Julio Jerez » Sat Oct 04, 2025 12:48 pm

Update
I’ve completed the joint demo with the roller coaster and added 25 instances to the Prop Vehicle demo. Naturally, this setup isn’t meant to be realistic, it’s just a demonstration of how models can be used to create inexpensive NPCs that are controlled by simple AI game logic.
The key difference is that these NPCs are full physics objects: they interact naturally with the simulated world while still responding predictably to game logic.

The Player capsule is essentially just a more advanced version of the Prop model, with the only difference being that it’s treated as a special rigid body, a legacy design from version 3.xx.
In practice, the player should really just be implemented as an ndModel.
Once the demos progress further, I’ll make that change and remove the extra special-case code for the Player capsule. For now, I’m leaving it as is.

Performance-wise
The system didn’t even flinch. The real limitation comes from transform updates. Before switching to the rendering library, I updated transforms asynchronously using a SpinLock per actor. That worked fine for slow-moving objects, but when the camera’s parent body moved quickly, updates would sometimes occur out of order. The result was severe and very noticeable camera jitter.

There are a couple of ways to solve this:
-Lock the parent asynchronous node.
-Lock the entire update after each physics step.

For simplicity, I went with the second method:
Code: Select all
ndScopeSpinLock Lock(m_lock);
ndFloat32 param = m_timeAccumulator / descreteStep;
m_manager->m_renderer->InterpolateTransforms(param);


This approach blocks physics during each render step, which could become costly.
As long as graphics remain orders of magnitude faster than physics, it’s fine.
But if rendering slows down, the physics stalls will increase and may need addressing.

One possible optimization is using double transform buffers, but that adds complexity and makes the system harder to understand for new users. For now, the simpler approach is good enough.
Julio Jerez
Moderator
Moderator
 
Posts: 12451
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: A minimalist rendering library.

Postby Julio Jerez » Sun Oct 05, 2025 4:35 pm

Update:
ok I added the rag goll demo.

nothing really special, only that this model is more physically correct, in the sense that joint limits are enforced more rigidity. This makes the ragdoll pose more humanoid plausible.

This ragdoll model I will use for AI self-balance training later.
I test this some more an add few more ragdolls to the scene
then I am moving the vehicle demos. :D :D
Julio Jerez
Moderator
Moderator
 
Posts: 12451
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: A minimalist rendering library.

Postby Dave Gravel » Mon Oct 06, 2025 4:12 am

Nice! The SDK compiled correctly, and everything seems to be working well.
The ragdoll looks good too.
I also remade the simple AI vehicle in my engine, and it seems to be working well too.

Here a code exemple for the ai vehicle in my engine:
https://orionx3d.sytes.net/dgDemo18.h
https://orionx3d.sytes.net/dgDemo18.cpp

Updated:
Simple ai vehicle video exemple:
https://www.youtube.com/watch?v=hNoGS_H76Oc
Last edited by Dave Gravel on Mon Oct 06, 2025 7:59 am, edited 3 times in total.
You search a nice physics solution, if you can read this message you're at the good place :wink:
OrionX3D Projects & Demos:
https://orionx3d.sytes.net
https://www.facebook.com/dave.gravel1
https://www.youtube.com/user/EvadLevarg/videos
User avatar
Dave Gravel
 
Posts: 808
Joined: Sat Apr 01, 2006 9:31 pm
Location: Quebec in Canada.

Re: A minimalist rendering library.

Postby JoeJ » Mon Oct 06, 2025 4:25 am

Just had a quick look, and i have some proposals to improve the impression:

Set asynchronous update by default, gives a much smoother camera control. (It's janky otherwise)
Centering and hiding mouse cursor when rotating view would help to feel better as well.
(Personally i do not center but teleport the cursor to the right edge if it goes out on the left.
That's some more work but i can drag UI elements to infinity without a need to restart if i hit a border of the window.)

The reflections - well, it's not robust and causes all kinds of flicker and distraction. Maybe that's not the impression you want to make. I would actually remove them or at least turn off by default.

I would also create a larger window because why not. It's 2025. They might not even find your window on their 4K screens. :D

Otherwise nice and looks better.
Oh, and i would prefer an environment map with just a sky. Trees and stuff forces your brain to make hopeless attempts on distance estimates.

I will integrate and report if i see some effect from the solver changes on my ragdoll.
Still working on getting the walking up to speed.
Currently my old friend comes back: Sinking feet due to my custom contact solution.
That's one of the problems which always come back son after i thought i have finally solved them.
But well, i make progress. Just very slowly... :roll:
User avatar
JoeJ
 
Posts: 1494
Joined: Tue Dec 21, 2010 6:18 pm

Re: A minimalist rendering library.

Postby JoeJ » Mon Oct 06, 2025 6:37 am

I think there now is an issue of missing an include.
In the file ndShape.h the define D_MSV_NEWTON_CLASS_ALIGN_32 is unknown.
(I have not looked into it any further yet)

It * we seemingly can no longer compile a single cpp file with VS.
So this happens to me too all the time, and idk how to spot such mistakes. :|
User avatar
JoeJ
 
Posts: 1494
Joined: Tue Dec 21, 2010 6:18 pm

Re: A minimalist rendering library.

Postby Julio Jerez » Mon Oct 06, 2025 8:11 am

JoeJ wrote:Did you get it to compile Joe?
Otherwise nice and looks better.
Oh, and i would prefer an environment map with just a sky. Trees and stuff forces your brain to make hopeless attempts on distance estimate

Yes, I think you are correct, the skyline with specific detail, gives the impression that the far clip plane is too close.

It is very hard to find a nice featureless environmental map.
The free programs that generate procedural like. Terraform has size limits.
If anyone wants to donate one, I will replace it.

In the reflection, this is because it is apply to all objects.
I just change the fbx loader to read the material,
I may still has some error.
It is not that trivial because these days, people are exporting model with special materials use shaders that only work with specific dlls.
The result is that they look different in max and blender.
In fact this is so out of control that now you see different Xbx formal. This is so ridiculous that I see now fbx unreal, fbx unity, fbx max, fbx blender, and they are incompatible.

I have to load some of my demo models that are not supposed to reflect the environment and set the coefficient of reflection to a low value.
And yes, maybe is better to set the default in the library to a low value.

Meantime what I have done is that I have an intermediate format that has a save and load functionality.

Later I will make to save to xml, and see if I can write a blender import/ export in python.
That way after converting from fbx to ndMesh, I can edit the materials by hand a make a proper Blinn model.

I do not want to go crazy with shaders in materials, that's what cause the exponential explosion of shader compilation in the big game engines, where they spend hours, some time days compiling a shader cache that is essentially the same code with different parameters, it is absurd, almost obscene.
The thing is that all those details, as important as they are, takes time away from my main goal.

Any way, I now start the multi body vehicle demos.
Julio Jerez
Moderator
Moderator
 
Posts: 12451
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: A minimalist rendering library.

Postby Julio Jerez » Mon Oct 06, 2025 8:27 am

Simple ai vehicle video exemple:
https://www.youtube.com/watch?v=hNoGS_H76Oc


Ah very nice, you got it very quickly, I was so surprised that such a basic trick was going to work as well as it does.

Before I had a simple convex hull, but it is difficult to get the constant distributed at the corners,
the compound and the Chamfered shapes does that trick.
And you get a easy to control for game AI vehicle.
Julio Jerez
Moderator
Moderator
 
Posts: 12451
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: A minimalist rendering library.

Postby Dave Gravel » Mon Oct 06, 2025 8:45 am

And you get a easy to control for game AI vehicle.


Yes, and it could definitely become useful for making the replicate system for multiplayer as well.
I like it, I still have a few small things to update, but I’ll be able to start testing a bit more soon.

I have two versions of my engine, this one has more options for graphic rendering, and I have CUDA and Torch installed for AI testing.
I’ve also updated the Newton SDK on both engine versions.

If you make an example with AI inside Newton later, I’ll definitely use Newton’s tools.
But since I had already made a small implementation for the pendulum, I decided to update this version of my engine as well to run a few tests.
You search a nice physics solution, if you can read this message you're at the good place :wink:
OrionX3D Projects & Demos:
https://orionx3d.sytes.net
https://www.facebook.com/dave.gravel1
https://www.youtube.com/user/EvadLevarg/videos
User avatar
Dave Gravel
 
Posts: 808
Joined: Sat Apr 01, 2006 9:31 pm
Location: Quebec in Canada.

Re: A minimalist rendering library.

Postby Julio Jerez » Mon Oct 06, 2025 12:45 pm

JoeJ wrote:The reflections - well, it's not robust and causes all kinds of flicker and distraction. Maybe that's not the impression you want to make. I would actually remove them or at least turn off by default.


the reflection model implements the Blinn, simplified rendering equation by the book :D
https://en.wikipedia.org/wiki/Rendering_equation

the Blinn equation is take literately from here: :D
https://en.wikipedia.org/wiki/Blinn%E2% ... tion_model

I am glad you noticed that, because I did find a bug, the instance rendering wasn't coping all of the material parameters passed in the creation descriptor.
this is the function

    static void BuildPlaygroundHangingBridge(ndDemoEntityManager* const scene, const ndSharedPtr<ndMesh>& mesh, const ndSharedPtr<ndBody>& playgroundBody)

I just set the specular and reflection to zoro, and I was still seeing specular.

Code: Select all
   ndRenderPrimitive::ndDescriptor descriptor(render);
   descriptor.m_collision = shape;
   descriptor.m_mapping = ndRenderPrimitive::m_box;
   ndRenderPrimitiveMaterial& material = descriptor.AddMaterial(render->GetTextureCache()->GetTexture(ndGetWorkingFileName("wood_1.png")));
   material.m_specular = ndVector::m_zero;
   material.m_reflection = ndVector::m_zero;


so that was a bug, and I fixed it.

how even I still see the flickering.
Bu that is not reflection. That's a bug in the shadow map algorithm.
what happen is that when the bridge start to fall, the camera sees for planks almost edge on,
and those are self-shadowing.

to solve that OpenGl has this function for off setting the z bias when rendering shadows.
Code: Select all
void ndRenderPassShadowsImplement::RenderScene(const ndRenderSceneCamera* const camera)
{
   glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_frameBufferObject);
   glDisable(GL_SCISSOR_TEST);
   glEnable(GL_DEPTH_TEST);
   glDepthFunc(GL_LEQUAL);
   glClear(GL_DEPTH_BUFFER_BIT);

   //glPolygonOffset(GLfloat(1.0f), GLfloat(1024.0f * 8.0f));
   glPolygonOffset(GLfloat(1.0f), GLfloat(1024.0f * 32.0f));
   glEnable(GL_POLYGON_OFFSET_FILL);



I believe, I understand what the parameters in glPolygonOffset are supposed to do in theory, but either I’m interpreting them incorrectly or the OpenGL implementation isn’t behaving as expected.

Here’s the basic idea:
The second parameter represents a value in depth buffer units. Ideally, this offset should be very small for faces that are perpendicular to the camera’s view direction. However, because the depth comparison in shadow mapping involves an inverse transform, a lot of precision is lost. Applying a small forward offset to the depth value can help fix that issue.

That’s the theory, but in practice, there are complications:

Problem 1: When a triangle isn’t perpendicular to the camera’s view, the required depth bias becomes much larger. In fact, as the viewing angle approaches 90 degrees incidence, the bias should theoretically approach infinity. To compensate, the first parameter of glPolygonOffset is used as a scaling factor based on the dot product between the face normal and the view direction. You typically need to tweak these values. For now, I’ve set the second parameter to a large value and the first one smaller, but I still need to find better numbers.
Maybe making the first param 10, and the secund smaller is better. I will experiment with that.
I do not want to do in the shader, because the GL option does in the pixel assembly in hardware.

Problem 2: This one is what you see in the demo, if the camera is positioned inside an object, that object will appear outside from the light’s point of view. As a result, it still generates a shadow in the shadow map, which causes the visual artifact you’re seeing.

The fix is to implement culling (or occlusion) during rendering. Currently, there’s no such logic in place, so that’s why the issue occurs.
Julio Jerez
Moderator
Moderator
 
Posts: 12451
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: A minimalist rendering library.

Postby JoeJ » Mon Oct 06, 2025 1:35 pm

The compiling issue was on me, i have somehow mixed old and new code.
Now it works, boxes fall down as expected, but the ragdoll neither moves it's joints nor has gravity.
I can pick it up, then it begins to move. So maybe it's something about sleeping. I'll figure it out...

In fact this is so out of control that now you see different Xbx formal. This is so ridiculous that I see now fbx unreal, fbx unity, fbx max, fbx blender, and they are incompatible.

So they have ruined another general 3d format by turning it into a specific mess?
I'm not really surprised to hear that... :roll:
User avatar
JoeJ
 
Posts: 1494
Joined: Tue Dec 21, 2010 6:18 pm

Re: A minimalist rendering library.

Postby Julio Jerez » Mon Oct 06, 2025 2:51 pm

JoeJ wrote:I can pick it up, then it begins to move. So maybe it's something about sleeping. I'll figure it out...


Hehe, Joe.
that’s another side effect of the preconditioned solver: sleep has become really effective.

It can now get a body to settle and go to rest in just one frame.
In some of the AI training demos, after a few epochs, once the agent gets the model into equilibrium, the auto-sleep code kicks in, and the training just stops in a local minimum!
Eventually, I had to reduce the sleep acceleration by a factor of 10, for trainning.
Code: Select all
ndModelArticulation::ndNode* const modelRoot = model->AddRootBody(cartBody);
modelRoot->GetBody()->SetSleepAccel(modelRoot->GetBody()->GetSleepAccel() * ndFloat32(0.1f));


You can try that with the root body of your model.

Disabling auto-sleep entirely isn’t ideal, it’s better to control it rather than turn it off.
A good approach is to manage it at the ndModel level. You can set the sleep state to true whenever needed, and that’s now quite effective since bodies usually go to sleep within the same frame when appropriate.

Because the model updates unconditionally, you can control the sleep state directly from the callback based on input, instead of disabling it altogether.
That's what I do in the vehicle module.
Julio Jerez
Moderator
Moderator
 
Posts: 12451
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: A minimalist rendering library.

Postby Julio Jerez » Mon Oct 06, 2025 5:36 pm

more on the shadow issue. The problem people called shadow acne.

In the pass when doing cascade show was expensive, I use to solve the problem at the pixel shader level
by just adding a constant proportional to the far flipping distance and that worked reasonably well for one shadow map. maybe two.

with arbitrary number of cascades shows, ther is no way to get a single scale to work at all levels.
so using glPolygonOffset is not going to work, simply because the Z depth in the shawdow man cove different range.

The solution is to just be doing the scale for each shadow map and pass it as a uniform other shader.
the pixel shader select he scale alone with the shadow map to sample for.

this is the pixel shader code.

Code: Select all
const char* ndRenderShaderCache::m_directionalDiffuseShadowPixel =
R""""(
   #version 450 core

   layout(binding = 0) uniform sampler2D texture0;
   layout(binding = 1) uniform sampler2D shadowMapTexture;
   layout(binding = 2) uniform samplerCube environmentMap;

   uniform vec3 diffuseColor;
   uniform vec3 specularColor;
   uniform vec3 reflectionColor;

   uniform vec3 directionalLightAmbient;
   uniform vec3 directionalLightIntesity;
   uniform vec3 directionalLightDirection;
   uniform float specularAlpha;

   uniform mat4 directionaLightViewProjectionMatrix[4];

   uniform vec4 shadowSlices;
[color=#FF0040]// fix for shadow acne
   uniform vec4 shadowBias; [/color]

   in vec4 worldPosit;
   in vec3 posit;
   in vec3 normal;
   in vec2 uv;

   out vec4 pixelColor;


   
   // implement a simple Blinn model
   void main()
   {
      vec3 normalDir = normalize (normal);

      // calculate emisive, just a constant;
      vec3 emissive = diffuseColor * directionalLightAmbient;

      // calculate Lambert diffuse component
      float diffuseReflection = max (dot (normalDir, directionalLightDirection), 0.0);
      vec3 diffuse = diffuseColor * directionalLightIntesity * diffuseReflection;

      // calculate Blinn specular component
      vec3 cameraDir = - normalize(posit);
      vec3 blinnDir = normalize(cameraDir + directionalLightDirection);
      float reflectionSign = (diffuseReflection >= 0.01) ? 1.0 : 0.0;
      float specularReflection = reflectionSign * pow(max (dot (normalDir, blinnDir), 0.0), specularAlpha);
      vec3 specular = specularColor * directionalLightIntesity * specularReflection;

      vec3 color = specular + diffuse;

      // calculate the shadow tile
      int index = 4;
      float zbufferDepth = gl_FragCoord.z;
      if (zbufferDepth < shadowSlices.w)
      {
         index = 3;
         if (zbufferDepth < shadowSlices.z)
         {
            index = 2;
            if (zbufferDepth < shadowSlices.y)
            {
               index = 1;
               if (zbufferDepth < shadowSlices.x)
               {
                  index = 0;
               }
            }
         }
      }

      if (index < 4)
      {
         vec4 pointInDepthMapSpace = directionaLightViewProjectionMatrix[index] * worldPosit;

         // this chek will never work for all cacade maps because
         // each mapp represent a diffrent resoltions.
         // To fix this the code needd to pass an array of zbiaz for each shadow map, for now just use a constant value
         pointInDepthMapSpace.z = pointInDepthMapSpace.z - 0.005f;

         //pointInDepthMapSpace.z = clamp (pointInDepthMapSpace.z, 0.0, 1.0);

         float textDepth = texture(shadowMapTexture, vec2(pointInDepthMapSpace)).x;
         if (textDepth < pointInDepthMapSpace.z)
         {
            color = vec3(0.0, 0.0, 0.0);
         }
      }
      // calculate reflection   
      vec3 reflectionDir = normalDir * (2.0 * dot(cameraDir, normalDir)) - cameraDir;
      vec3 reflection = directionalLightAmbient * reflectionColor * vec3(texture(environmentMap, reflectionDir));
      
      // add all contributions
      color = color + emissive;
      color = color * vec3 (texture(texture0, uv));
      color = color + reflection;
      
      pixelColor = vec4(color, 1.0);
   }

)"""";


the read part, is when the zbias is offset, and there is that a z value is on cascade the close cascade panel has a lot more resolution that one in a far panel. therefore, using a constant will never work.

It is not a big problem, but after you mentioned, it is bothering me alot, so I wil try to make it betters.
Julio Jerez
Moderator
Moderator
 
Posts: 12451
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

PreviousNext

Return to General Discussion

Who is online

Users browsing this forum: No registered users and 79 guests