How to grab texture filenames off model recursive?

Blitz3D Forums/Blitz3D Programming/How to grab texture filenames off model recursive?

Guy Fawkes(Posted 2013) [#1]
Hi all. Is there a way to recursively scan through a .X, .B3D, and .3DS file, and grab the names of all textures associated to the 3D model, then put said models in selected folder? I'm doing this for my level editor which is very close to completion, I've got that working for 3D models, just not 3D textures.

If you need any more information, then please! Feel free to ask! :)

Thank You!


Yasha(Posted 2013) [#2]
You can get the name of a texture with TextureName, and I assume (haven't tried) that you can get the texture out of an entity's loaded brush with GetEntityBrush (and GetSurfaceBrush, if relevant) followed by GetBrushTexture.

Scanning through the model hierarchy you'd do the same way as for any other model task.


Rroff(Posted 2013) [#3]
Probably a reference for it somewhere maybe even example code in the help files dunno but I have this noted down:

	For count = 1 To CountChildren(meshhandle)
		child = GetChild(meshhandle,count)
		If (child) Then
			surface = GetSurface(child,1)
			brush = GetSurfaceBrush(surface)
			texture = GetBrushTexture(brush,0)
			debuglog TextureName$(texture)
			FreeBrush brush
		EndIf
	Next


I also used a function to strip the file path if present from the texturename for what I was doing.


Guy Fawkes(Posted 2013) [#4]
Thanks guys. I just tried it, but I don't think it's working...

EDIT: Nope, it's not working.. And yes, the model I'm importing DOES have a texture.





I am receiving absolutely no debuglog. :(


Yasha(Posted 2013) [#5]
Well you should probably add a couple of lines above that to try to get the Entity brush as well, perhaps that's where the texture is?


Guy Fawkes(Posted 2013) [#6]
You mean CreateBrush(), Yasha?


Rroff(Posted 2013) [#7]
I'm not even sure if that code I pasted works just something I had noted down as a reference as a basis to work from if I needed that feature - pretty sure it works for 3ds files tho but not tested with b3d models.

EDIT: I think for this to work you need to use LoadAnimMesh IIRC LoadMesh won't work with it.


Guy Fawkes(Posted 2013) [#8]
Is there any way to get it to work with B3D, 3DS, and X?


Yasha(Posted 2013) [#9]
I mean that in that code you're doing GetSurface and GetSurfaceBrush for each entity, but not the more straightforward GetEntityBrush.

Different formats also store things differently: B3D matches Blitz entities perfectly so it can apply properties to whole meshes, whereas 3DS has a different structure altogether based on "materials", which get loaded into Blitz3D as surfaces and therefore for that type the properties are likely to be per-surface.


Bobysait(Posted 2013) [#10]
try this

-> totally untested ... (on the fly, so may contains text errors)

function GrabEntityTextures(entity,tab$="", recursive%=True)
 if entityclass(entity)="Mesh"
    print tab+"texture of "+entityname(entity)
    ; texture of the Entity-Brush
    grabbrushtextures(getentitybrush(entity),tab+" | -")
    ; grab textures of the entity-surfaces
    local NbS = countsurfaces(entity), ids, s
    for ids = 1 to Nbs
      Grabbrushtextures(GetSurface(entity,ids),tab+" | -")
    Next
 EndIf
 
 ; grab the children too ?
 if recursive
   for n=1 t countchildren(entity)
     grabEntitytextures(getchild(entity,n), tab+" | -")
   next
 endif
end function
function Grabbrushtextures(brush,tab$="   ")
 if not(brush) then return false
 for i = 0 To 7
  t=GetBrushTexture(brush,i)
   if t
    f$=TextureName(t)
     if len(f) then print tab+" - tex["+i+"] = "+f
      EndIf
 next
end function




Guy Fawkes(Posted 2013) [#11]
Thanks, but that didn't work. HOWEVER. I have a SORTA working function. Debuglog captures the name of the textures applied to the X model just fine. Problem is, it's not copying to the folder "\ents\", which DOES INDEED exist.



and inside the ImportEnts() function:




Bobysait(Posted 2013) [#12]
the function I posted above should always work with <loaded models> (except a small error if the line "for n=1 t countchildren(entity)" where it should be "1 tO countchildren")

If it does not work, it's that the <loaded model> is currently NOT textured (whatever the file is exported with textures, blitz3d does not fully support it and does not apply the textures)

I know 3ds and X files are not really fully supported (for sure, 3ds does not import skined animation and/or textures, and there is different "x" version that are more or less supported)

So, if you intend to grab the real textures from the file (and not from the model), you'll have to parse the file and extract the textures from the file chunks.
thoses file formats are not so complicated.
Maybe then, you could make some stuff to apply the textures from the file to the loaded model


Guy Fawkes(Posted 2013) [#13]
I just wanna download the texture locations from the model, and make a copy of them from their original folder, to the current folder.


Bobysait(Posted 2013) [#14]
sure, but, you need to be more precise.
the Model as "a blitz3d loaded entity" ?
or the model as "a 3D model file"

because, for the entity, as explained, if my function does not get the textures, then, the only way is to grab the file (and not the entity)


Guy Fawkes(Posted 2013) [#15]
the model as a 3d model file.


Bobysait(Posted 2013) [#16]
Ok, then, it will be a bit of work to achieve.

1 - check extension (.x/.b3d/.3ds)
2 - for each extension, you need a specific parser
2.a: b3d file : check the first chunk ( it should be the "TEXS" chunk that contains all the textures of the model(s) )

2.b: 3ds file : search for the $AFFF tag wich contains materials
then the texture finename is stored on the chunk $A000 (as far as I remember)

2.c X file : ... no idea, I 've never deal with this format
[edit] for x format, it seems there is 2 specifications, one for a text based format, one for a binary format ...


Guy Fawkes(Posted 2013) [#17]
How would I parse the chunk? o.O


Bobysait(Posted 2013) [#18]
With a parser of course :)

have a look on the code archive, there must be many of them (for obj, x, 3ds, b3d and almost all the classic 3D formats)


Rroff(Posted 2013) [#19]
@Yasha - been awhile since I played with that code but I seem to remember GetSurface and GetSurfaceBrush being needed for correctly handling 3ds files, while b3d model format worked with entitybrush ok.


Guy Fawkes(Posted 2013) [#20]
Thanks alot, you guys! I'll take a look at the code in a bit! :)


John Blackledge(Posted 2013) [#21]
This code works for me, and write the textures to a text file:



Guy Fawkes(Posted 2013) [#22]
Ok, that's EPIC! Thanks alot, John Blackledge! ^_^


Bobysait(Posted 2013) [#23]
I've made a "simple" parser for b3d and x
(not currently tested with x files as I don't have X files ...
but should work ...)
I assumed textures are stored after the "TextureFilename {" chunk in the X files (txt version only)
It seems it is the way they store them, but, it also seems there is different X file format so ...


-> the function read the files (whatever the format is, it will detect it using the first tag)