Gestire mesh mappatura C#

Salve a tutti,

ho un problema che non riesco ad affrontare con C# per farmi un plug-in.

Avrei bisogno di sapere se è possibile gestire le coordinate uv di mappatura di una mesh, mi spiego meglio:

Uso un software esterno per mappare la mia mesh e dargli un uv a mia scelta, poi importo la mesh in rhino e voglio andare a “testare” le normali appartenenti a dei determinati punti della mesh utilizzando le coordinate uv. E’ possibile ?

Spero di essere stato chiaro, è un po’ complicato da spiegare.

Grazie in anticipo

Luca

Ciao Luca

Premetto che non ho uso meh e textures, quindi sono nuovo in queste cose … :blush:

Ma, spinto dalla curiosita’, ho cercato su RhinoCommon e ho visto questo
( Dalla proprieta’ TextureCoordinates di Mesh )

http://developer.rhino3d.com/api/RhinoCommon/html/T_Rhino_Geometry_Collections_MeshTextureCoordinateList.htm

Ho fatto un piccolo test con uno script e pare che questa lista contenga tante coppie di coordinate quanti sono i vertici della mesh.

Forse ti da’ le coordinate della texture corrispondenti ai vari vertici … adesso non riesco a scavare piu’ a fondo, sorry …

Se e’ cosi, credo che cercando i vertici vicini al valori uv che vuoi esaminare … magari interpolando … si possa risalire alla faccia della mesh in questione. … e quindi alla normale … forse :confused:

… O magari ho detto solo cavolate, come gia’ detto e’ un ambiente che purtroppo non frequento … :wink:

EDIT

Forse le facce non c’entrano, vedo che dovrebbero esserci direttamente le normali sui vertici …

Ciao Emilio,

innanzitutto grazie per la risposta.
Ho già provato tutti i comandi che ho trovato googlando, ma purtroppo nessuno di questi fa al caso mio, o forse non li uso correttamente. Mi servirebbe un modo per gestire i point3d e le normali sulla mesh come li gestisco sulle superfici attraverso PointAt(u,v) e NormalAt(u,v) ad un passo costante.

MeshTextureCoordinate di da le coordinate uv ai vertitci, il problema è che attraverso questi comandi non posso arrivare a gestire tutte le coordinate uv della mesh, almeno non direttamente.

Grazie mille

Luca

Certo, nemmeno io ho trovato niente di gia’ fatto.
Ma, volendo, si prova a farselo.

texture

Ho provato per il caso piu’ semplice:
Mesh senza triangoli, con texture singola, cioe’ non ripetuta sulla superficie.

Questo e’ lo script in Python di prova

import Rhino
import rhinoscriptsyntax as rs
import scriptcontext

def main():
  gob = Rhino.Input.Custom.GetObject()
  gob.SetCommandPrompt( 'Mesh ?' )
  gob.AcceptNothing( True )
  gob.Get()
  res = gob.Result()
  if res != Rhino.Input.GetResult.Object:
    return
  obref = gob.Object( 0 )
  mesh = obref.Mesh()
# ricava coordinate texture
  tcl = mesh.TextureCoordinates
# costruisce mesh ausiliaria con coordinate texture
  muv = mesh.DuplicateMesh()
  for ix in range( muv.Vertices.Count ):
    muv.Vertices.SetVertex( ix, tcl[ ix ].X, tcl[ ix ].Y, 0.0 )
# ciclo input valori U,V per normali
  while True:
    gop = Rhino.Input.Custom.GetPoint()
    gop.SetCommandPrompt( 'UV "point" ?' )
    gop.AcceptNothing( True )
    gop.Get()
    res = gop.Result()
    if res != Rhino.Input.GetResult.Point:
      break
# punto U,V,0 appartenente alla mesh ausiliaria
    pnt = gop.Point()
    if ( ( pnt.X < 0.0 ) or ( pnt.X > 1.0) or 
        ( pnt.Y < 0.0 ) or ( pnt.Y > 1.0 ) ):
      break
    pnt.Z = 0.0
# ricava il MeshPoint relativo dalla mesh ausiliaria
    mp = muv.ClosestMeshPoint( pnt, 0.001 )
# ricava la faccia, sempre dalla mesh ausiliaria
    facuv = muv.Faces[ mp.FaceIndex ]
    veruv = muv.Vertices
# disegna una superficie ausialiria sulla faccia (della mesh ausiliaria)
    suruv = rs.AddSrfPt( 
        [ veruv[ facuv.A ], veruv[ facuv.B ], 
        veruv[ facuv.C ], veruv[ facuv.D ] ] )
# ricava la posizione del punto cercato come U e V della superficie
# (normalizzata con Domain 0..1 , 0..1)
    fau, fav = rs.SurfaceClosestPoint( suruv, pnt )
    udom = rs.SurfaceDomain( suruv, 0 )
    vdom = rs.SurfaceDomain( suruv, 1 )
    fau /= ( udom[ 1 ] - udom[ 0 ] )
    fav /= ( vdom[ 1 ] - vdom[ 0 ] )
# ora riporta il tutto sulla mesh originale ...
    face = mesh.Faces[ mp.FaceIndex ]
    vert = mesh.Vertices
# disegna la superficie ausialiria sulla faccia della mesh originale
    sur = rs.AddSrfPt( 
        [ vert[ face.A ], vert[ face.B ], vert[ face.C ], vert[ face.D ] ] )
    udom = rs.SurfaceDomain( sur, 0 )
    vdom = rs.SurfaceDomain( sur, 1 )
