Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 15 von 16

Thema: Topologie vereinheitlichen

  1. #1

    Standard Topologie vereinheitlichen

    Hallo,

    vielleicht hat mir ja einer von euch einen passenden Tipp.

    Folgendes Problem:


    Ich habe hier drei Meshes von Köpfen vorliegen, welche rein optisch identische Topologien aufweisen. Leider stimmen aber deren Punkt-, resp. Polygonstrukturen nicht überrein. Punkt x liegt nicht bei allen Meshes an der gleichen 'Stelle' in bezug auf das Mesh, Polygon y besteht je nach Kopf aus unterschiedlichen Punktindices.

    Das wäre aber mein Ziel, denn nur so können die Köpfe z.B. untereinander gemorpht werden.

    Gibt es in C4D einen Funktion/einen Workflow, um dies zu erreichen?
    Nur ungern würde ich dies manuell durch 'snappen' der Punkte eines Meshes auf die anderen erreichen, da es durchaus vorkommen könnte, dies noch öfters machen zu müssen.

    Grüße
    Peter
    Angehängte Grafiken Angehängte Grafiken  

    Nicht möglich! 0 Nicht möglich!

  2. #2
    trickfilmer Avatar von moebius
    Registriert seit
    19.08.2010
    Ort
    CH - St.Gallen
    Beiträge
    3.995
    Software
    MSA

    Standard

    Erinnert mich an den Thread. Hilft vllt irgendwie...

    http://c4dnetwork.com/board/threads/...highlight=vamp

    Nicht möglich! 0 Nicht möglich!


    Win10 - Intel Xeon E5-2650V3, 10 Cores, 2.3-3.0 GHz - Asus GTX 980ti STRIX, 6 GB DDR5 - 32 GB Ram - C4D MSA - Octane - Adobe CC Sklave


  3. #3

    Standard

    Hi Simon,

    ähnlich scheint das Problem zu sein, nur dass bei mir auch die Punktposition nicht übereinstimmen. Schaut für mich nicht nach einem Fall für 'VAMP' aus.
    Werde ich heute Abend trotzdem genauer anschauen.

    Vermutlich werde ich eine Meshanalyse anstellen müßen, um die Liste der Punkte eines Meshes auf die topologisch identischen Punkte des anderen Meshes zu mappen. Wenn nur die 'neighbor'-Klasse nicht so unhandlich wär

    Grüße
    Peter

    Nicht möglich! 0 Nicht möglich!

  4. #4
    Generalist Avatar von mp5gosu
    Registriert seit
    14.08.2006
    Ort
    Hamburg
    Beiträge
    2.713
    Software
    MSA

    Standard

    Du könntest einen der Köpfe klonen und auf einen anderen projizieren. Das bringt aber vielleicht etwas Nacharbeiten mit sich.

    Nicht möglich! 0 Nicht möglich!

  5. #5
    I break together Avatar von tillgiermann
    Registriert seit
    03.04.2013
    Ort
    Dresden
    Beiträge
    1.392
    Software
    MSA

    Standard

    Leichter wäre es gewesen, die zwei rechten Köpfe von Anfang an als Morphtargets zu bauen, mit der Ausgangsform des linken Kopfes.
    Dann hättest du eine Geometrie mit drei verschiedenen Shapes zum überblenden. Im Nachhinein ist das natürlich etwas mehr Arbeit, wäre aber mMn die simpelste Variante.

    Hast du es schon mal mit dem Pose Morph Tag und einem externen Ziel bei "Weitergehndes" versucht?

    Nicht möglich! 0 Nicht möglich!
    "Don´t wake me for the end of the world unless it has good special effects." Roger Zelazny

  6. #6
    trickfilmer Avatar von moebius
    Registriert seit
    19.08.2010
    Ort
    CH - St.Gallen
    Beiträge
    3.995
    Software
    MSA

    Standard

    Warum nicht gleich mit angeschaltetem Punkte-Snapping den einen Kopf in den andern ummodellieren? Sind ja nicht sooo viele Punkte zum rumschupsen und symmetrisch sind sie auch noch

    Nicht möglich! 0 Nicht möglich!


    Win10 - Intel Xeon E5-2650V3, 10 Cores, 2.3-3.0 GHz - Asus GTX 980ti STRIX, 6 GB DDR5 - 32 GB Ram - C4D MSA - Octane - Adobe CC Sklave


  7. #7

    Standard

    Projizieren kann in gewissen Fällen (@ mp5gosu) vielleicht ein erster Schritt sein. Das manuelle snappen auf das 'Referenzmesh' bleibt einem aber nicht erspart.
    Und da hat 'moebius' natürlich recht. Das 'Ummodellieren' eines Meshes auf das andere ist in diesem Fall auch nicht der große Aufwand.

    Da ich im Moment erst dran bin eine Standardtopologie für ein größeres Projekt zu entwickeln, wird es sicher auch weiterhin zu Änderungen am Mesh kommen, welche in den verschiedenen Morphologien nachgeführt werden müssen, um sie auch dort testen zu können.
    Letzlich geht es bei meinem Projekt dann nicht nur um drei Charaktere, sondern um ein vielfaches.

    Dies relativiert auch 'tillgiermann's an sich durchaus richtige Bemerkung. Nur liegt hier der Fall etwas anders. Wüsste ich jetzt schon wie das Mesh aussehen muss, so würde ich das selbstredend auch gleich so machen.

    Dann werde ich mich wohl mal etwas ins Python-SDK vertiefen, und mich mit der Neighbor-Klasse beschäftigen.

    Grüße
    Peter

    Nicht möglich! 0 Nicht möglich!

  8. #8
    Erfahrener Benutzer Avatar von Salamander
    Registriert seit
    15.11.2008
    Ort
    Hamburg
    Beiträge
    4.629
    Software
    MSA

    Standard

    Mich wundert sowieso, dass du mal eine Frage hast. Du bist doch der Mann für die Antworten.

    Nicht möglich! +4 Nicht möglich!

  9. #9

    Standard

    So wie's im Moment ausschaut, werde ich vermutlich eh versuchen, meine Frage in Form eines kleinen Scripts selber zu lösen.

    Nicht möglich! 0 Nicht möglich!

  10. #10
    I break together Avatar von tillgiermann
    Registriert seit
    03.04.2013
    Ort
    Dresden
    Beiträge
    1.392
    Software
    MSA

    Standard

    An dem Script wäre ich dann durchaus interessiert

    Nicht möglich! 0 Nicht möglich!
    "Don´t wake me for the end of the world unless it has good special effects." Roger Zelazny

  11. #11

    Standard

    So, dann melde ich mich mal wieder zurück.
    Habe mir in der Zwischenzeit ein Skript zusammengestrickt, welches mir die Punkt- und Polygonreihenfolgen eines Objektes an ein topologisch identes Objekt anpasst.


    Bei den im eingefügten Bild sichtbaren Meshs übernimmt Mesh 'A' z.B. die Nummerierung der Punkte und Polygone von Mesh 'B'.

    Auch wenn das Skript für den 'Hausgebrauch' erstellt wurde, so hänge ich trotzdem hier mal den Code an.
    Beschreibung und Bedienungsanleitung ist im Skript zu finden.
    Vielleicht probiert der Eine oder Andere das Skript ja netterweise aus und gibt eine kurze Rückmeldung, ob es auch erwartungsgemäß funktioniert.

    Code:
    import c4d
    from c4d import gui
    
    
    polygons_calculated = 0
    
    
    """
    --------------------------------------------------------------------------------------
    Skript zum Synchronisieren der Punkt- und Polygonindizes
    von zwei Polygonobjekten mit identischer Topologie aber unterschiedlicher Punkt- und
    Polygonreihenfolgen.
    --------------------------------------------------------------------------------------
    v01-01:
    Korrektur im Algorithmus für die Markierung der abzuarbeitenden Polygone. Fälschlicherweise
    wurden Polygone mehrfach markiert. Nach einer entsprechenden Anpassung ist das Skript nun 
    um ein vielfaches schneller.
    
    
    Peter Notz (nophoto)
    2017-10-16
    
    
    
    
    Nach dem Ausführen des Skripten sind die Punkt- und Polygonstrukturen der beiden
    Objekte identisch.
    
    
    
    
    Bedienung:
    ----------
    Sowohl im zu bearbeitenden, als auch im Referenzobjekt muss jeweils genau ein Polygon
    und ein Punkt ausgewählt sein.
    Wobei im Referenzobjekt das dem im zu bearbeitenden Objekte selektierten Polygon topo-
    logisch entsprechende Polygon selektiert sein muss.
    
    
    Die selektierten Punkte müssen sich ebenfalls topologisch entsprechen und zusätzlich zu 
    den selektierten Polygonen gehören.
    
    
    Zusätzlich müssen beide Objekte im Objektmanager ausgewählt sein. Die Reihenfolge der
    Auswahl bestimmt, welches der Objekte bearbeitet wird und welches als Referenzobjekt 
    dient. Das als erstes ausgewählte Objekt wird bearbeitet, das zweite dient als Referenz.
    
    
    
    
    Bedingungen:
    ------------
    Die Polygonobjekte dürfen keine Ngons enthälten. Dreiecke sind jedoch erlaubt.
    Die Normalen müssen ausgerichtet und bei beiden Objekten in die gleiche Richtung zeigen.
    Die Objekte sollten 'Optimiert' sein.
    Die Objekte dürfen nur aus einem zusammenhängenden Bereich bestehen.
    
    
    
    
    Bemerkung:
    ----------
    Die Übereinstimmung der Topologie der beiden Objekte wird durch das Skript nicht überprüft.
    Ebenso wird auch die Plausibilität der nötigen Punkt-, Polygon- und Objektauswahlen nicht
    geprüft.
    
    
    Der Code ist nicht optimiert und soll auch keineswegs als Beispiel für einen guten Programmier-
    stil dienen.
    Es ging lediglich darum, ein funktionierendes Skript zu erstellen. Ebenso ist die Kommentierung
    noch sehr lückenhaft.
    """
    
    
    def GetRefPolypoints(o_src, i_srcpoly, i_srcpoint, o_ref, i_refpoly, i_refpoint):
        
        srcpoly = o_src.GetPolygon(i_srcpoly)
        src_vertexnum = srcpoly.Find(i_srcpoint)
        
        refpoly = o_ref.GetPolygon(i_refpoly)
        ref_vertexnum = refpoly.Find(i_refpoint)
        
        polygonvertices = [refpoly.a, refpoly.b, refpoly.c, refpoly.d]
        
        if refpoly.c != refpoly.d: # Es handelt sich um ein Quad
            
            offset =  (ref_vertexnum - src_vertexnum)%4
            
            if    offset == 0:
                return refpoly.a, refpoly.b, refpoly.c, refpoly.d
            elif  offset == 1:
                return refpoly.b, refpoly.c, refpoly.d, refpoly.a
            elif  offset == 2:
                return refpoly.c, refpoly.d, refpoly.a, refpoly.b
            elif  offset == 3:
                return refpoly.d, refpoly.a, refpoly.b, refpoly.c
            
        else: # Es handelt sich um ein Tri
            
            if src_vertexnum == 0:
                
                if ref_vertexnum == 0:
                    return refpoly.a, refpoly.b, refpoly.c, refpoly.c
                elif ref_vertexnum == 1:
                    return refpoly.b, refpoly.c, refpoly.a, refpoly.a
                else:
                    return refpoly.c, refpoly.a, refpoly.b, refpoly.b
                
            elif src_vertexnum == 1:
                
                if ref_vertexnum == 0:
                    return refpoly.c, refpoly.a, refpoly.b, refpoly.b
                elif ref_vertexnum == 1:
                    return refpoly.a, refpoly.b, refpoly.c, refpoly.c
                else:
                    return refpoly.b, refpoly.c, refpoly.a, refpoly.a
                
            else:
                
                if ref_vertexnum == 0:
                    return refpoly.b, refpoly.c, refpoly.a, refpoly.a
                elif ref_vertexnum == 1:
                    return refpoly.c, refpoly.a, refpoly.b, refpoly.b
                else:
                    return refpoly.a, refpoly.b, refpoly.c, refpoly.c
    
    
        
    
    
    
    
    def main():
        global polygons_calculated
        
        #c4d.CallCommand(13957, 13957) # Clear Console
        
        osel = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_SELECTIONORDER | c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
        if len(osel) != 2: return
        
        o_src = osel[0] # Objekt
        o_ref = osel[1] # Referenz-Objekt
        
        #print "Objekte definiert"
        
        src_pointcount = o_src.GetPointCount()
        src_polygoncount = o_src.GetPolygonCount()
        
        ref_pointcount = o_ref.GetPointCount()
        ref_polygoncount = o_ref.GetPolygonCount()
        
        point_map = [-1]*src_pointcount
        polygon_map = [-1]*src_polygoncount
        
        """ Vorbereiten der Startauswahl """
       
        src_bs_point = o_src.GetPointS()
        if src_bs_point.GetCount() != 1: return
        src_pointsel = src_bs_point.GetAll(src_pointcount)
        i_src_point = src_pointsel.index(1)
        #print "src_pointsel:", i_src_point
        
        src_bs_polygon = o_src.GetPolygonS()
        if src_bs_polygon.GetCount() != 1: return
        src_polygonsel = src_bs_polygon.GetAll(src_polygoncount)    
        i_src_polygon = src_polygonsel.index(1)
        #print "src_polygonsel:", i_src_polygon
        
        ref_bs_point = o_ref.GetPointS()
        if ref_bs_point.GetCount() != 1: return
        ref_pointsel = ref_bs_point.GetAll(ref_pointcount)
        i_ref_point = ref_pointsel.index(1)
        #print "ref_pointsel:", i_ref_point
        
        ref_bs_polygon = o_ref.GetPolygonS()
        if ref_bs_polygon.GetCount() != 1: return
        ref_polygonsel = ref_bs_polygon.GetAll(ref_polygoncount)
        i_ref_polygon = ref_polygonsel.index(1)
        #print "ref_polygonsel:", i_ref_polygon
        
        """ Definieren der Liste mit den markierten Polygonen """
        mark = []
        mark.append({"src_pt": i_src_point, "src_pg": i_src_polygon, "ref_pt": i_ref_point, "ref_pg": i_ref_polygon})
        
        """ Anlegen der Neighbor-Klassen """
        src_nbr = c4d.utils.Neighbor()
        src_nbr.Init(o_src)
        
        ref_nbr = c4d.utils.Neighbor()
        ref_nbr.Init(o_ref)
        
        
        """ Abarbeiten der Topologie """
        while len(mark) > 0:
            
            #print "Anzahl der markierten Polygone:", len(mark)
            #print mark
            
            # Bestimmen der korrespondierenden Punktvertices des aktuellen Polygons...
            m = mark.pop(0)
            res = GetRefPolypoints(o_src, m["src_pg"], m["src_pt"], o_ref, m["ref_pg"], m["ref_pt"])
        
            vadr = o_src.GetPolygon(m["src_pg"])
            
            point_map[vadr.a] = res[0]
            point_map[vadr.b] = res[1]
            point_map[vadr.c] = res[2]
            point_map[vadr.d] = res[3]
            
            polygon_map[m["src_pg"]] = m["ref_pg"]
            polygons_calculated += 1
            
            # Bestimmen der benachbarten Polygone und ablegen dieser in der 'mark'-Liste...
            
            if vadr.c != vadr.d: # Quad...
                src = src_nbr.GetNeighbor(vadr.a, vadr.b, m["src_pg"])
                ref = ref_nbr.GetNeighbor(point_map[vadr.a], point_map[vadr.b], m["ref_pg"])
                if src >= 0 and polygon_map[src] == -1:
                    polygon_map[src] = -2
                    mark.append({"src_pt": vadr.a, "src_pg": src, "ref_pt": point_map[vadr.a], "ref_pg": ref})
                
                src = src_nbr.GetNeighbor(vadr.b, vadr.c, m["src_pg"])
                ref = ref_nbr.GetNeighbor(point_map[vadr.b], point_map[vadr.c], m["ref_pg"])
                if src >= 0 and polygon_map[src] == -1:
                    polygon_map[src] = -2
                    mark.append({"src_pt": vadr.b, "src_pg": src, "ref_pt": point_map[vadr.b], "ref_pg": ref})
                
                src = src_nbr.GetNeighbor(vadr.c, vadr.d, m["src_pg"])
                ref = ref_nbr.GetNeighbor(point_map[vadr.c], point_map[vadr.d], m["ref_pg"])
                if src >= 0 and polygon_map[src] == -1:
                    polygon_map[src] = -2
                    mark.append({"src_pt": vadr.c, "src_pg": src, "ref_pt": point_map[vadr.c], "ref_pg": ref})
                
                src = src_nbr.GetNeighbor(vadr.d, vadr.a, m["src_pg"])
                ref = ref_nbr.GetNeighbor(point_map[vadr.d], point_map[vadr.a], m["ref_pg"])
                if src >= 0 and polygon_map[src] == -1:
                    polygon_map[src] = -2
                    mark.append({"src_pt": vadr.d, "src_pg": src, "ref_pt": point_map[vadr.d], "ref_pg": ref})
                    
            else: # Tri...
                src = src_nbr.GetNeighbor(vadr.a, vadr.b, m["src_pg"])
                ref = ref_nbr.GetNeighbor(point_map[vadr.a], point_map[vadr.b], m["ref_pg"])
                if src >= 0 and polygon_map[src] == -1:
                    polygon_map[src] = -2
                    mark.append({"src_pt": vadr.a, "src_pg": src, "ref_pt": point_map[vadr.a], "ref_pg": ref})
                
                src = src_nbr.GetNeighbor(vadr.b, vadr.c, m["src_pg"])
                ref = ref_nbr.GetNeighbor(point_map[vadr.b], point_map[vadr.c], m["ref_pg"])
                if src >= 0 and polygon_map[src] == -1:
                    polygon_map[src] = -2
                    mark.append({"src_pt": vadr.b, "src_pg": src, "ref_pt": point_map[vadr.b], "ref_pg": ref})
                
                src = src_nbr.GetNeighbor(vadr.c, vadr.a, m["src_pg"])
                ref = ref_nbr.GetNeighbor(point_map[vadr.c], point_map[vadr.a], m["ref_pg"])
                if src >= 0 and polygon_map[src] == -1:
                    polygon_map[src] = -2
                    mark.append({"src_pt": vadr.c, "src_pg": src, "ref_pt": point_map[vadr.c], "ref_pg": ref})
                    
            
        #print point_map
        #print polygon_map
        
        doc.StartUndo()
        doc.AddUndo(c4d.UNDOTYPE_CHANGE, o_src)
        
        points = o_src.GetAllPoints()
        ref_tpolygon = o_ref.GetTag(c4d.Tpolygon)
        if ref_tpolygon:
            src_tpolygon = ref_tpolygon.GetClone()
            
            for i in xrange(o_src.GetPointCount()):
                o_src.SetPoint(point_map[i], points[i])
                
            o_src.InsertTag(src_tpolygon)
            o_src.Message(c4d.MSG_UPDATE)
            
        doc.EndUndo()
            
        c4d.EventAdd()
        
        #print "polygons_calculated", polygons_calculated
            
    
    
    if __name__=='__main__':
        main()
    Grüße
    Peter
    Angehängte Grafiken Angehängte Grafiken  

    Nicht möglich! +5 Nicht möglich!
    Geändert von nophoto (16.10.2017 um 22:46 Uhr) Grund: Korrigierten, schnelleren Code eingefügt

  12. #12
    trickfilmer Avatar von moebius
    Registriert seit
    19.08.2010
    Ort
    CH - St.Gallen
    Beiträge
    3.995
    Software
    MSA

    Standard

    Du bist doch irgendwie verrückt.
    Willst nicht mal ein Screencast aufnehmen, wie du so an Codegeschreibsel herangehst? Na? :-)

    Nicht möglich! 0 Nicht möglich!


    Win10 - Intel Xeon E5-2650V3, 10 Cores, 2.3-3.0 GHz - Asus GTX 980ti STRIX, 6 GB DDR5 - 32 GB Ram - C4D MSA - Octane - Adobe CC Sklave


  13. #13
    black nick is beautiful. Avatar von Cinemike
    Registriert seit
    29.10.2008
    Ort
    lebt schon immer hier
    Beiträge
    5.716
    Software
    MSA

    Standard

    Zitat Zitat von moebius Beitrag anzeigen
    Du bist doch irgendwie verrückt.
    Willst nicht mal ein Screencast aufnehmen, wie du so an Codegeschreibsel herangehst? Na? :-)
    Mit zugeschalteter Raumkamera - ich will die Kaffeetassen fliegen sehen!

    Nicht möglich! 0 Nicht möglich!
    Benutzte Software: C4D R18 Studio oder so

    Niveau sieht nur von unten betrachtet wie Arroganz aus.

  14. #14

    Standard

    Zitat Zitat von moebius Beitrag anzeigen
    Willst nicht mal ein Screencast aufnehmen, wie du so an Codegeschreibsel herangehst? Na? :-)
    Zitat Zitat von Cinemike Beitrag anzeigen
    Mit zugeschalteter Raumkamera - ich will die Kaffeetassen fliegen sehen!
    Ich stell mir das ziemlich unspektakulär vor. Auch wenn ich meist nicht sehr strukturiert ans programmieren der kleinen Helferlein gehe, kommt vor dem eigentlichen coden sehr wohl eine mehr oder weniger lange Phase des (wenn man so sagen will) Denkens.
    Das kann auch, wie Cinemike ganz treffend gemutmaßt hat, mal beim Abwasch sein.


    Ich habe übrigens einen korrigierten Code in meinem Beitrag weiter oben eingefügt. Irgendwie wollte ich nicht hinnehmen, dass das Skript bei meinen Meshs mit nur 231 Polygonen auf meinem Rechner fast eine Minute für's Aufräumen braucht!
    Effektiv wurde im ersten Skript die Liste der vorgemerkten Polygone falsch geführt, so dass jedes Polygon mehrmals abgearbeitet wurde.
    Nach der Anpassung des Codes braucht das Skript bei den gleichen Testköpfen nur doch knapp 2ms.

    Für mich genug Erfolgselebnis für heute.

    Grüße
    Peter

    Nicht möglich! +4 Nicht möglich!

  15. #15
    DIGITAL-CONNECTOR Avatar von kirby
    Registriert seit
    28.06.2006
    Ort
    Berlin
    Beiträge
    240
    Software
    MSA

    Standard

    Zitat Zitat von mp5gosu Beitrag anzeigen
    Du könntest einen der Köpfe klonen und auf einen anderen projizieren. Das bringt aber vielleicht etwas Nacharbeiten mit sich.
    das müßte doch funktionieren > also einen kopf nehmen + eine shrink-wrap deformer zuweisen > als ziel für den shrinkwrap > den zweiten kopf nehmen. siehe c4d manual shrink-wrap deformer > das kannst du dann sogar also poses im posemorph speichern und die miteinander abmischen und so auch für den dritten, vierten, etc. kopf....oder irre ich mich irgendwo...ich denke eher nicht.

    > mp5gosu hat genau den richtigen Ansatz grob geschildert, nur seine Erklärungen/Vorgehensweise ist eben lediglich nur ganz grob angerissen und eben sehr wortkarg geschildert....aber ich stimme dem Ansatz definitv zu...

    ..scripte dafür programmieren > finde ich klasse, aber das ist wie mit mit Kanonenkugeln auf Spatzen geschossen, da es soviel einfacher geht.....

    ..das ganze Thema fällt auch in den Bereich Retopo was ja auch zum Großteil in C4D mit dem Shrink-Wrap-Deformer gemacht wird....aber hier eben um die Topologie auf ein Mesh in unterschidlichen Morphs zu speichern.....das geht so genau auch .... siehe auch mal youtube - shrinkwrap-deformer + c4d retopology....

    Nicht möglich! 0 Nicht möglich!
    Geändert von kirby (17.10.2017 um 04:49 Uhr)
    Wenn man lange genug sucht wird man in der Regel auch belohnt werden...

    www.DIGITAL-CONNECTOR.com

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •