Important information: this site is currently scheduled to go offline indefinitely by December 1st 2023.
If you wish to donate to attempt the preservation of tools and software somewhere else before it goes down, check the GoFundMe
If you wish to donate to attempt the preservation of tools and software somewhere else before it goes down, check the GoFundMe
How do normals work?
-
Repeperilka
- n00b
- Posts: 14
- Joined: Fri Jun 08, 2018 10:36 pm
- Has thanked: 6 times
- Been thanked: 1 time
How do normals work?
I mean, I know they usualy weight 3 floats but I have no idea what's their purpose. Actualy I kind of know what they do, but not how they do it, and that's what I need to know. Like whats the purpose of each float that compose the normal.
I'm getting an error in noesis that looks like this:
WARNING: Size of normal list does not match positions, ignoring normals.
I'm getting an error in noesis that looks like this:
WARNING: Size of normal list does not match positions, ignoring normals.
- Bigchillghost
- double-veteran

- Posts: 1031
- Joined: Tue Jul 05, 2016 9:37 am
- Has thanked: 32 times
- Been thanked: 1216 times
Re: How do normals work?
Normals are unit vectors of which the square sum of the 3 coords equal to 1.0. And if you treat their coords as the ones of vertexes, you'll see them all distributing on the Unit Ball. Usually the normal vector of a vertex equals to the average of all the normal vectors of the faces this vert belongs to, but that's not always applicable for game models.Repeperilka wrote:I mean, I know they usualy weight 3 floats but I have no idea what's their purpose. Actualy I kind of know what they do, but not how they do it, and that's what I need to know. Like whats the purpose of each float that compose the normal.
Usually for game models the amount of vertexes of positions will equal to the ones of the normal vectors, and of the texcoords(UVs).Repeperilka wrote:I'm getting an error in noesis that looks like this:
WARNING: Size of normal list does not match positions, ignoring normals.
But you can optimize them by removing the copies of the same object, which'll result in different counts for positions/normals/UVs. Guess that's what your problem is about.
May you find peace in this puzzle-solving game.
when you get helped.
- An Imitable Workflow for Reverse Engineering a Game Model
- Advanced Mesh Reaper
- Reverse Model Wireframe
when you get helped.-
Repeperilka
- n00b
- Posts: 14
- Joined: Fri Jun 08, 2018 10:36 pm
- Has thanked: 6 times
- Been thanked: 1 time
Re: How do normals work?
Hmm, it is probably a problem with my script because i've just made some debugging and this is what i am facing:Bigchillghost wrote:Usually for game models the amount of vertexes of positions will equal to the ones of the normal vectors, and of the texcoords(UVs).
But you can optimize them by removing the copies of the same object, which'll result in different counts for positions/normals/UVs. Guess that's what your problem is about.
Code: Select all
Detected file type: Leisure Suit Larry
3
35
------Object14------
vertex count = 1668
face index count = 5325
normals count = 1668
uv's count = 1668
------Object16------
vertex count = 265
face index count = 666
normals count = 265
uv's count = 265
------Object17------
vertex count = 362
face index count = 777
normals count = 362
uv's count = 362
------Object28------
vertex count = 891
face index count = 2742
normals count = 891
uv's count = 891
------Object34------
vertex count = 274
face index count = 651
normals count = 274
uv's count = 274
WARNING: Size of normal list does not match positions, ignoring normals.
WARNING: Size of uv list does not match positions, ignoring uv's.
WARNING: Size of normal list does not match positions, ignoring normals.
WARNING: Size of uv list does not match positions, ignoring uv's.
WARNING: Size of normal list does not match positions, ignoring normals.
WARNING: Size of uv list does not match positions, ignoring uv's.
WARNING: Size of normal list does not match positions, ignoring normals.
WARNING: Size of uv list does not match positions, ignoring uv's.
WARNING: Size of normal list does not match positions, ignoring normals.
WARNING: Size of uv list does not match positions, ignoring uv's.
Generating normals for 1668 vertices...
Generating normals for 265 vertices...
Generating normals for 362 vertices...
Generating normals for 891 vertices...
Generating normals for 274 vertices...
Reading 'C:\Users\aleja\OneDrive\Escritorio\Larry Extract\out\GIRL\LARRYCOOL\\14'...Failed.
Reading 'C:\Users\aleja\OneDrive\Escritorio\Larry Extract\out\GIRL\LARRYCOOL\\16'...Failed.
Reading 'C:\Users\aleja\OneDrive\Escritorio\Larry Extract\out\GIRL\LARRYCOOL\\17'...Failed.
Reading 'C:\Users\aleja\OneDrive\Escritorio\Larry Extract\out\GIRL\LARRYCOOL\\28'...Failed.
Reading 'C:\Users\aleja\OneDrive\Escritorio\Larry Extract\out\GIRL\LARRYCOOL\\34'...Failed.So, (vn1 + vn2 + vn3)^2 = 1.0? (I am not very good at math nor english)Bigchillghost wrote:Normals are unit vectors of which the square sum of the 3 coords equal to 1.0. And if you treat their coords as the ones of vertexes, you'll see them all distributing on the Unit Ball. Usually the normal vector of a vertex equals to the average of all the normal vectors of the faces this vert belongs to, but that's not always applicable for game models.
- Bigchillghost
- double-veteran

