Great Tool, nice finding, thanks !
In my case I needed face->vertex colour
But the average model does have textures and no materials, so you are right in most cases if someone need vertex colours in the future
So here is my library so far:
Function List
MaterialObject= LoadObjectMaterialFromXFile(File$)
VertexObject= LoadObjectVertexColorFromObjFile(File$)
- BuildMeshMemblockObject(MemblockID)
- CreateMeshMemblock(VertexCount,IndexCount,Bitmask)
- CreateMeshMemblockWithAttribute(MemblockID,Bitmask,Vertex as VertexData, Material as MaterialData)
- SetObjectAttribute(ObjectID,Bitmask,Vertex as VertexData, Material as MaterialData)
Attributes= GetMeshMemblockAttributes(MemblockID)
IndexCount= GetMeshMemblockIndexCount(MemblockID)
IndexOffset= GetMeshMemblockIndexOffset(MemblockID)
VertexCount= GetMeshMemblockVertexCount(MemblockID)
VertexOffset= GetMeshMemblockVertexOffset(MemblockID)
VertexSize= GetMeshMemblockVertexSize(MemblockID)
- PrintMeshMemblock(MemblockID)
- SetMemblockByte4(MemblockID,Offset,r,g,b,a)
- SetMemblockVec2(MemblockID,Offset,u#,v#)
- SetMemblockVec3(MemblockID,Offset,x#,y#,z#)
Library
type VertexColorData
Red#
Green#
Blue#
Alpha#
endtype
type MaterialData
Used as integer
MaterialID as integer[]
VertexColor as VertexColorData[]
endtype
type VertexData
Used as integer
VertexColor as VertexColorData[]
endtype
function CreateMeshMemblock(VertexCount,IndexCount,Bitmask)
Attributes=1
VertexOffset=24
VertexSize=3*4
Position$="position"+chr(0)
PositionLength=GetNextValueOfFour(len(Position$)+1)
inc VertexOffset,PositionLength+4
if (Bitmask && %0001)>0
Normal$="normal"+chr(0)
NormalLength=GetNextValueOfFour(len(normal$)+1)
inc VertexOffset,NormalLength+4
inc VertexSize,3*4
inc Attributes
endif
if (Bitmask && %0010)>0
Uv$="uv"+chr(0)
UvLength=GetNextValueOfFour(len(uv$)+1)
inc VertexOffset,UvLength+4
inc VertexSize,2*4
inc Attributes
endif
if (Bitmask && %0100)>0
Color$="vertexcolor"+chr(0)
ColorLength=GetNextValueOfFour(len(Color$)+1)
inc VertexOffset,ColorLength+4
inc VertexSize,4*1
inc Attributes
endif
if VertexOffset<60 then VertexOffset=60
IndexOffset=VertexOffset+(VertexCount*VertexSize)
MemblockID=Creatememblock(VertexOffset+(VertexCount*VertexSize)+(IndexCount*4))
SetMemblockInt(MemblockID,0,VertexCount)
SetMemblockInt(MemblockID,4,IndexCount)
SetMemblockInt(MemblockID,8,Attributes)
SetMemblockInt(MemblockID,12,VertexSize)
SetMemblockInt(MemblockID,16,VertexOffset)
SetMemblockInt(MemblockID,20,IndexOffset)
AttributeOffset=24
SetMemblockByte(MemblockID,AttributeOffset,0) // Float type component
SetMemblockByte(MemblockID,AttributeOffset+1,3) // number of components
SetMemblockByte(MemblockID,AttributeOffset+2,0) // normalize flag
SetMemblockByte(MemblockID,AttributeOffset+3,PositionLength) // string length
SetMemblockString(MemblockID,AttributeOffset+4,Position$) // string
inc AttributeOffset,PositionLength+4
if (Bitmask && %0001)>0
SetMemblockByte(MemblockID,AttributeOffset,0) // Float type component
SetMemblockByte(MemblockID,AttributeOffset+1,3) // number of components
SetMemblockByte(MemblockID,AttributeOffset+2,0) // normalize flag
SetMemblockByte(MemblockID,AttributeOffset+3,NormalLength) // string length
SetMemblockString(MemblockID,AttributeOffset+4,normal$) // string
inc AttributeOffset,NormalLength+4
endif
if (Bitmask && %0010)>0
SetMemblockByte(MemblockID,AttributeOffset,0) // Float type component
SetMemblockByte(MemblockID,AttributeOffset+1,2) // number of components
SetMemblockByte(MemblockID,AttributeOffset+2,0) // normalize flag
SetMemblockByte(MemblockID,AttributeOffset+3,UvLength) // string length
SetMemblockString(MemblockID,AttributeOffset+4,uv$) // string
inc AttributeOffset,UvLength+4
endif
if (Bitmask && %0100)>0
SetMemblockByte(MemblockID,AttributeOffset,1) // Float type component
SetMemblockByte(MemblockID,AttributeOffset+1,4) // number of components
SetMemblockByte(MemblockID,AttributeOffset+2,1) // normalize flag
SetMemblockByte(MemblockID,AttributeOffset+3,ColorLength) // string length
SetMemblockString(MemblockID,AttributeOffset+4,Color$) // string
inc AttributeOffset,ColorLength+4
endif
for Offset=VertexOffset to VertexOffset+(VertexCount*VertexSize) step 4
SetMemblockFloat(MemblockID,Offset, 0.0)
next Offset
endfunction MemblockID
function BuildMeshMemblockObject(MemblockID)
ObjectID=CreateObjectFromMeshMemblock(MemblockID)
DeleteMemblock(MemblockID)
endfunction ObjectID
function SetMemblockVec3(MemblockID,Offset,x#,y#,z#)
SetMemblockFloat(MemblockID,Offset,x#)
SetMemblockFloat(MemblockID,Offset+4,y#)
SetMemblockFloat(MemblockID,Offset+8,z#)
endfunction
function SetMemblockVec2(MemblockID,Offset,u#,v#)
SetMemblockFloat(MemblockID,Offset,u#)
SetMemblockFloat(MemblockID,Offset+4,v#)
endfunction
function SetMemblockByte4(MemblockID,Offset,r,g,b,a)
SetMemblockByte(MemblockID,Offset,r)
SetMemblockByte(MemblockID,Offset+1,g)
SetMemblockByte(MemblockID,Offset+2,b)
SetMemblockByte(MemblockID,Offset+3,a)
endfunction
function GetMeshMemblockVertexCount(MemblockID)
VertexCount=GetMemblockInt(MemblockID,0)
endfunction VertexCount
function GetMeshMemblockIndexCount(MemblockID)
IndexCount=GetMemblockInt(MemblockID,4)
endfunction IndexCount
function GetMeshMemblockAttributes(MemblockID)
Attributes=GetMemblockInt(MemblockID,8)
endfunction Attributes
function GetMeshMemblockVertexSize(MemblockID)
VertexSize=GetMemblockInt(MemblockID,12)
endfunction VertexSize
function GetMeshMemblockVertexOffset(MemblockID)
VertexOffset=GetMemblockInt(MemblockID,16)
endfunction VertexOffset
function GetMeshMemblockIndexOffset(MemblockID)
IndexOffset=GetMemblockInt(MemblockID,20)
endfunction IndexOffset
function GetNextValueOfFour(Value)
local p
p=4
while p<Value
p=p+4
endwhile
endfunction p
function SetObjectAttribute(ObjectID,Bitmask,Vertex as VertexData, Material as MaterialData)
local MemblockID as integer[]
local TempMemblockID
MaxMeshID=GetObjectNumMeshes(ObjectID)
TempMemblockID=CreateMemblockFromObjectMesh(ObjectID,1)
MemblockID.insert(CreateMeshMemblockWithAttribute(TempMemblockID,Bitmask,Vertex, Material))
DeleteMemblock(TempMemblockID)
for MeshID=2 to MaxMeshID
TempMemblockID=CreateMemblockFromObjectMesh(ObjectID,MeshID)
MemblockID.insert(CreateMeshMemblockWithAttribute(TempMemblockID,Bitmask,Vertex, Material))
DeleteMemblock(TempMemblockID)
next MeshID
DeleteObject(ObjectID)
CreateObjectFromMeshMemblock(ObjectID,MemblockID[0])
DeleteMemblock(MemblockID[0])
for MeshID=1 to MaxMeshID-1
AddObjectMeshFromMemblock(ObjectID,MemblockID[MeshID])
DeleteMemblock(MemblockID[MeshID])
next MeshID
endfunction
function CreateMeshMemblockWithAttribute(MemblockID,Bitmask,Vertex as VertexData, Material as MaterialData)
VertexCount=GetMemblockInt(MemblockID,0)
IndexCount=GetMemblockInt(MemblockID,4)
Attributes=GetMemblockInt(MemblockID,8)
VertexSize=GetMemblockInt(MemblockID,12)
VertexOffset=GetMemblockInt(MemblockID,16)
IndexOffset=GetMemblockInt(MemblockID,20)
//~ if (Bitmask && %0100)>0
//~ for i=0 to Material.MaterialID.length
//~ message(str(Material.MaterialID[i]))
//~ next i
//~ for j=0 to Material.VertexColor.length
//~ message(str(Material.VertexColor[j].Red#)+", "+str(Material.VertexColor[j].Green#)+", "+str(Material.VertexColor[j].Blue#))
//~ next j
//~ endif
NewMemblockID=CreateMeshMemblock(VertexCount,IndexCount,Bitmask)
NewIndexOffset=GetMeshMemblockIndexOffset(NewMemblockID)
NewVertexSize=GetMeshMemblockVertexSize(NewMemblockID)
NewVertexOffset=GetMeshMemblockVertexOffset(NewMemblockID)
for VertexID=0 to VertexCount-1
Offset=VertexOffset+(VertexID*VertexSize)
NewOffset=NewVertexOffset+(VertexID*NewVertexSize)
SetMemblockVec3(NewMemblockID,NewOffset,GetMemblockFloat(MemblockID,Offset),GetMemblockFloat(MemblockID,Offset+4),GetMemblockFloat(MemblockID,Offset+8))
inc NewOffset,3*4
if (Bitmask && %0001)>0
SetMemblockVec3(NewMemblockID,NewOffset,GetMemblockFloat(MemblockID,Offset+12),GetMemblockFloat(MemblockID,Offset+16),GetMemblockFloat(MemblockID,Offset+20))
inc NewOffset,3*4
endif
if (Bitmask && %0010)>0
SetMemblockVec2(NewMemblockID,NewOffset,GetMemblockFloat(MemblockID,Offset+24),GetMemblockFloat(MemblockID,Offset+28))
inc NewOffset,2*4
endif
if (Bitmask && %0100)>0
if Vertex.Used=1
Red#=Vertex.VertexColor[VertexID].Red#
Green#=Vertex.VertexColor[VertexID].Green#
Blue#=Vertex.VertexColor[VertexID].Blue#
Alpha#=Vertex.VertexColor[VertexID].Alpha#
//~ message(str(Red#)+", "+str(Green#)+", "+str(Blue#))
SetMemblockByte4(NewMemblockID,NewOffset,Red#*255,Green#*255,Blue#*255,Alpha#*255)
inc NewOffset,4*1
endif
if Material.Used=1
//~ message(str(VertexID))
//~ message(str(Material.MaterialID.length))
FaceID=trunc(VertexID/3)
//~ message(str(FaceID))
MaterialID=Material.MaterialID[FaceID]
Red#=Material.VertexColor[MaterialID].Red#
Green#=Material.VertexColor[MaterialID].Green#
Blue#=Material.VertexColor[MaterialID].Blue#
Alpha#=Material.VertexColor[MaterialID].Alpha#
//~ message(str(Red#)+", "+str(Green#)+", "+str(Blue#))
SetMemblockByte4(NewMemblockID,NewOffset,Red#*255,Green#*255,Blue#*255,Alpha#*255)
inc NewOffset,4*1
endif
endif
next VertexID
for Index=0 to IndexCount-1
Offset=IndexOffset+Index*4
NewOffset=NewIndexOffset+Index*4
SetMemblockInt(NewMemblockID,NewOffset,GetMemblockInt(MemblockID,Offset))
next Index
endfunction NewMemblockID
function PrintMeshMemblock(MemblockID)
VertexCount=GetMemblockInt(MemblockID,0)
IndexCount=GetMemblockInt(MemblockID,4)
Attributes=GetMemblockInt(MemblockID,8)
VertexSize=GetMemblockInt(MemblockID,12)
VertexOffset=GetMemblockInt(MemblockID,16)
IndexOffset=GetMemblockInt(MemblockID,20)
AttributeOffset=24
message("VertexCount: "+str(VertexCount))
message("IndexCount: "+str(IndexCount))
message("Attributes: "+str(Attributes))
message("VertexSize: "+str(VertexSize))
message("VertexOffset: "+str(VertexOffset))
message("IndexOffset: "+str(IndexOffset))
for i=1 to Attributes
message("type: "+str(GetMemblockByte(MemblockID,AttributeOffset))) // Float type component
message("components: "+str(GetMemblockByte(MemblockID,AttributeOffset+1))) // number of components
message("normalize: "+str(GetMemblockByte(MemblockID,AttributeOffset+2))) // normalize flag
Stringlength=GetMemblockByte(MemblockID,AttributeOffset+3) // string length
Message("length: "+str(Stringlength))
message("string: "+GetMemblockString(MemblockID,AttributeOffset+4,Stringlength)) // string
inc AttributeOffset,StringLength+4
next
endfunction
function LoadObjectVertexColorFromObjFile(File$)
local Vertex as VertexData
local tempVertexColor as VertexColorData
FileID=OpenToRead(File$)
repeat
String$=ReadLine(FileID)
Index=FindString(String$,"v ")
if Index>0
Vertex.Used=1
tempVertexColor.Red#=ValFloat(GetStringToken(String$," ",5))
tempVertexColor.Green#=ValFloat(GetStringToken(String$," ",6))
tempVertexColor.Blue#=ValFloat(GetStringToken(String$," ",7))
Vertex.VertexColor.insert(tempVertexColor)
endif
until FileEOF(FileID)=1
CloseFile(FileID)
endfunction Vertex
function LoadObjectMaterialFromXFile(File$)
local Material as MaterialData
local tempVertexColor as VertexColorData
FileID=OpenToRead(File$)
repeat
Key$=ReadLine(FileID)
if FindString(Key$,"MeshMaterialList")
Material.Used=1
MaxMaterials$=ReadLine(FileID)
MaxMaterials=val(StripString(MaxMaterials$,";"))
MaxFaces$=ReadLine(FileID)
MaxFaces=val(StripString(MaxFaces$,";"))
for FaceID=0 to MaxFaces-1
FaceMaterial$=ReadLine(FileID)
Material.MaterialID.insert(val(StripString(FaceMaterial$,";")))
next FaceID
MaterialID=0
repeat
Key$=ReadLine(FileID)
if FindString(Key$,"Material")
inc MaterialID
Material$=ReadLine(FileID)
tempVertexColor.Red#=ValFloat(GetStringToken(Material$,";",1))
tempVertexColor.Green#=ValFloat(GetStringToken(Material$,";",2))
tempVertexColor.Blue#=ValFloat(GetStringToken(Material$,";",3))
tempVertexColor.Alpha#=ValFloat(GetStringToken(Material$,";",4))
Material.VertexColor.insert(tempVertexColor)
endif
until MaterialID>=MaxMaterials or FileEOF(FileID)=1
endif
until FileEOF(FileID)=1
CloseFile(FileID)
endfunction Material
There is a huge potential for improvements but it works for now.
Actualy, I need Material Color because they are per face but I don't know how to achieve it, I only know Vertices,UV and Normals maybe bones

I know that three vertices creates a triangle-face/polygon...
AGK____________________________________________________________
MeshLab