March 29, 2024, 03:14
bigger smaller reset     1020px Wide width Full width Reset   * *

Gildor's Forums

  Homepage Facebook Read news on Twitter Youtube channel Github page
Welcome, Guest. Please login or register.
Did you miss your activation email?

« previous next »
Print
Author Topic: Normal Map Issue Importing TERA .psk files into 3ds max  (Read 27345 times)
Ayrshi
Newbie
*
Posts: 8


View Profile
« on: August 03, 2013, 08:12 »

Gildor I need your help ._.

First of all thanks so much for the importer script for .psk files! It works awesome.

One thing I noticed though, the imported models seem to have lighting seams on where there's more than 1 UV coordinate for a vertex - I then analyzed the script and it appears you made it this way, to create as many Points as Wedges even if duplicates, so 3ds max can't smoothly light those surfaces.

I made a few modifications to your script here is what I changed if you're interested:

*CHANGED:*
   -- generate mesh
   MaxFaces = #()
   MaxVerts = #()
   MaxFaces[numTris]   = [ 0, 0, 0 ]         -- preallocate
   MaxVerts[numWedges] = [ 0, 0, 0 ]         -- ...
   for i = 1 to numWedges do
   (
      MaxVerts[i] = Verts[Wedges[i].PointIndex + 1] * g_meshScale
   )
   for i = 1 to numTris do
   (
      tri = Tris[i]
      w0 = tri.Wedge0
      w1 = tri.Wedge1
      w2 = tri.Wedge2
      MaxFaces[i] = [ w1+1, w0+1, w2+1 ]      -- note: reversing vertex order
   )



*TO:*
   MaxFaces = #()
   MaxVerts = #()
   MaxFaces[numTris]   = [ 0, 0, 0 ]         -- preallocate
   MaxVerts[numVerts]  = [ 0, 0, 0 ]         -- ...
   for i = 1 to numVerts do
   (
      MaxVerts[i] = Verts[i] * g_meshScale
   )
   for i = 1 to numTris do
   (
      tri = Tris[i]
      w0 = Wedges[tri.Wedge0+1].PointIndex
      w1 = Wedges[tri.Wedge1+1].PointIndex
      w2 = Wedges[tri.Wedge2+1].PointIndex
      MaxFaces[i] = [ w1+1, w0+1, w2+1 ]      -- note: reversing vertex order
   )



*AND CHANGED:*
      for wedge = 1 to numWedges do
      (
         vert    = Wedges[wedge].PointIndex+1
         start   = vertInfStart[vert]
         numInfs = vertInfNum[vert]

         -- This code uses ReplaceVertexWeights with arrays, a few times slower;
         -- it is still here in a case of bugs with SetVertexWeights path
         infBones   = #()
         infWeights = #()
         for i = 1 to numInfs do
         (
            v = Infs[start + i - 1]
            append infBones   boneIDMap[v.BoneIndex + 1]
            append infWeights v.Weight
         )
         skinOps.ReplaceVertexWeights skinMod wedge infBones infWeights
         -- NOTE: ReplaceVertexWeights will reset infBones and infWeights arrays, so we
         -- cannot reuse them
      )



*TO:*
      for vert = 1 to numVerts do
      (
         start   = vertInfStart[vert]
         numInfs = vertInfNum[vert]

         -- This code uses ReplaceVertexWeights with arrays, a few times slower;
         -- it is still here in a case of bugs with SetVertexWeights path
         infBones   = #()
         infWeights = #()
         for i = 1 to numInfs do
         (
            v = Infs[start + i - 1]
            append infBones   boneIDMap[v.BoneIndex + 1]
            append infWeights v.Weight
         )
         skinOps.ReplaceVertexWeights skinMod vert infBones infWeights
      )




I have also added smooth groups in the following code like this:

   for i = 1 to numTris do
   (
      -- setup face vertices and material
      tri = Tris[i]
      meshop.setMapFace newMesh 1 i [ tri.Wedge1+1, tri.Wedge0+1, tri.Wedge2+1 ]
      setFaceMatId newMesh i (tri.MatIndex+1)

      -- set smoothing groups
      setFaceSmoothGroup newMesh i tri.SmoothingGroups
   )