# e riporta sulla mesh originale il punto con i valori U e V ricavati 
# dalla mesh ausiliaria
    pnt3d = rs.EvaluateSurface( sur, 
        fau * ( udom[ 1 ] - udom[ 0 ] ), fav * ( vdom[ 1 ] - vdom[ 0 ] ) )
# ( disegna il punto )
    rs.AddTextDot( '%g,%g' % ( pnt.X, pnt.Y ), pnt3d )
# dal punto ricava il MeshPoint sulla mesh originale
    mp3d = mesh.ClosestMeshPoint( pnt3d, 0.1 )
# dal MeshPoint ricava la normale
    vec = mesh.NormalAt( mp3d )
# disegna la normale
    gid = scriptcontext.doc.Objects.AddLine(
        Rhino.Geometry.Line( pnt3d, vec * 50 ) )
    rob = Rhino.DocObjects.ObjRef( gid ).Object()
    att = rob.Attributes
    att.ObjectDecoration = Rhino.DocObjects.ObjectDecoration.EndArrowhead
    scriptcontext.doc.Objects.ModifyAttributes( rob, att, True )
  
main()

Selezioni la mesh e poi, nel ciclo di input dei valori U e V, scrivi U e V come se fossero X e Y di un punto, ad esempio digiti “0.5,0.6” … e cosi’ via

Lo script costruisce una mesh ausiliaria con le coordinate dei vertici corrispondenti alle coordinate della texture.
Su questa mesh ausialiria, ad esempio, il punto U=0.2, V=0.3 si trova in X=0.2,Y=0.3,Z=0
Cosi’, avendo un punto 3D e una mesh 3D (veramente 2D) su cui lavorare, ricava la faccia e, tramite una superficie ausiliaria corrispondente alla faccia, ricava la posizione del punto cercato relativa alla faccia.
Conoscendo la posizione sulla faccia, tramite un’altra superficie ausiliaria sulla mesh originale riporta il punto sulla mesh originale.
Dal punto ricava la normale.

Lo script e’ solo un test, non cancella nemmeno le varie cose che disegna.

E’ solo un modo, credo ce ne siano certamente altri per attaccare il problema.
E per casi meno semplici, la cosa si complica … si cercheranno altre vie … :slight_smile:

Ciao

texture2

OK … semplificato lo script usando le ‘coordinate baricentriche’ del MeshPoint.
Basta ricavarle dalla mesh ausiliaria e riportarle su quella originale. :slight_smile:

 import Rhino
import rhinoscriptsyntax as rs
import scriptcontext

def main():
  gob = Rhino.Input.Custom.GetObject()
  gob.SetCommandPrompt( 'Mesh ?' )
  gob.AcceptNothing( True )
  gob.Get()
  res = gob.Result()
  if res != Rhino.Input.GetResult.Object:
    return
  obref = gob.Object( 0 )
  mesh = obref.Mesh()
# ricava coordinate texture
  tcl = mesh.TextureCoordinates
# costruisce mesh ausiliaria con coordinate texture
  muv = mesh.DuplicateMesh()
  for ix in range( muv.Vertices.Count ):
    muv.Vertices.SetVertex( ix, tcl[ ix ].X, tcl[ ix ].Y, 0.0 )
# ciclo input valori U,V per normali
  while True:
    gop = Rhino.Input.Custom.GetPoint()
    gop.SetCommandPrompt( 'UV "point" ?' )
    gop.AcceptNothing( True )
    gop.Get()
    res = gop.Result()
    if res != Rhino.Input.GetResult.Point:
      break
# punto U,V,0 appartenente alla mesh ausiliaria
    pnt = gop.Point()
    if ( ( pnt.X < 0.0 ) or ( pnt.X > 1.0) or 
        ( pnt.Y < 0.0 ) or ( pnt.Y > 1.0 ) ):
      break
    pnt.Z = 0.0
# ricava il MeshPoint relativo dalla mesh ausiliaria
    mp = muv.ClosestMeshPoint( pnt, 0.001 )
# ricava la faccia, sempre dalla mesh ausiliaria
    facuv = muv.Faces[ mp.FaceIndex ]
    veruv = muv.Vertices
# ricava coordinate baricentriche
    tt = mp.T
# ricava il punto sulla mesh originale dalle coordinate baricentriche
    pnt3d = mesh.PointAt( mp.FaceIndex, tt[ 0 ], tt[ 1 ], tt[ 2 ], tt[ 3 ] )
# ( disegna il punto )
    rs.AddTextDot( '%g,%g' % ( pnt.X, pnt.Y ), pnt3d )
# dal punto ricava il MeshPoint sulla mesh originale
    mp3d = mesh.ClosestMeshPoint( pnt3d, 0.1 )
# dal MeshPoint ricava la normale
    vec = mesh.NormalAt( mp3d )
# disegna la normale
    gid = scriptcontext.doc.Objects.AddLine(
        Rhino.Geometry.Line( pnt3d, vec * 50 ) )
    rob = Rhino.DocObjects.ObjRef( gid ).Object()
    att = rob.Attributes
    att.ObjectDecoration = Rhino.DocObjects.ObjectDecoration.EndArrowhead
    scriptcontext.doc.Objects.ModifyAttributes( rob, att, True )
  
main()