- Posts: 1031
- Joined: Tue Jul 05, 2016 9:37 am
- Has thanked: 32 times
- Been thanked: 1216 times
Re: How do normals work?
Then you must have made some mistakes with your code. You'll need to post your script to reveal your issues.Repeperilka wrote:and I've checked the uv's with ModelResearcher and they are good.
Nop. It's vnx^2 + vny^2 + vnz^2 = 1.0.Repeperilka wrote:So, (vn1 + vn2 + vn3)^2 = 1.0?
May you find peace in this puzzle-solving game.
when you get helped.
- An Imitable Workflow for Reverse Engineering a Game Model
- Advanced Mesh Reaper
- Reverse Model Wireframe
when you get helped.-
Repeperilka
- n00b
- Posts: 14
- Joined: Fri Jun 08, 2018 10:36 pm
- Has thanked: 6 times
- Been thanked: 1 time
Re: How do normals work?
Code: Select all
from inc_noesis import *
def registerNoesisTypes():
handle = noesis.register("Leisure Suit Larry", ".WGG")
noesis.setHandlerTypeCheck(handle, noepyCheckType)
noesis.setHandlerLoadModel(handle, noepyLoadModel)
noesis.logPopup()
return 1
def noepyCheckType(data):
if len(data) < 8:
return 0
j = NoeBitStream(data)
if j.readUInt() != 0x49535648:
return 0
return 1
def noepyLoadModel(data, mdlList):
f = NoeBitStream(data)
#start positions
VertexStart = []
f.seek(0x24, NOESEEK_ABS)
TableStart = f.readUInt()
NumberOfChunks = f.readUInt()
StartChunkPos = f.readUInt() + 0x58
f.seek(0x4, NOESEEK_REL)
FacesStart = f.readUInt() + 0x8
StartPosition = 0x58
for i in range(0, NumberOfChunks):
f.seek(StartChunkPos + 0x4, NOESEEK_ABS)
vertCount = f.readUInt()
f.seek(0x30, NOESEEK_REL)
vertSize = f.readUInt()
VertexStart.append(Chunk(vertSize, f.tell()))
StartChunkPos = f.tell() + vertCount * vertSize
print(len(VertexStart))
#objects
f.seek(StartPosition + TableStart + 0x8, NOESEEK_ABS)
ObjectsCount = f.readUInt()
f.seek(StartPosition, NOESEEK_ABS)
Objects = []
for i in range(0, ObjectsCount):
Objects.append(f.readBytes(8).decode("ASCII").rstrip("\0"))
f.seek(0x8, NOESEEK_REL)
#table
f.seek(StartPosition + TableStart, NOESEEK_ABS)
NumberOfEntries = f.readUInt()
f.seek(0x14, NOESEEK_REL)
StartEntries = f.tell()
Entries = []
for i in range(0, NumberOfEntries):
chunk = f.readUShort()
f.seek(0xA, NOESEEK_REL)
nVert = f.readUShort()
f.seek(0x2, NOESEEK_REL)
nFac = f.readUShort()
f.seek(0x2, NOESEEK_REL)
fac = f.readUShort()
f.seek(0x4, NOESEEK_REL)
vert = f.readUShort()
f.seek(0x2, NOESEEK_REL)
index = f.readUShort()
f.seek(0x8, NOESEEK_REL)
Entries.append(Entry(chunk, vert, fac, nVert, nFac, index))
print(len(Entries))
#objects
Meshes = []
FinalObjects = 0
vertex = []
faces = []
normals = []
uv = []
for i in range(0, len(Entries)):
LastVert = len(vertex)
#Vertices
pos = VertexStart[Entries[i].nChunk].startPosition + Entries[i].nVertex * VertexStart[Entries[i].nChunk].entrySize
f.seek(pos, NOESEEK_ABS)
if VertexStart[Entries[i].nChunk].entrySize == 40:
for e in range (0, Entries[i].vertexCount):
vertex.append (NoeVec3((f.readFloat(), f.readFloat(), f.readFloat())))
f.seek(0x8, NOESEEK_REL)
normals.append(NoeVec3((f.readFloat(), f.readFloat(), f.readFloat())))
uv.append(NoeVec3((f.readFloat(), f.readFloat(), f.readFloat())))
f.seek(-0x4, NOESEEK_REL)
elif VertexStart[Entries[i].nChunk].entrySize == 36:
for e in range (0, Entries[i].vertexCount):
vertex.append (NoeVec3((f.readFloat(), f.readFloat(), f.readFloat())))
f.seek(0x4, NOESEEK_REL)
normals.append(NoeVec3((f.readFloat(), f.readFloat(), f.readFloat())))
uv.append(NoeVec3((f.readFloat(), f.readFloat(), f.readFloat())))
f.seek(-0x4, NOESEEK_REL)
elif VertexStart[Entries[i].nChunk].entrySize == 32:
for e in range (0, Entries[i].vertexCount):
vertex.append (NoeVec3((f.readFloat(), f.readFloat(), f.readFloat())))
normals.append(NoeVec3((f.readFloat(), f.readFloat(), f.readFloat())))
uv.append(NoeVec3((f.readFloat(), f.readFloat(), f.readFloat())))
f.seek(-0x4, NOESEEK_REL)
#Faces
pos = FacesStart + StartPosition + Entries[i].nFaces * 2
f.seek(pos, NOESEEK_ABS)
for e in range (0, Entries[i].facesCount):
faces.append(f.readUShort() + LastVert)
#setup1
if (FinalObjects < Entries[i].objIndex):
Meshes.append(NoeMesh (faces, vertex, str(i), str(i)))
Meshes[FinalObjects].normals.append(normals)
Meshes[FinalObjects].uvs.append(uv)
print("------Object" + str(i) + "------")
print("vertex count = " + str(len(vertex)))
print ("face index count = " + str(len(faces)))
print("normals count = " + str(len(normals)))
print("uv's count = " + str(len(uv)))
faces = []
vertex = []
normals = []
uv = []
FinalObjects = FinalObjects + 1
#setup2
#print(len(normals))
#print(len(vertex))
#Meshes.append(NoeMesh (faces, vertex, "Hola" + str(i), ""))
#Meshes[i].normals.append(normals)
#normals = []
#vertex = []
#faces = []
#uv = []
mdlList.append(NoeModel(Meshes, [], []))
return 1
class Entry:
nChunk = 0
vertexCount = 0
facesCount = 0
nVertex = 0
nFaces = 0
objIndex = 0
def __init__(self, chunk, vert, fac, nVert, nFac, index):
self.nChunk = chunk
self.vertexCount = vert
self.facesCount = fac
self.nVertex = nVert
self.nFaces = nFac
self.objIndex = index
class Chunk:
startPosition = 0
entrySize = 0
def __init__(self, size, start):
self.entrySize = size
self.startPosition = start- Bigchillghost
- double-veteran