However it appears TERA models (at least those I tried) have no smoothing groups? So this way the object becomes faceted. I can use Auto Smooth option of course but that smooths even the object's intentionally rough edges.

How does umodel know what to smooth? Because in umodel the characters aren't faceted.


Anyway, here comes my REAL issue now. I'm having a problem with the Normal map on my TERA models rendered in 3ds max, at symmetry points. I want to make a video with them so how 3ds max renders them is crucial.

Here's 2 images to see what I'm talking about:

3ds max




umodel




As you can see there's a seam on her right shoulder and on her head the lighting is inverted in 3ds max.

I noticed that her right half has the UV .x coordinate increased by 1 unit, between 1.0 and 2.0 instead of 0.0 and 1.0. So I thought, umodel uses a shader to flip normals on such UV coordinates. I manually inverted the Green Channel of the Normal Map for her right half, and it looks flawless!

But!

Another character I import, he does NOT have the .x coordinate of his right half increased by 1 unit, and same graphic issue is present in 3ds max. But in umodel it looks flawless! Even worse, he has more symmetry meshes along his body - he has a rotating sphere on each of his arms - and they are symmetric, so he has even more UV flips, and I couldn't even fix those spheres by inverting or swapping Red/Green channels of the normal map, their normals are messed up at the symmetry intersection.

I searched on Google about this issue and it seems it's not the normal map at fault, it's the tangent space. Basically the normal / tangent / bitangent system. I read that the bitangent has to be flipped at flipped UV coordinates, using W component as the sign or something? I'm confused and not that good at math Sad

The characters display PERFECT in umodel, and since you made umodel (or am I wrong?), I need to know how do you generate the normals / tangent / bitangent from a .psk file because according to your script and data structure - psk doesn't hold Normal information, only smoothing groups.

3ds max won't allow me to modify tangents and bitangents (I suppose it auto generates them from normal and UV coordinates), but if the Vertex Normal is the problem, I can use the maxscript function: setNormal <mesh> <vert_index_integer> <point3>

But I need to know how you calculate normals in umodel to achieve the perfect lighting for those TERA characters, because 3ds max calculation of normals obviously is wrong in this case...

PLEASE help I'm desperate, 2 days of non stop browsing about this issue and it's driving me crazy. How does umodel display them perfectly?! What is the secret? What's the code it uses to generate normals and tangents/bitangents for normal maps?
Logged
Ayrshi
Newbie
*
Posts: 8


View Profile
« Reply #1 on: August 03, 2013, 08:18 »

Sorry for double post but forgot to add:

I'm almost sure the problem is the tangent space, because if I set the Normal Bump sub material to Screen or Local XYZ, it does not display any artifacts at the symmetry intersection - it looks perfect, as it should.

So my guess is that 3ds max's Normal / Tangent / Bitangent are messed up for imported .psk files, at least for TERA.

How can I get them to be like in umodel and look flawless?
Logged
Gildor
Administrator
Hero Member
*****
Posts: 7978



View Profile WWW
« Reply #2 on: August 03, 2013, 13:33 »

Gildor I need your help ._.

First of all thanks so much for the importer script for .psk files! It works awesome.
Thanks Smiley You're welcome!
Quote
One thing I noticed though, the imported models seem to have lighting seams on where there's more than 1 UV coordinate for a vertex - I then analyzed the script and it appears you made it this way, to create as many Points as Wedges even if duplicates, so 3ds max can't smoothly light those surfaces.
Yes, exactly. I didn't find different way to load mesh and share vertices. I'm not 3ds Max programmer Wink
Quote
I made a few modifications to your script here is what I changed if you're interested:
...
I understand your code, but unfortunately I can't test it by myself because I don't have Max installation for quite a long period of time. If this code will be confirmed to work well by other users I can integrate your changes to importer.
Quote
I have also added smooth groups in the following code like this:
...
However it appears TERA models (at least those I tried) have no smoothing groups? So this way the object becomes faceted. I can use Auto Smooth option of course but that smooths even the object's intentionally rough edges.
Smoothing groups are not exported because they are missing in Unreal model data - this "feature" (mistake of the nature Smiley) is unique for 3ds Max and of course not used in game engines.
Quote
How does umodel know what to smooth? Because in umodel the characters aren't faceted.
It's simple. I generate normals for UE1-UE2 meshes, and use prepared normals for UE3 meshes.
Quote
...
The characters display PERFECT in umodel, and since you made umodel (or am I wrong?), I need to know how do you generate the normals / tangent / bitangent from a .psk file because according to your script and data structure - psk doesn't hold Normal information, only smoothing groups.
Yes' I'm umodel's author Smiley
As I mentioned above, I have 2 approaches for normals - generate them from geometry and UV space, or use prebuilt data.
Quote
3ds max won't allow me to modify tangents and bitangents (I suppose it auto generates them from normal and UV coordinates), but if the Vertex Normal is the problem, I can use the maxscript function: setNormal <mesh> <vert_index_integer> <point3>

