Blender Add-on: PapyNR

It's not so much a bug but a feature not covered.
For now, add and apply the Edge Split modifier (tick Sharp Edges only) to any such objects.
Perspectively and much to my relief, I strongly hope to employ that modifier's effects during export preparation, similar to triangulation (this would avoid (A) changing blender mesh data, of course, and (B) diving deeper into rather obscure .PAS smoothing groups (similar to .OBJ?) for little gain).
 
I'll give edge split a try and see the results. I do notice using this modifier it increases the vert count for every object it applied to though since its essentially splitting the mesh into more pieces where hard edges exist. The 3ds max pas plugin however retains the same number of verts for a cube for example, its 8 while the blender exporter will make it 24 if all edges were marked sharp to be edge split..

I think the major downside is when the tri-stripping is run in make3do it no longer can be as efficient since physical gaps exist where the 3ds max pas is still a single mesh until it reaches the game and the GPU will then split faces where hard edges exist.

Having Edge Split modifier included in the export would be cool, maybe it could be a toggle if we need to manually adjust the angle per mesh as I notice the edge split modifier can sometimes not calculate all the sharp edges I defined until I changed the angle in the modifier settings a bit more.
 
Last edited:
I don't think I've ever run into a normals issue with max 8 exporter. I always applied reset X-Form modifier to any meshes I imported. All the obj files I imported to 3ds I had already applied sharp edges so my smoothing groups were ready to go as well. Example of the process: https://www.adrd-forums.net/index/t...-in-3ds-max-for-pas-export-basic-process.475/

All mods and trackside objects I've made (thousands of 3do's at this point) I've never had to manually split sharp edges for normals to work in NR2003. This also ensure maximum tri-stripping efficiency when make3do compiles a 3do. This is why the 3dsimed3 process of making 3do's is so performance heavy as its always splitting edges and not tri-stripping properly on compile (aka the thing we are trying to avoid with this blender plugin lol).
 
This mesh wasn't imported into Max 8. It was created in Max 8 from scratch, but using an imported ground model as a template using vertex snapping. The model looks correct in Max 8, but not in NR2003 if I have it set to be dynamically lit.
 
@TChapman500 do you know if at runtime in NR2003 if it makes any difference if a mesh was split in the PAS or not to define sharp edges instead of the smoothing group method 3ds uses? Its hard to explain so here is a visual:

For example I have the same visually looking sphere,

sphere #1 I only defined the edges as sharp, you can see the vert count is 34
Screenshot_20260215_210648.png

Same sphere #2 but this time the sharp edges are defined by the edge split modifier, you can see we've increased the vert count to 144 as each face is a separate piece of the mesh:

Screenshot_20260215_210704.png

we can confirm edge spit works if I move a face it is detached:

Screenshot_20260215_210628.png

While the edge split sphere #2 now will properly have sharp edges in NR2003 is this mesh less performance friendly or is NR2003 splitting sphere #1 exactly the same at runtime? The strange thing is in 3ds max pas the vert count for the same sphere is not split but renders proper hard edges in the game, I assume at runtime NR2003 is still 'splitting' the mesh where needed but do you know if it makes a difference for performance when a mesh is split by default instead of the engine doing it for us?

If there is no difference from the user doing the manual splitting great! I just wanna make sure we are not creating 3do's an incorrect way that the 3ds pas version does for performance in NR2003.