- Posts: 1031
- Joined: Tue Jul 05, 2016 9:37 am
- Has thanked: 32 times
- Been thanked: 1216 times
Re: How do normals work?
Code: Select all
normals.append(NoeVec3((f.readFloat(), f.readFloat(), f.readFloat())))Code: Select all
normals.append(NoeVec3([f.readFloat(), f.readFloat(), f.readFloat()]))Code: Select all
normals.append(NoeVec3.fromBytes(bs.readBytes(12)))Code: Select all
uv.append(NoeVec3((f.readFloat(), f.readFloat(), f.readFloat())))like
Code: Select all
uv.append(NoeVec3([f.readFloat(), f.readFloat(), 0]))May you find peace in this puzzle-solving game.
when you get helped.
- An Imitable Workflow for Reverse Engineering a Game Model
- Advanced Mesh Reaper
- Reverse Model Wireframe
when you get helped.-
Repeperilka
- n00b
- Posts: 14
- Joined: Fri Jun 08, 2018 10:36 pm
- Has thanked: 6 times
- Been thanked: 1 time
Re: How do normals work?
I tried every combination possible with the things you told me, and i still get the same warning prompts.
It keep saying "Url of the archive...Failed" even though noesis is showing me the 3d model perfectly (with fucked up normals, of course)
Edit: i just aded a print with the first entry of every array
Code: Select all
Detected file type: Leisure Suit Larry
3
45
------Object23------
vertex count = 2067
1st vert = (0.07027500867843628, 0.07789701223373413, 0.16757899522781372)
face index count = 7437
1st face = 0
normals count = 2067
1st normal = (0.6937000751495361, 0.6547720432281494, 0.300091028213501)
uv's count = 2067
1st uv = [0.4456320106983185, 0.38781505823135376, 0]
------Object28------
vertex count = 407
1st vert = (0.018630001693964005, 0.05230500549077988, 0.46636101603507996)
face index count = 1371
1st face = 0
normals count = 407
1st normal = (0.49452102184295654, 0.07861600816249847, 0.865602970123291)
uv's count = 407
1st uv = [0.4007430076599121, 0.04190700128674507, 0]
------Object34------
vertex count = 326
1st vert = (0.1076200008392334, -0.1154480054974556, 0.39223504066467285)
face index count = 1011
1st face = 0
normals count = 326
1st normal = (0.6704729795455933, -0.35633304715156555, 0.6507640480995178)
uv's count = 326
1st uv = [0.22328200936317444, 0.4489409923553467, 0]
------Object36------
vertex count = 150
1st vert = (0.02080800198018551, -0.10414400696754456, 0.46253401041030884)
face index count = 597
1st face = 0
normals count = 150
1st normal = (0.5784180164337158, -0.24716001749038696, 0.777396023273468)
uv's count = 150
1st uv = [0.4647040069103241, 0.04448600485920906, 0]
------Object39------
vertex count = 121
1st vert = (-0.08317900449037552, -0.051423002034425735, 0.12147300690412521)
face index count = 468
1st face = 0
normals count = 121
1st normal = (-0.7651110291481018, -0.15395501255989075, 0.6252229809761047)
uv's count = 121
1st uv = [0.9215329885482788, 0.7528210282325745, 0]
------Object42------
vertex count = 256
1st vert = (-0.0910470113158226, -0.02799900248646736, 0.08261200040578842)
face index count = 801
1st face = 0
normals count = 256
1st normal = (-0.9300490617752075, 0.08480000495910645, 0.35751602053642273)
uv's count = 256
1st uv = [0.9501460790634155, 0.07912901043891907, 0]
------Object44------
vertex count = 131
1st vert = (0.06489300727844238, -0.1863820105791092, -0.8974469900131226)
face index count = 213
1st face = 0
normals count = 131
1st normal = (0.12117300927639008, -0.6720520257949829, 0.730522096157074)
uv's count = 131
1st uv = [0.9698180556297302, 0.4650510251522064, 0]
WARNING: Size of normal list does not match positions, ignoring normals.
WARNING: Size of uv list does not match positions, ignoring uv's.
WARNING: Size of normal list does not match positions, ignoring normals.
WARNING: Size of uv list does not match positions, ignoring uv's.
WARNING: Size of normal list does not match positions, ignoring normals.
WARNING: Size of uv list does not match positions, ignoring uv's.
WARNING: Size of normal list does not match positions, ignoring normals.
WARNING: Size of uv list does not match positions, ignoring uv's.
WARNING: Size of normal list does not match positions, ignoring normals.
WARNING: Size of uv list does not match positions, ignoring uv's.
WARNING: Size of normal list does not match positions, ignoring normals.
WARNING: Size of uv list does not match positions, ignoring uv's.
WARNING: Size of normal list does not match positions, ignoring normals.
WARNING: Size of uv list does not match positions, ignoring uv's.
Generating normals for 2067 vertices...
Generating normals for 407 vertices...
Generating normals for 326 vertices...
Generating normals for 150 vertices...
Generating normals for 121 vertices...
Generating normals for 256 vertices...
Generating normals for 131 vertices...
Reading 'C:\Users\aleja\OneDrive\Escritorio\Larry Extract\out\GIRL\GIRLACTR\\23'...Failed.
Reading 'C:\Users\aleja\OneDrive\Escritorio\Larry Extract\out\GIRL\GIRLACTR\\28'...Failed.
Reading 'C:\Users\aleja\OneDrive\Escritorio\Larry Extract\out\GIRL\GIRLACTR\\34'...Failed.
Reading 'C:\Users\aleja\OneDrive\Escritorio\Larry Extract\out\GIRL\GIRLACTR\\36'...Failed.
Reading 'C:\Users\aleja\OneDrive\Escritorio\Larry Extract\out\GIRL\GIRLACTR\\39'...Failed.
Reading 'C:\Users\aleja\OneDrive\Escritorio\Larry Extract\out\GIRL\GIRLACTR\\42'...Failed.
Reading 'C:\Users\aleja\OneDrive\Escritorio\Larry Extract\out\GIRL\GIRLACTR\\44'...Failed.Edit: i just aded a print with the first entry of every array
-
akderebur
- double-veteran

- Posts: 640
- Joined: Fri Jul 08, 2011 10:36 am
- Has thanked: 65 times
- Been thanked: 898 times
Re: How do normals work?
I am not really proficient in Python/Noesis but these lines probably insert the whole normal/uv array as a single object.
Try
Code: Select all
Meshes[FinalObjects].normals.append(normals)
Meshes[FinalObjects].uvs.append(uv)Code: Select all
Meshes[FinalObjects].setNormals(normals)
Meshes[FinalObjects].setUVs(uv)-
Repeperilka
- n00b
- Posts: 14
- Joined: Fri Jun 08, 2018 10:36 pm
- Has thanked: 6 times
- Been thanked: 1 time
Re: How do normals work?
It worked! I have to admit that i did not think this was going to work, but it did!
Thank you both, very much indeed!
Thank you both, very much indeed!