But I need to know how you calculate normals in umodel to achieve the perfect lighting for those TERA characters, because 3ds max calculation of normals obviously is wrong in this case...
Generating normals in Max Script would be very slow task. As you know, PSK format doesn't have a place for normals. It has place for SmoothingGroups, unfortunately it looks like impossible task to regenerate smoothing groups from mesh's normals - I can easily find cases when mesh has normals, but it's not possible to reproduce them using smoothing groups. FBX format has normals stored, and they can be exported/imported, but that's C++ plugin, not script.
Logged
warrantyvoider
Full Member
***
Posts: 109


View Profile
« Reply #3 on: August 03, 2013, 19:36 »

I linked this post to my forum, maybe some max ppl can test and use this. Thanks alot!

greetz WV

http://me3explorer.freeforums.org/better-actorx-importer-script-t588.html

PS: for tangent space calculation you could try this
« Last Edit: August 03, 2013, 19:38 by warrantyvoider » Logged
Ayrshi
Newbie
*
Posts: 8


View Profile
« Reply #4 on: August 03, 2013, 20:33 »

Thanks for the fast reply Smiley

But I am confused.

You said "smoothing groups are not exported because they are missing in Unreal model data", so what's that 32 bit value SmoothingGroups in the .psk format?

I thought .psk has smoothing groups. But if it has normals in it instead, I think it's better. Because as you said smoothing groups is not a great way to produce normals, you can't generate smoothing groups from normals because explicit normals have more control.

But smoothing groups aren't needed even for 3ds max I think, 3ds max has Edit Normals modifier which lets you control them so I think I can with MAX script too.


You also said:

"As I mentioned above, I have 2 approaches for normals - generate them from geometry and UV space, or use prebuilt data."

1) How do you generate them? I don't mean a literal max-script, just the general idea in some pseudo code, maybe I can translate it to MAX script.

2) How do you use prebuilt data? Does TERA who uses U3 engine have prebuilt normals in the .psk file? If so, that might explain, but your ActorX importer script doesn't read or do anything about the normals, so I am clueless where they even are in the .psk format Sad



Lastly, even if I calculate the normal properly, or use prebuilt one, I can't seem to find a way to manipulate the tangents and bitangents / binormals of a mesh in 3ds max. It seems it only auto-calculates them with the following code (searched on the web for it)

