Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Como Conseguir Ciertos Datos En Maxscript

Iniciado por Haddd, 19 de Septiembre de 2004, 10:00:15 PM

« anterior - próximo »

Haddd

 Os pongo el código de un exportador. Necesitaría saber cómo conseguir el material ref base que tiene el objeto, y cómo conseguir más coordenadas de textura, si por ejemplo tuviera las coordenadas de textura de los lightmaps. También me gustaría saber cómo puedo acceder al material y conocer, por ejemplo, el archivo de diffuse que utiliza el material.

¿alguien puede echarme una manita?

Muchísimas gracias. (ole)


   -- Cogemos un snapshot del mes
 at time fstart geo = snapShotAsMesh obj
 
 local geo_nverts = geo.numverts -- Nº de vértices
 local geo_nfaces = geo.numfaces -- Nº de caras
 local uv_num= geo.numtverts  -- Nº de coordenadas de textura
 
 if uv_num != 0 then ( -- si no tiene coordenadas de textura no lo queremos


  -- Creamos el archivo
  local outGeoFile = createfile out_name
 
  -- Grabamos la cabecera
  format "Haddd\n" to:outGeoFile
  format "Vertices:%\nCaras:%\n" geo_nverts geo_nfaces to:outGeoFile

  -- Grabamos las coordenadas de las vértices en formato D3D
  for v = 1 to geo_nverts do (

   local vcoords = getVert geo v
   local vx = vcoords[1]
   local vy = vcoords[3]
   local vz = vcoords[2] * -1
   local n=v-1

   format "%:% % %\n" n vx vy vz  to:outGeoFile
  )

  -- Ahora las caras
  format "CARAS\n" to:outGeoFile
 
  for f = 1 to geo_nfaces do (
 
   local pface = (getface geo f) - 1
   local p1 = pface[1] as integer
   local p2 = pface[2] as integer
   local p3 = pface[3] as integer
   
   --Cogemos el MatID
   local matID=getFaceMatId geo f

   -- UV
   local vert_uv = getTVFace geo f
   
   -- Cogemos los valores de textura del primer vértice de la cara. Le restamos 1 a y para convertirlos en D3D
   
   local uvw_1 = getTVert geo vert_uv[1]
   local uv1_x = uvw_1[1]
   local uv1_y = 1-uvw_1[2]
   local uv1_z = uvw_1[3]
   
   -- del segundo
   local uvw_1 = getTVert geo vert_uv[2]
   local uv2_x = uvw_1[1]
   local uv2_y = 1-uvw_1[2]
   local uv2_z = uvw_1[3]
   
   -- y del tercero
   local uvw_1 = getTVert geo vert_uv[3]
   local uv3_x = uvw_1[1]
   local uv3_y = 1-uvw_1[2]
   local uv3_z = uvw_1[3]
   
    format " % (% % %) % (% % %) % (% % %) %\n" p3 uv3_x uv3_y uv3_z p2 uv2_x uv2_y uv2_z p1 uv1_x uv1_y uv1_z matID to:outGeoFile
   -- end UV
  )
 
  --Se terminó, así que cerramos el fichero
  close outGeoFile

BeRSeRKeR

 Hi.

Pues para el tema de recoger el material ya lo expliqué hace poco. Concretamente aquí puse un trozo de código que extrae cierta información de los materiales aplicados a los nodos de la escena.

En cuanto a cómo acceder al mapeado de cada canal, nunca lo he utilizado pero te he escrito en un momento un trozo de código donde muestra cómo hacerlo. Yo lo he probado creando un plano y asignándole 2 canales de mapeado y parece funcionar. Ten en cuenta que con este script tienes que tener seleccionado el nodo del que quieres saber las coordenadas de textura.

-- Convertirmos el nodo seleccionado en un TriMesh
obj = snapshotAsMesh $

-- Número de canales soportados por este mesh
numChannels = (meshOp.getNumMaps obj) - 1
format "Canales disponibles: %\n\n" numChannels

-- Suponemos que los canales van consecutivos (canal#1, canal#2, etc).
-- De lo contrario habría que manejar este bucle de otra forma. O bien
-- permitir al usuario escoger los canales a su gusto a la hora de
-- exportar la escena.
for nChannel = 1 to numChannels do
(
   -- Si el mesh coporta este canal de mapeado...
   if (meshOp.getMapSupport obj 1) == true then
   (
       format "\nIndices de coordenadas de textura para el canal %\n\n" nChannel

       -- Indices de coordenadas de textura para el canal actual
       numFaces = meshOp.getNumMapFaces obj nChannel
       format "\tEste canal dispone de % caras\n" numFaces
       for nFace = 1 to numFaces do
       (
           format "\t\tFace#%: %\n" nFace (meshOp.getMapFace obj nChannel nFace)
       )

       -- Coordenadas de textura para el canal actual
       numTexCoords = meshOp.getNumMapVerts obj nChannel
       format "\tEste canal dispone de % coordenadas de textura\n" numTexCoords
       for nTexCoord = 1 to numTexCoords do
       (
           texCoord = meshOp.getMapVert obj nChannel nTexCoord
           format "\t\tTexCoord#%: % %\n" nTexCoord texCoord.x texCoord.y
       )
   )
   else -- No existe mapeado para este canal
   (
       format "\nNo hay coordenadas de textura para el canal %\n\n" nChannel
   )
)


Aquí tienes la salida utilizando el plano que he mencionado antes:

CitarCanales disponibles: 2

Indices de coordenadas de textura para el canal 1

   Este canal dispone de 2 caras
  Face#1: [3,1,4]
  Face#2: [2,4,1]
   Este canal dispone de 4 coordenadas de textura
  TexCoord#1: 0.000499547 0.000499785
  TexCoord#2: 0.9995 0.000499547
  TexCoord#3: 0.000499785 0.9995
  TexCoord#4: 0.9995 0.9995

Indices de coordenadas de textura para el canal 2

   Este canal dispone de 2 caras
  Face#1: [3,1,4]
  Face#2: [2,4,1]
   Este canal dispone de 4 coordenadas de textura
  TexCoord#1: 0.000999093 0.000499785
  TexCoord#2: 1.999 0.000499547
  TexCoord#3: 0.00099957 0.9995
  TexCoord#4: 1.999 0.9995

A ver si eso te ayuda.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

BeRSeRKeR

 Hay un pequeño fallo en el código de antes. Como ves, siempre comprobaba la validez del canal de mapeado 1:

Cita de: "BeRSeRKeR"for nChannel = 1 to numChannels do
(
   -- Si el mesh soporta este canal de mapeado...
   if (meshOp.getMapSupport obj 1) == true then    -- <- FALLO
   (
       format "\nIndices de coordenadas de textura para el canal %\n\n" nChannel

       ....

Debería ser:

for nChannel = 1 to numChannels do
(
   -- Si el mesh soporta este canal de mapeado...
   if (meshOp.getMapSupport obj nChannel) == true then
   (
       format "\nIndices de coordenadas de textura para el canal %\n\n" nChannel

       ....


Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Haddd

 Muchas gracias. He probado lo de los materiales y te cuento:

Uso el max 5, me da un error al referirme al diffuseMap. Me dice que no es una propiedad :(

También necesito saber qué material base utiliza un mesh. Si exportas un ASE, te genera un Material ID para cada cara, pero al final te indica un MATERIAL_REF para todo el mesh.

Ya es muy tarde, esper oque mañana por la noche pueda probar lo de las texturas.

De nuevo muchas gracias.


BeRSeRKeR

 En el caso de que MAX5 no disponga de la propiedad DiffuseMap, prueba a utilizar:

tu_material.maps[2]               <- devuelve el diffuse map
tu_material.maps[2].fileName <- devuelve el archivo de textura para el diffuse map

El índice 2 apunta al diffuse map en el array maps. Los índices coinciden con el orden en el que puedes ver los "Maps" en la ventana de materiales de MAX:

1 - Ambient Color
2 - Diffuse Color
3 - Specular Color
......
etc.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

BeRSeRKeR

 
Cita de: "Haddd"También necesito saber qué material base utiliza un mesh. Si exportas un ASE, te genera un Material ID para cada cara, pero al final te indica un MATERIAL_REF para todo el mesh.
Para conocer el material para cada cara tienes que utilizar la función:

CitargetFaceMatID
   Returns the indexed face's material ID as an integer.

Después recoges el material de dicha cara utilizando el índice que te devuelve getFaceMatID:

faceMtl = sceneMaterials[faceMtlID]

Con respecto a lo del MATERIAL_REF, no se trata de una función de MAX. Se trata de una lista interna de materiales que mantiene el plugin que exporta a ASE. Te he creado un script que emula el comportamiento del plugin:

-- Clase que mantiene la lista de los materiales de la escena
struct MtlKeeper
(
   mtlTab = #(), -- Lista de materiales

   -- Añade un material a la lista siempre que no sea null
   -- o ya se encuentre en la lista
   fn addMtl mtl =
   (
       if mtl == undefined do return false

       local numMtls = mtlTab.count;
       for nMtl = 1 to numMtls do
           if mtlTab[nMtl] == mtl do return false

       append mtlTab mtl
   ),

   -- Retorna el índice del material "mtl" dentro de la lista
   fn getMtlID mtl =
   (
       local  numMtls = mtlTab.count
       for nMtl = 1 to numMtls do
           if mtlTab[nMtl] == mtl do return nMtl

       return -1
   ),

   -- Retorna el número de materiales en la lista
   fn count =
   (
       return mtlTab.count
   ),

   -- Devuelve el material cuyo índice es "mtlID"
   fn getMtl mtlID =
   (
       return mtlTab[mtlID]
   )
)

-- Insertamos los materiales de la escena en una lista
mtlList = MtlKeeper()
for node in $* do
(
   mtlList.addMtl node.material
)

-- Mostramos los materiales de la lista
format "*MATERIAL_LIST {\n"
format "\t*MATERIAL_COUNT %\n" (mtlList.count())
for nMtl = 1 to mtlList.count() do
(
   local mtl = mtlList.getMtl(nMtl)
   format "\t*MATERIAL % {\n" nMtl
   format "\t\t*MATERIAL_NAME \"%\"\n" mtl.name
   format "\t\t*MATERIAL_CLASS: %\n\t}\n" (classOf mtl)
)
format "}\n"

-- Ahora mostramos el MATERIAL_REF para cada nodo de la escena
for node in $* do
(
   local mtlID = mtlList.getMtlID node.material
   format "\n*GEOMOBJECT {\n"
   format "\t*NODE_NAME \"%\"\n" node.name
   format "\t*MATERIAL_REF %\n}\n" mtlID
)


La salida del script en la escena con la que he probado:

Citar*MATERIAL_LIST {
    *MATERIAL_COUNT 2
        *MATERIAL 1 {
            *MATERIAL_NAME "03 - Default"
            *MATERIAL_CLASS: Standardmaterial
        }
        *MATERIAL 2 {
            *MATERIAL_NAME "01 - Default"
            *MATERIAL_CLASS: Multimaterial
        }
}

*GEOMOBJECT {
    *NODE_NAME "Sphere01"
    *MATERIAL_REF 1
}
*GEOMOBJECT {
    *NODE_NAME "Sphere02"
    *MATERIAL_REF 2
}

Eso es todo.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Haddd

 Miles de gracias, eres la caña.

Sin embargo, no me funciona. Tengo una escena con 3 objetos. 2 de ellos están atachados y han creado un submaterial:

Atachados:Cubo(matID:1) y esfera(matID:2)

Rectángulo(MatID:1)

Como puedes ver, me está dando el mismo nº de MatID, cuando en realidad son materiales diferentes. He aquí el código enterito:


fn GetGeometry g = (
Superclassof g == Geometryclass and classof g != TargetObject )

fn geo2Houdini fstart fend obj = (

fstart=0 -- Siempre el frame 0

--Pedimos el nombre del archivo a grabar

local objName = obj.name
local geoName = objName + ".ase"
local out_name = GetSaveFileName filename:geoName

if out_name != undefined then ( -- Comprobamos que haya indicado un nombre de archivo correcto
 
 -- Creamos el archivo
 local archivo = createfile out_name
 
 -- Grabamos la cabecera
 format "Haddd\n" to:archivo
 
 for node in geometry do ( -- todos los objectos
 
  obj=node

   -- Cogemos un snapshot del mes
 at time fstart geo = snapShotAsMesh obj
 
 local geo_nverts = geo.numverts -- Nº de vértices
 local geo_nfaces = geo.numfaces -- Nº de caras
 local uv_num= geo.numtverts  -- Nº de coordenadas de textura
 
 if uv_num != 0 then ( -- si no tiene coordenadas de textura no lo queremos

  format "Nombre:%s\n" obj.name to:archivo
 
  format "Vertices:%\nCaras:%\n" geo_nverts geo_nfaces to:archivo

  -- Grabamos las coordenadas de las vértices en formato D3D
  for v = 1 to geo_nverts do (

   local vcoords = getVert geo v
   local vx = vcoords[1]
   local vy = vcoords[3]
   local vz = vcoords[2] * -1
   local n=v-1

   format "%:% % %\n" n vx vy vz  to:archivo
  )

  -- Ahora las caras
  format "CARAS\n" to:archivo
 
  for f = 1 to geo_nfaces do (
 
   local pface = (getface geo f) - 1
   local p1 = pface[1] as integer
   local p2 = pface[2] as integer
   local p3 = pface[3] as integer
   
   --Cogemos el MatID
   local matID=getFaceMatId geo f
   
   local faceMtl=sceneMaterials[matID]
   
   -- UV
   local vert_uv = getTVFace geo f
   
   -- Cogemos los valores de textura del primer vértice de la cara. Le restamos 1 a y para convertirlos en D3D
   
   local uvw_1 = getTVert geo vert_uv[1]
   local uv1_x = uvw_1[1]
   local uv1_y = 1-uvw_1[2]
   local uv1_z = uvw_1[3]
   
   -- del segundo
   local uvw_1 = getTVert geo vert_uv[2]
   local uv2_x = uvw_1[1]
   local uv2_y = 1-uvw_1[2]
   local uv2_z = uvw_1[3]
   
   -- y del tercero
   local uvw_1 = getTVert geo vert_uv[3]
   local uv3_x = uvw_1[1]
   local uv3_y = 1-uvw_1[2]
   local uv3_z = uvw_1[3]
   
   format " % (% % %) % (% % %) % (% % %) % %\n" p3 uv3_x uv3_y uv3_z p2 uv2_x uv2_y uv2_z p1 uv1_x uv1_y uv1_z matID faceMtl to:archivo
  )
 )
 )
 format "\nMATERIALES\n" to:archivo
 
 for node in $* do ( -- $* significa todos los elementos
 
  if node.material!=undefined then (
 
   local mtl=node.material
   
   if (ClassOf mtl)==Multimaterial then (
   
    format "Material % con submaterial\n" mtl.name to:archivo
   
    for subMtl in mtl do (
   
     --Asumimos que el material es de tipo standard
     
     format "Submaterial:%\n" subMtl.name to:archivo
     
     --if subMtl.DiffuseMap!=undefined then (
     
      format "diffuse:%\n" subMtl.DiffuseMap.fileName to:archivo

     --)
    )
   )
   else (

    format "Material %\n" mtl.name to:archivo

    --if mtl.DiffuseMap!=undefined then (
   
     format "diffuse:%\n" mtl.DiffuseMap.fileName to:archivo

    --)
   )
   
  )
 )

 --Se terminó, así que cerramos el fichero

 close archivo
)
)

rollout exportGeo_rollout "poly with uv to houdini" width:162 height:154
(

radiobuttons animated "" pos:[26,27] width:86 height:16 labels:#("yes", "no") default:2 columns:2
pickButton pickObject "pick an object" pos:[35,115] width:98 height:29 toolTip:"pick an object in the scene" message:"ok" filter:GetGeometry
GroupBox grp1 "is animated " pos:[5,9] width:152 height:99

edittext fromf "from frame :" pos:[11,47] width:138 height:21 enabled:false text:"0"
edittext tof "to frame :" pos:[22,75] width:125 height:21 enabled:false text:"0"

on animated changed state do (

fstart_string = animationrange.start as string
rcount = fstart_string.count - 1
fstart_s = substring fstart_string 1 rcount

fend_string = animationrange.end as string
rcount = fend_string.count - 1
fend_s = substring fend_string 1 rcount
local zero = 0 as string

fromf.enabled = case animated.state of
 (
 1: true
 2: false
 )
tof.enabled = case animated.state of
 (
 1: true
 2: false
 )
fromf.text = case animated.state of
 (
 1: fstart_s
 2: zero  )
tof.text = case animated.state of
 (
 1: fend_s
 2: zero  )
 -- end change state radiobutton
 )
 
on pickObject picked g do(
 local fstart = fromf.text as integer
 local fend = tof.text as integer
 local obj = g
 geo2houdini fstart fend obj
 )
-- end interface
)
-- MAIN
poly2h = newRollOutFloater "houdini exporter" 180 230
addRollout exportGeo_rollout poly2h rolledUp:false
-- END MAIN


Cogí un ejemplo y lo he modificado. Al ejecutarlo te pedirás que elijas un objeto, pero da igual, porque después hay un bucle que recorre toda la geometría. Tampoco importa si le dices si quieres o no animación.

Bueno, pues a ver si encuentras el error. Gracias mil!! :D  

BeRSeRKeR

 
Cita de: "Haddd"Sin embargo, no me funciona. Tengo una escena con 3 objetos. 2 de ellos están atachados y han creado un submaterial:

Atachados:Cubo(matID:1) y esfera(matID:2)

Rectángulo(MatID:1)

Como puedes ver, me está dando el mismo nº de MatID, cuando en realidad son materiales diferentes.
Mea culpa. En realidad, si el material es de tipo Multimaterial, el índice que te devuelve getFaceMatID no es para el array sceneMaterials sino para el array "material" del nodo en cuestión. Por ejemplo, imagínate que el nodo "nodo_actual" tenga un material de tipo Multimaterial y que las caras de dicho nodo tengan IDs 1 y 2. Para acceder al material de cada cara sería:

nodo_actual.material[1]
nodo_actual.material[2]


En cualquier caso, y como me apetecía aportar algo al motor éste que tenéis pensado desarrollar, he programado un MAXScript que exporta la escena de la misma forma que hace el plugin ASE de MAX. Evidentemente no da tanta información ni soporta animación pero lo importante sí está. He estado comparando la salida del plugin ASE y la de este script y son iguales por lo que supongo que está bien. También le he añadido soporte para canales de mapeado, de forma que el usuario puede escoger el canal a exportar. Eso sí, no he tenido en cuenta las conversiones MAX->D3D y los índices comienzan en 1 y no en 0 como ocurre en C/C++.

Pues nada más. El script es algo tocho para ponerlo aquí así que lo he subido a mi ftp. Lo puedes descargar de aquí. Verás que son dos archivos. Esto es así porque quería mantener el exportador lo más organizado posible. El script principal (el que tienes que ejecutar) es hadddMain.ms

Si tienes alguna duda pues aquí estoy. :)

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Haddd

 Genial, tu script me ha aclarado un montón de dudas y ya exporto casi correctamente. (ole)
Digo casi por que me he encontrado que la escena que estoy probando tiene materiaels Shell_material.

Pues cuando añado esta información al exportador, con esta línea:


else if (classOf mtl) == Shell_Material do (


Me da un error al evaluar el maxscript. (nooo)

¿Conoces el motivo?

BeRSeRKeR

 
Cita de: "Haddd"Pues cuando añado esta información al exportador, con esta línea:

else if (classOf mtl) == Shell_Material do (

Me da un error al evaluar el maxscript. (nooo)

¿Conoces el motivo?
Pues viendo sólo eso es complicado pero se me ocurre que tienes algo así:
Citarif (classOf mtl) == StandardMaterial then
(
    .....
)
else if (classOf mtl) == MultiMaterial do    <- ERROR
(
    .....
)
else if (classOf mtl) == Shell_Material do
(
    .....
)
cuando debería ser:
Citarif (classOf mtl) == StandardMaterial then
(
    .....
)
else if (classOf mtl) == MultiMaterial then    <- ASI ESTA BIEN
(
    .....
)
else if (classOf mtl) == Shell_Material do
(
    .....
)
Otra cosa no se me ocurre, porque lo que es el Shell_Material está bien.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Haddd

 
Bien, otro problema que he encontrado es con lo ssubmateriales. Resulta que los submateriales pueden estar formado por otros submateriales  :angry:

He hecho una función recursiva, pero no ha ido muy bien. Te pongo el código y la escena de prueba que estoy intentando exportar.

Archivo

A ver si puedo exportar ya esta barbaridad de escena. También me falta exportar el canal de lightmaps(que incluye la escena) , que todavía no lo he intentado.

Gracias por tu ayuda.. (ole)  

BeRSeRKeR

Cita de: "Haddd"También me falta exportar el canal de lightmaps(que incluye la escena) , que todavía no lo he intentado.
El canal de lightmaps se supone que es el canal de mapeado que tú especifiques por lo que en teoría deberías poder exportar las coordenadas de textura con el script que puse aquí. De todas formas a ver si esta noche le echo un vistazo.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Haddd


BeRSeRKeR

 Es que no sé realmente qué quieres hacer. Yo probé a exportar la escena con el script que escribí y excepto por el tema de que habían ciertos objetos que tenían un canal de mapeado distinto (los tuve que cambiar), la escena se exportó perfectamente. Bueno, menos los materiales Shell_Material que como no le dí soporte pues no los exporta enteros.

Y con respecto a los multimateriales dentro de multimateriales, ¿tiene sentido utilizar eso?. Es decir, tenemos un objeto que utiliza un multimaterial, y pongamos por caso que una de sus caras utiliza el material #1 que a su vez es otro multimaterial. ¿Qué sentido tiene?. ¿Cómo sabes cuál es el submaterial que tienes que aplicar a esa cara?.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Haddd

 No sé si tiene sentido, pero la escena que tengo sí que lo utiliza. Cosas de grafistas!!

La idea de la recursividad debería funcionar. ¿Sabes porqué no funciona en el exportador que yo cree ?






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.