Also this is an obvious thing but yes, generally you only have hard edges for your 'hero' meshes (aka LODs 1-3, maybe 4-5 for large 3do's like a grandstand you can still see far away) so everything else in lower LODs will be smoothed to make every mesh truly a single object piece not split even by engine runtime as you can see hard edges on a mesh that far away anyways.
 
When compiling even though sphere #2 pas file is larger in size it seems they still compile to the same size for verts, strips and length (larger strip length is better)

Sphere #1
Screenshot_20260215_212718.png

Sphere #2:
Screenshot_20260215_212642.png

despite the pas files being different size the 3do file size looks to be the same:
Screenshot_20260215_212948.png

Screenshot_20260215_213034.png
 
That is very interesting. May I see those 3DOs? I'd like to take a look at them in the HEX editor. Also, what do they look like in game when dynamically lit?
 
I attached the 3dos and the pas files you can open up the pas files in a text editor to compare the differences

I didn't run dynamic lighting on them, I can run further tests later if you like
 

Attachments

  • sphere_test.zip
    5.8 KB · Views: 1
Here's the same 3do's run with dynamic lighting:
1771220425805.png

same file size again
 

Attachments

  • spheres_dynamic_lit.zip
    2.4 KB · Views: 1
Without dynamic lighting, both models have 34 vertices. With dynamic lighting, they both have 150 vertices. Make3do is optimizing based on whether the model is dynamically lit. When dynamic lighting is important, it splits the geometry according to the normals of the individual faces if the normals are different for each face. When it's not dynamically lit, the normals are essentially irrelevant.
 
Without dynamic lighting, both models have 34 vertices. With dynamic lighting, they both have 150 vertices. Make3do is optimizing based on whether the model is dynamically lit. When dynamic lighting is important, it splits the geometry according to the normals of the individual faces if the normals are different for each face. When it's not dynamically lit, the normals are essentially irrelevant.

So this is good news right? Essentially regardless if a user exports a pas from 3ds max plugin or the blender one make3do is going to compile the geometry the same before the NR2003 runtime will render the smooth or hard edge shading?

Make3do must be smart enough to weld back the split verts from the mesh that had edge split if the vert points are in the same exact coordinates. I have not got a change to see a 3do uisng the edge split method in NR2003 looks like but I assume by the compile data it should look the same.
 
Probably. And it also helps that no texture coords are applied to it. On the GPU side, normals and texture coords (sometimes along with other information) are fed per vertex and cannot be fed any other way. That's why it must split the vertices when faces have different normals when dynamic lighting is to be applied.

And if the model had texture coords, all vertices with identical texture coords would also be fused together when static lighting is applied. If the texture coords were different, then it would force make3do to split the vertices for that as well.

It's probably the case that my grandstands appeared messed up in-game because I used a hex editor to change the material's lighting flag after telling make3do that the model is to be statically lit. Of course, the screenshot I posted was taken in Unity, and the importer I wrote doesn't implement static lighting. So that's why the grandstands also appear messed up in Unity.
 
Yup. That's exactly what happened to my grandstands. But at least now we know that we do not have to take into account stuff like smoothing groups when exporting meshes from any program. But we still need to be aware of texture coordinate mismatches between faces of the same smoothing group as that will still destroy optimization. Does this Blender tool split vertices on export or does it leave them alone?
1771222985658.png
 
Yeah it splits verts where you used the edge split modifier, if you open up the sphere2.pas file I attached you cna see the vert list is longer.
 
I was asking more along the lines of for meshes that the user does not manually split. Though in hindsight, I should have been able to figure that out as well (sorry).
 
No worries, yeah if the user doesn't do any manual splitting (either destructive or with a modifier) the verts list is just like the 3ds max pas export where no edges were split too.
 
Ok @TChapman500 I ran a more thorough test, this time 2 identical meshes with materials attached and compiled with dynamic lighting. Each one I gave a smoothed front and made the top, rear, and bottom hard edges. Both used a single texture to cover the entire mesh, same exact UV unwrapping too.

Red = 3ds max mesh (no edge split, exported through 3ds max)
Green = Blender mesh with hard edges split by the edge split modifier (exporter through the blender papy)

Screenshot_20260216_024030.png

Screenshot_20260216_024042.png

Screenshot_20260216_024052.png

Screenshot_20260216_024142.png

Both look pretty identical in sandbox. Interestingly the 3ds max one when compile does seem to have slightly better performance stats:
  • smaller tri count
  • smaller vert count
  • 5 less tristrips
  • the bswaps being 5% lower is quite a drop
  • 1.0 increase on AvgLen (higher is better)
3ds:
results_3ds_3do.png


Blender:
results_blender_3do.png

I don't know if it really matters with the slight variance in the compile stats but in-game they look pretty much identical I'd say for 98% of the normals rendering.

I've attached all the working files from both if you needed to dissect it further but I feel we won't see any negative performance impact. Maybe I am wrong depending on more complex meshes but then again not every edge will need hard edges.
 

Attachments

  • Cars.zip
    3.9 MB · Views: 2
re smoothing group vs edge split-baked mesh---
---3DOs do not know about explicit smoothing groups or sharp edges/1/
---same applies to make3do, in this regard it would never weld any verts (or the setup of normals, which ofc can model sharp edges, is lost)/2/
---smoothing groups is basically a .PAS-only optimization
---remember you can always inspect geometry of 3DO via import

importantly, in blender, as Sharp Edges are purposefully set by authors, I will (and, quite simply, need to) cover them during export

importwise, again 3DO do not store sharp edges, these cannot be recovered as such, so I'll leave it there
---if I'm not totally way-off wrong this is perfectly regular with 3d formats of such sorts (2003) ...
---authors would need to apply a weld/merge of verts, then proceed within blender to gain the modeling optimization the app allows ...

/1/ basically, the 3DO format (+ very prob. the gfx engine) does not support tangents/bi-normals (one common way to store the info), or any other info like that
/2/ the respective count of verts and normals need to match
 
I've noticed that both PAS files seem to not have the hard edges set up correctly, which would explain the inconsistent smoothing on the corners and edges in-game. Perhaps a smoothing group issue? The Max PAS file has 24 vertices while the Blender PAS file has 56 vertices. Both PAS files have the same number of faces (44). The 3DO files have almost the same vertex count (56 for Max, 58 for Blender). The Max version has 4 tri strips while the Blender version has 5 tri strips.
 
I've noticed that both PAS files seem to not have the hard edges set up correctly, which would explain the inconsistent smoothing on the corners and edges in-game. Perhaps a smoothing group issue? The Max PAS file has 24 vertices while the Blender PAS file has 56 vertices. Both PAS files have the same number of faces (44). The 3DO files have almost the same vertex count (56 for Max, 58 for Blender). The Max version has 4 tri strips while the Blender version has 5 tri strips.
Interesting, yeah sharp edges were applied to the mesh as I always do, it must just be the way make3do translates things after it takes the data from the pas
 
Interesting, yeah sharp edges were applied to the mesh as I always do, it must just be the way make3do translates things after it takes the data from the pas
I'm not sure that they were applied to the mesh before being exported to PAS. At least, not to the whole mesh. I think you should double check the smoothing groups in both models. Both PAS files have normals at wierd angles that suggest that the smoothing groups were not applied correctly before export.
 
I'm not sure that they were applied to the mesh before being exported to PAS. At least, not to the whole mesh. I think you should double check the smoothing groups in both models. Both PAS files have normals at wierd angles that suggest that the smoothing groups were not applied correctly before export.

For blender it does not have smoothing groups with the pas exporter, its only able to retain where sharp edges where made. As far as 3ds max I simply imported the same mesh as an obj which was exported with smoothing groups and vertex groups. I've never used the traditional smoothing group panel in 3ds but always relied on the hard edges I defined on import of an object where I do have the option to retain my normals.

As far as in game the hard edges I defined always looked as I expected.
 
DESERGARD this post (unless you want to see the trial and error lol), next page has a much easier method for the time being

Continuing the process of sailing into uncharted waters using the blender method to make a mod I've successfully completed the undamaged state of a mod:
  • 4 makes
  • wheels with lods all appearing and rotating correct orientation
  • all lods for the 4 makes
  • roof/hood flaps etc animate in game with region morphs
  • mod looks as expected with textures and performance in a full field is great
Moving to the damaged state however has been very rough, since we don't have animation frames to rely on where each mesh can act as the damaged and undamaged state at the same time it required extra technical challenge of duplicating the mesh to have 1 in damaged state and 1 in its undamaged state for every piece. Tedious but doable and even some older mods used this method.

However, the real issue came when compiling:

1771411275206.png


Despite 2 meshes being the exact same in vert, face, and tri count in this example a chassis mesh, because we manipulated the verts the export of the meshes will create unnecessary changes to the normals thus splitting extra verts. Doesn't matter when we created the 'damaged' look on the mesh by manually moving verts with out mouse or used a lattice deform modifier the results will be the same error I've found for 15-25% of your meshes (more complex and warped the mesh more prone this error occurs)

The reason why I didn't run into this error with the roof flaps which uses the same REGION_MORPH state switch is because with roof flaps you don't need to move vertices, you simply just use the orientation to rotate the entire mesh.

I tried using the data transfer modifier to match vertex order and the sorting order for the mesh in X orientation but neither fixed the issue. What I found to fix this was exporting the undamaged state of my mesh as a OBJ then re-importing and clearing custom normals data and applying clear all transforms. You have to reapply your papy material and then make a COPY of this mesh for the damage state you wanted.

At this point compiling works


but its doesn't stop there...


in game while damage works you then notice as damage is taken the morph that occurs is all jarbled up, as in the verts are not morphing to the correct location of the damaged mesh. This is due to vertex order being incorrect. Despite us making a COPY of the imported sanitized OBJ file and vert count matching it still becomes broken when we manipulate the verts of the COPIED mesh as its treated as a separate entity and the vertex order gets re-sorted.

So we have two things we have to fix for each mesh simultaneously to make it work correct in NR2003:

- matching vertex count
- vertex order 100% matching


So after a couple hours I finally found the 'current' wroking process that I have replicated now several times as I go through and 'sanitize' each damage part:

- Starting with MESH A (your undamaged mesh piece) export it as OBJ with object groups, vertex groups on and materials off:

Screenshot_20260218_123613.png

- re-import your MESH A OBJ and on import prompt ensure vertex/object groups is selected

- clear transforms (so coordinates reset to 0,0,0), clear custom normals, and apply your papy material back

- make copy of MESH A to make the damaged copy (MESH B) then apply the lattice deform (or deform your MESH B however you want to make the damaged 'look' )

- select MESH B THEN MESH A and choose 'join shapes' option (can find this by pressing F3 and searching for it too)

- delete MESH B from your scene (or you can keep it but its useless now)

-select Mesh A and move the shape slider to 1.0 to show the damaged state, essentially the join shapes has made our MESH A 'inherit' MESH B's shape with a slider we can toggle on and off (you might be thinking, isn't this what lattice deform does? yes, but remember applying even the same lattice deform on a different mesh its not keeping the same data as this joined shape has)

-COPY the MESH A whne your slider is in the damaged state, its now an exact replicate of MESH A but in a damaged state, this becomes your new MESH B

- ensure you purge your blender scene of unused data: File > cleanup > purge unused data

- you can now rename MESH A and MESH B to their respective names you want to use in your code for papy export


-final result-

compiling has no errors AND in game the corrupting warped effect no longer appears, as your parts become damaged they warp as expected instead of appearing 'exploded'


I am still working on LOD state 1 for the first make. I have yet to see if I have to do this process for the other LODs as well since I use a LOD generator for my other LOD states, either way this does kinda suck but I'd rather do this than be stuck with 3ds max 8. Once I get into the rhythm of exporting and re-importing OBJs in the process it won't be too bad. The real pain was the constant errors and figuring out how to solve it.

This is more a blender thing I think than the addon itself, I think if we were able to animate between frame 0 and 1 for damage since it would be the same mesh we couldn't run into this but since we have to deal with two separate meshes for each damage part thats where it becomes tricky.

I plan in the future to make an in-depth tutorial on using the papy blender addon and things to be aware of for mod creation but since we are still in alpha stage I don't want to write a whole thing up and things change 6 months later.
 
Last edited:
Back
Top