void ComputeTangentAndBinormal(const Point3 tv[3], const Point3 v[3], Point3 bvec[2])
{
  float uva,uvb,uvc,uvd,uvk;
  Point3 v1,v2;
  int ix = 0; // 0 corresponds to the U axis
  int iy = 1; // 1 corresponds to the V axis
  uva = tv[1][ix]-tv[0][ix];
  uvb = tv[2][ix]-tv[0][ix];
  uvc = tv[1][iy]-tv[0][iy];
  uvd = tv[2][iy]-tv[0][iy];
  uvk = uvb*uvc - uva*uvd;
  v1 = v[1]-v[0];
  v2 = v[2]-v[0];
  if (uvk!=0) {
    bvec[0] = FNormalize((uvc*v2-uvd*v1)/uvk);
  }
  else {
    if (uva!=0)
      bvec[0] = FNormalize(v1/uva);
    else if (uvb!=0)
      bvec[0] = FNormalize(v2/uvb);
    else
      bvec[0] = Point3(0.0f,0.0f,0.0f);
  }
  Point3 normal = Normalize( (v[1] - v[0]) ^ (v[2] - v[1]) );
  bvec[1] = CrossProd( normal, bvec[0] );



Then this code to flip the binormal when the triangle in UV space is back-facing:

Point3 mapNormal = FNormalize((mapTri[1] - mapTri[0]) ^ (mapTri[2] - mapTri[1]));
if( mapNormal.z<0 ) // is the UV face flipped?
    basisVec[1] = -basisVec[1]; // yes, so flip the binormal




I also found this MAXscript that computes tangents and binormals:

fn computeTangentSpace obj =
(

local theMesh = snapshotAsMesh obj

local tSpace = #()

for nFace = 1 to theMesh.numFaces do
(
local face = getFace theMesh nFace
local tface = getTVFace theMesh nFace

local v1 = getVert theMesh face[1]
local v2 = getVert theMesh face[2]
local v3 = getVert theMesh face[3]

local w1 = getTVert theMesh tface[1]
local w2 = getTVert theMesh tface[2]
local w3 = getTVert theMesh tface[3]

local x1 = v2.x - v1.x
local x2 = v3.x - v1.x
local y1 = v2.y - v1.y
local y2 = v3.y - v1.y
local z1 = v2.z - v1.z
local z2 = v3.z - v1.z

local s1 = w2.x - w1.x
local s2 = w3.x - w1.x
local t1 = w2.y - w1.y
local t2 = w3.y - w1.y

local r = 1.0 / (s1 * t2 - s2 * t1)

local tan1 = [(t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r]
local tan2 = [(s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r]

local normal = normalize (getFaceNormal theMesh nFace)

local tangent = normalize (tan1 - normal * (dot normal tan1))

local handedness = if (dot (cross normal tan1) tan2) < 0.0 then -1.0 else 1.0

local binormal = (normalize (cross normal tangent)) * handedness

local fCenter = meshOp.getFaceCenter theMesh nFace

append tSpace (Matrix3 tangent binormal normal fCenter)
)

delete theMesh

return tSpace
)



The problem is I can't find a way to manipulate the tangents / binormals in 3ds max at all, I can only let it auto-generate them? This wouldn't be an issue if it did it properly, but for some reason it doesn't, at least for TERA models. And I have a feeling the issue of my inverted lighting on one half is because of the binormal not flipping, but I am not sure.

1) I am using an older version of MAX so any idea if a newer one lets you manipulate tangents and binormals, or it doesn't?

2) If I can't, then how can I make the auto-generation perfect like umodel does - are my normals wrong? (the ones 3ds max auto generates atm) If so, what's the trick umodel generates them perfectly for TERA models? (I may translate it into max script)

3) If it's not the normals being at issue, then what else is wrong with the generation of tangents and binormals, something which umodel doesn't have problems of, but 3ds max does.

I saw this piece of code and I wonder about one part of it:

   for i = 1 to numWedges do
   (
      -- set texture coordinates
      w = Wedges[i]
      meshop.setMapVert newMesh 1 i [ w.U, 1-w.V, 1-w.V ]   -- V coordinate is flipped
   )

What's the 3rd value of the array [ ] for? And why is it 1-w.V same as 2nd ? Could it be that the problem for when MAX auto generates tangents / binormals from UV coords, or am I completely off the point?


Thanks in advance Smiley
« Last Edit: August 03, 2013, 20:38 by Ayrshi » Logged
Ayrshi
Newbie
*
Posts: 8


View Profile
« Reply #5 on: August 03, 2013, 22:53 »

Ok update, I translated the function above from the 3ds MAX SDK documentation in MAXscript, to compute tangents:


fn computeTangentSpace obj =
(
  local theMesh = snapshotAsMesh obj

  local tSpace = #()

  for nFace = 1 to theMesh.numFaces do
  (
    local face = getFace theMesh nFace
    local tface = getTVFace theMesh nFace

    local v = #(getVert theMesh face[1], getVert theMesh face[2], getVert theMesh face[3])
    local tv = #(getTVert theMesh tface[1], getTVert theMesh tface[2], getTVert theMesh tface[3])

    local tangent  = [0, 0, 0] as point3
    local binormal = [0, 0, 0] as point3
    local normal   = [0, 0, 0] as point3

    local uva = tv[2].x - tv[1].x
    local uvb = tv[3].x - tv[1].x
    local uvc = tv[2].y - tv[1].y
    local uvd = tv[3].y - tv[1].y
    local uvk = uvb*uvc - uva*uvd

    local v1 = v[2] - v[1]
    local v2 = v[3] - v[1]

    if uvk != 0 then
    (
      tangent = normalize ((uvc*v2-uvd*v1)/uvk)
    )
    else
    (
           if uva != 0 then tangent = normalize (v1/uva)
      else if uvb != 0 then tangent = normalize (v2/uvb)
    )

    normal = normalize (cross v1 v2)
    binormal = cross normal tangent

    local mapNormal = normalize (cross (tv[2] - tv[1]) (tv[3] - tv[2]))
    if mapNormal.z < 0 then binormal = -binormal

    local fCenter = meshOp.getFaceCenter theMesh nFace

    append tSpace (Matrix3 tangent binormal normal fCenter)
  )

  delete theMesh

  return tSpace
)



Then I used the following function to display the normal / tangent / binormal:

fn showTangentSpace tSpace axisLength =
(
local worldMat = inverse (viewport.getTM())

gw.setTransform (matrix3 1)

for nFace = 1 to tSpace.count do
(
local tbn = tSpace[nFace]

if (dot tbn.row3 worldMat.row3) >= 0.0 do
(
gw.setColor #line red
gw.polyLine #( tbn.row4, (tbn.row4 + tbn.row1 * axisLength) ) false
gw.setColor #line green
gw.polyLine #( tbn.row4, (tbn.row4 + tbn.row2 * axisLength) ) false
gw.setColor #line blue
gw.polyLine #( tbn.row4, (tbn.row4 + tbn.row3 * axisLength) ) false
)
)

gw.enlargeUpdateRect #whole
gw.updateScreen()
)



And I took a screenshot:




Then used umodel's display of normals and also took a screenshot:




blue in max = green in umodel = Normal

red in max = blue in umodel = tangent (or am I wrong?)

green in max = pink in umodel = binormal


As you can see, the binormal in 3ds max is flipped compared to umodel - why? And how can I fix? Is that why lighting is inverted on the model's right half? Or something else?
Logged
Ayrshi
Newbie
*
Posts: 8


View Profile
« Reply #6 on: August 03, 2013, 23:23 »

Sorry for rushing last post, I modified my maxscript a bit so it calculates and displays tangents for vertex instead of face, like umodel does, for a closer comparison. Result is still the same though, binormals are flipped and point in another direction.




new script:

fn computeTangentSpace obj =
(
  local theMesh = snapshotAsMesh obj

  local tSpace = #(); tSpace.count = theMesh.numtverts
  for i = 1 to theMesh.numtverts do tSpace[i] = Matrix3 0

  for nFace = 1 to theMesh.numFaces do
  (
    local face = getFace theMesh nFace
    local tface = getTVFace theMesh nFace

    local v = #(getVert theMesh face[1], getVert theMesh face[2], getVert theMesh face[3])
    local tv = #(getTVert theMesh tface[1], getTVert theMesh tface[2], getTVert theMesh tface[3])

    local tangent  = [0, 0, 0] as point3
    local binormal = [0, 0, 0] as point3
    local normal   = [0, 0, 0] as point3

    local uva = tv[2].x - tv[1].x
    local uvb = tv[3].x - tv[1].x
    local uvc = tv[2].y - tv[1].y
    local uvd = tv[3].y - tv[1].y
    local uvk = uvb*uvc - uva*uvd

    local v1 = v[2] - v[1]
    local v2 = v[3] - v[1]

    if uvk != 0 then
    (
      tangent = normalize ((uvc*v2-uvd*v1)/uvk)
    )
    else
    (
           if uva != 0 then tangent = normalize (v1/uva)
      else if uvb != 0 then tangent = normalize (v2/uvb)
    )

    normal = normalize (cross v1 v2)
    binormal = cross normal tangent

    local mapNormal = normalize (cross (tv[2] - tv[1]) (tv[3] - tv[2]))
    if mapNormal.z < 0 then binormal = -binormal

    -- calculate vertex tangents from face by smoothing
    for i = 1 to 3 do
    (
      local j = tface[i]
      tSpace[j].row1+= tangent
      tSpace[j].row2+= binormal
      tSpace[j].row3 = getNormal theMesh face[i]
      tSpace[j].row4 = v[i]
    )
  )

  -- normalize tangents
  for i = 1 to tSpace.count do
  (
    tSpace[i].row1 = normalize tSpace[i].row1
    tSpace[i].row2 = normalize tSpace[i].row2
  )

  delete theMesh

  return tSpace
)
Logged
Ayrshi
Newbie
*
Posts: 8


View Profile
« Reply #7 on: August 04, 2013, 07:21 »

Ok another update... I realized why binormals were wrong, because in the import script you did 1-uv.y for the y coord of an UV vertex, because max uses different UV coordinate system (1 is up instead of down). That's ok for diffuse map, but it flips out the binormal. This is super easy to fix though. I just made the script read "as is", meaning uv.y directly, and just flip the textures vertically in photoshop (or rotate 180 degrees on U axis in the material editor)

Now the normals/tangents/binormals appear exactly as umodel displays them!


But I am even more depressed...

because the same problem is still there Sad inverted lighting on the mirrored half.

WHY is this happening in max but not in umodel? What's going on? I'm totally out of ideas. Is it because I use an older max and it uses a different (worse) tangent space calculation than the one I found in the SDK on web? Could someone who has a newer max confirm for me? If you're willing, import a symmetric TERA character model (or if you want my exact example case, extract MessengerOfSandramanaia.gpk found in CookedPC\Art_Data\Packages\CH\Monster folder), and then look at the mirror edge in the center, disable view of diffuse and other maps except Bump to make it more clear, and Render. Is the lighting inverted like in my first screenshot, or it looks flawless like in umodel?

If this issue is still in newer max too... I'm just completely clueless at what this might be. If it helps to give you a spark of an idea, like I said if I invert her right half's green channel of the normal map, it appears flawless (select her right half and apply a different material with the option that flips Green). However this doesn't work for all models especially those that have more symmetries, even horizontal, and not just mirrored at the middle. So I'm sure this is just a quick fix that works only in some cases and not how it's actually supposed to be...
« Last Edit: August 04, 2013, 07:39 by Ayrshi » Logged
Gildor
Administrator
Hero Member
*****
Posts: 7978



View Profile WWW
« Reply #8 on: August 04, 2013, 14:39 »

Tangent space building code should take into account possible mirroring. Tangent should look at direction of growing U, and binormal - in direction of growing V. These 3 tangent vectors are not always right-handed or left-handed coordinate systems.
« Last Edit: August 04, 2013, 14:45 by Gildor » Logged
Ayrshi
Newbie
*
Posts: 8


View Profile
« Reply #9 on: August 04, 2013, 21:20 »

I understand but how do you detect the mirrored half?

I made it manually (because in this particular model, the right half U's coordinate is set to 1+) to swap the U coordinates of the right half (to 2 - U), and then flip the texture for the right half so it matches the new U coords. Result was the texture was applied as before for both sides, but tangents were flipped on the right side and... it looked perfect.

However that's as much of a fix as swapping green channel and it's not a great way for other models. Some models don't even have the U coordinate modified for the right side to 1-2 range. How does umodel detect the mirrored half to display them perfect?

Also, I'm still confused, because the tangents with that script are displayed same as in umodel - yet give incorrect results, and I have to flip tangents for mirrored half for accurate results. I'm clueless why, unless my version of 3ds max actually computes tangents differently than my script (which was made with the formula I found about how max computes tangents - but maybe my max is too old?)

Can you show me the formula umodel uses for tangents for TERA models (uses unreal engine 3) or is it top secret? Tongue


EDIT: one more thing; since .psk has smoothing groups only and not normals, can you make umodel export some improved custom .psk that has normals instead? Since it appears you know the skeletal mesh format for it.

Even if it's a custom format, I could modify the max script to make it import the normals from the new custom format and apply an Edit Normals modifier or something, not sure yet.

This isn't really solving my other issue with inverted lighting so it's not that important, but it would solve the smoothing groups one because now there's no smoothing groups import so you have no idea how the original model is supposed to be, you have to manually smooth everything (or use Auto Smooth based on angle). Was just wondering if you'd want to do this feature Tongue
« Last Edit: August 04, 2013, 23:51 by Ayrshi » Logged
Ayrshi
Newbie
*
Posts: 8


View Profile
« Reply #10 on: August 05, 2013, 03:49 »

Ah one thing about the modifications on first post, they work well for max because max can have more than one tangent / binormal / normal per vertex - but if you want to export meshes to some game engine that only supports 1 tangent per vertex, then that method of having 1 vertex at UV seams fails, since you need 2 tangents and binormals even if only 1 normal.

So another solution is to use the default way of having more vertices at same spot, but modify normals manually at seams with Edit Normals modifier. Note that this option only works if you export the mesh to some format that saves 3ds max normals, otherwise there is no point to it, and you'll have seams from default normals.

Code modifications from first post = good if you use in 3ds max or export to a format that doesn't have normals data. In this case when you import to an engine that doesn't support more than 1 tangent per vertex then you'll have a few artifacts on the lighting from normal map because of 1 tangent / binormal at UV seams, but otherwise you'd have lighting seams from the Normals themselves, anyway, so in either cases it looks bad. This one also uses less memory because of fewer vertices.

These new modifications = good if you export to a format that saves normals data. It will allow you to have 100% smooth seams since you'll have smoothed normals and more than one tangent/binormal at one spot when needed.


To get the new modifications, we go back to the original unmodified script version, and modify this section like this:

   -- generate mesh
   MaxFaces = #()
   MaxVerts = #()
   MaxFaces[numTris]   = [ 0, 0, 0 ]         -- preallocate
   MaxVerts[numWedges] = [ 0, 0, 0 ]         -- ...
   VertList = #(); VertList.count = numVerts; for i=1 to numVerts do VertList[i] = #()
   for i = 1 to numWedges do
   (
      local vert_id = Wedges[i].PointIndex + 1
      MaxVerts[i] = Verts[vert_id] * g_meshScale
      append VertList[vert_id] i
   )


And add this section before the skin modifier:


   update newMesh

   -- smooth vertex normals accross UV seams
   max modify mode
   select newMesh

   normalMod = editNormals ()
   addModifier newMesh normalMod
   normalMod.selectBy = 1

   for i = 1 to VertList.count do
   (
      if VertList[i].count > 1 then
      (
         local seamWedges = VertList[i] as bitArray
         local n = #{}
         normalMod.ConvertVertexSelection &seamWedges &n
         normalMod.Average selection:n
      )
   )
   VertList.count = 0
        collapsestack newMesh

   -- generate skin modifier
   skinMod = skin ()
   boneIDMap = #()


Note that I also pushed the update newMesh line above there, and removed it from original position under skin modifier. This is so it doesn't recompute the normals for the mesh.

I also attached the modified script if you're interested.

[вложение удалено Администратором]
« Last Edit: August 05, 2013, 03:51 by Ayrshi » Logged
warrantyvoider
Full Member
***
Posts: 109


View Profile
« Reply #11 on: February 27, 2014, 21:24 »

you can find mirrowed UVs by checking if the triangle defined by UVs points in same direction as the face (like UVs are counterclockwise to a clockwise face), then flip it

greetz WV
Logged
Gildor
Administrator
Hero Member
*****
Posts: 7978



View Profile WWW
« Reply #12 on: February 01, 2015, 22:49 »

I know that this is a bit late (1.5 years passed since this discussion), but I've integrated patch from recent post of this thread into ActorX Importer 1.30.

I think I missed this conversation because at August 2013 I left Ubisoft UK, got many troubles because of that - so my head was busy with different things. You may notice how little changes I did to UModel in 2013
https://github.com/gildor2/UModel/graphs/contributors?from=2013-01-01&to=2014-01-01&type=c
« Last Edit: February 01, 2015, 22:51 by Gildor » Logged
Print 
« previous next »
Jump to:  

Powered by SMF | SMF © 2006-2009, Simple Machines LLC
Leviathan design by Bloc | XHTML | CSS