PDA

Voir la version complète : Dessoudeur



César Vonc
01/11/2010, 16h15
Suite au sujet de cette discussion (http://frenchcinema4d.fr/showthread.php?71370-Dessouder-des-ar%EAtes), j'ai décidé de tenter de scripter un outil permettant de dessouder des sommets, avec un script Coffee.


Pour l'instant j'y arrive sans trop de mal, j'ajoute de nouveaux sommets en fonction de ceux sélectionnés et modifie l'attribution des points des polygones.



http://img266.imageshack.us/img266/7174/dessoudeur1.png


Le but étant également de dessouder à partir des arêtes sélectionnés, peut-on récupérer une sélection d'arêtes en script Coffee ?

J'ai encore un ou deux soucis à régler et je vous montre le script.

Aurety
01/11/2010, 16h44
:scared: génial !

2Mylent
01/11/2010, 16h49
Oui, génial et très utile! :thumbup:

human
01/11/2010, 16h54
bravo

César Vonc
01/11/2010, 18h47
Merci, j'ai également une autre question : comment paramètre-t-on l'annulation du script (Ctrl + Z) ? Car là, on dirait qu'il n'est pas pris en compte dans l'historique.


Voici le script qui dessoude les sommets uniquement, j'ai été surpris de voir que l'UVW en sortait indemne !



var doc = GetActiveDocument();
var op = doc->GetActiveObject();
if(!op) return;

var nbPolys = op->GetPolygonCount();
var nbPts = op->GetPointCount();


var selPts = op->GetPointSelection();
var nbSelPts = selPts->GetCount();
if (nbSelPts != 0)
{
var tabSelPts = new(array, nbPolys * 4); // ID du point
var tabSelPol = new(array, nbPolys * 4); // ID du poly
var tabSelPop = new(array, nbPolys * 4); // (abcd) du poly
var i;
var ii = 0;
for (i = 0 ; i < nbPolys ; i++)
{
if (selPts->IsSelected(op->GetPolygon(i)->a))
{
tabSelPts[ii] = op->GetPolygon(i)->a;
tabSelPol[ii] = i;
tabSelPop[ii] = "a";
ii++;
}
if (selPts->IsSelected(op->GetPolygon(i)->b))
{
tabSelPts[ii] = op->GetPolygon(i)->b;
tabSelPol[ii] = i;
tabSelPop[ii] = "b";
ii++;
}
if (selPts->IsSelected(op->GetPolygon(i)->c))
{
tabSelPts[ii] = op->GetPolygon(i)->c;
tabSelPol[ii] = i;
tabSelPop[ii] = "c";
ii++;
}
if ((selPts->IsSelected(op->GetPolygon(i)->d)) && ((op->GetPolygon(i)->c) != (op->GetPolygon(i)->d)) ) // Vérifie si le poly est un triangle.
{
tabSelPts[ii] = op->GetPolygon(i)->d;
tabSelPol[ii] = i;
tabSelPop[ii] = "d";
ii++;
}
}
if (ii > 1)
{
var vcPt = new (VariableChanged); if(!vcPt) return;
vcPt->Init(nbPts, nbPts + ii);
var j;
for (j = 0 ; j < ii ; j++)
{
var valid = op->MultiMessage(MSG_POINTS_CHANGED, vcPt);
op->SetPoint(nbPts + j, op->GetPoint(tabSelPts[j]));

var poly = op->GetPolygon(tabSelPol[j]);
if (tabSelPop[j] == "a")
poly->a = nbPts + j;
if (tabSelPop[j] == "b")
poly->b = nbPts + j;
if (tabSelPop[j] == "c")
poly->c = nbPts + j;
if (tabSelPop[j] == "d")
poly->d = nbPts + j;

op->SetPolygon(tabSelPol[j], poly);
op->Message(MSG_UPDATE);
}
CallCommand(12109); // Supprime les anciens points.
}
}

http://img208.imageshack.us/img208/1378/dessoudeur2.jpg


Ma question sur la récupération d'une sélection d'arêtes en Coffee reste d'actualité.

lolofedo
01/11/2010, 19h05
;) pas mal ça effectivement, ça peux toujours servir. Tu nous ferai ça en plug ? avec un petit icone ?

2Mylent
01/11/2010, 19h19
Désolé de ne pouvoir pas répondre à tes questions kpj, je débute avec C4D, et je ne rien connais à Coffee :blush:

D'ailleurs, ais-je Coffee sous R12 PRIME ? :confused1:

oli_d
01/11/2010, 20h29
Merci, j'ai également une autre question : comment paramètre-t-on l'annulation du script (Ctrl + Z) ? Car là, on dirait qu'il n'est pas pris en compte dans l'historique.


Dans la doc dans la classe BaseDocument tu as trois méthodes StartUndo(), AddUndo() et EndUndo() avec un exemple de code, teste de ce côté.


Ma question sur la récupération d'une sélection d'arêtes en Coffee reste d'actualité.


Je ne crois pas que l'on puisse directement récupérer les arrêtes, je crois que cela passe de toute façon par la sélection des points ...

César Vonc
01/11/2010, 22h19
Tu nous ferai ça en plug ? avec un petit icone ?
En script, dans l'onglet Module externe > Scipts personnalisés, donc avec une icône et une petite interface, oui !


Dans la doc dans la classe BaseDocument tu as trois méthodes StartUndo(), AddUndo() et EndUndo() avec un exemple de code, teste de ce côté.
D'accord, je vais aller voir de ce côté.


Je ne crois pas que l'on puisse directement récupérer les arrêtes, je crois que cela passe de toute façon par la sélection des points...
C'est bien ce que je craignais, tant pis, j'ai ma petite idée pour ne se servir que des sommets sélectionnés et en déduire les arêtes.


J'ajouterai une option pour éloigner les points dessoudés entre eux, si vous avez des idées particulières pour agrémenter ce script, n'hésitez pas.


J'aimerais bien également ajouter quelques images explicatives dans la fenêtre d'interface du script, mais il me semble que c'est faisable uniquement pour un module en C++ et non un simple script Coffee, non ?

lenogre
02/11/2010, 10h12
Ça peut être effectivement très utile. Bravo.

Jean-Laurent
02/11/2010, 11h16
J'aimerais bien également ajouter quelques images explicatives dans la fenêtre d'interface du script, mais il me semble que c'est faisable uniquement pour un module en C++ et non un simple script Coffee, non ?

Non, non. C'est faisable en Coffee.
Mais dans ce cas il faut que les images soient placées au bon endroit dans le dossier de ton script. Préciser l'endroit en chemin relatif il me semble etc ...

Il me semble aussi que l'image doit prendre place dans une user area du script, un truc du genre mais je n'en suis pas certain.
Il y a des exemples dans le SDK.

C'est très loin pour moi, donc je ne peux pas être plus précis, mais c'est faisable puisque je me souviens l'avoir fait dans une vie antérieure. ;)

xs_yann
02/11/2010, 11h43
http://www.xsyann.com/274/coffee/addbitmap#more-274

César Vonc
03/11/2010, 22h49
D'accord, merci, je regarderai ça (dommage que tu ne parles pas français, xs_yann).


En attendant j'ai un autre problème, je ne peux pas dessouder les arêtes uniquement avec une sélection de points...
Si j'ai une grille de points sélectionnés, rien ne m'indique quelles lignes dessouder.


Y a-t-il un moyen de récupérer les données de la propriété Normale en Coffee ?

Gyom
04/11/2010, 00h07
Mô si ... Il parle Francais mossieur XS_Yann ;)

xs_yann
04/11/2010, 10h57
En attendant j'ai un autre problème, je ne peux pas dessouder les arêtes uniquement avec une sélection de points...
Si j'ai une grille de points sélectionnés, rien ne m'indique quelles lignes dessouder.
Je ne suis pas sûr de comprendre.
Avec une sélection d'arêtes cela fonctionnerais ?
Avec les points tu peux peut-être te servir du nombres de points adjacents sélectionnés ?


Y a-t-il un moyen de récupérer les données de la propriété Normale en Coffee ?

Si tu parles du Normal Tag (Tnormal), oui.
C'est un VariableTag (regardes dans le SDK COFFEE comment faire pour accéder aux données).
Les données sont stockées sous la forme ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz.

César Vonc
04/11/2010, 13h56
Avec une sélection d'arêtes cela fonctionnerais ?
Avec les points tu peux peut-être te servir du nombres de points adjacents sélectionnés ?
C'est ce que je pensais, mais ce ne serait pas aussi précis qu'une sélection d'arêtes.



Si tu parles du Normal Tag (Tnormal), oui.
C'est un VariableTag (regardes dans le SDK COFFEE comment faire pour accéder aux données).
J'ai pourtant essayé de récupérer les données comme j'avais fait pour la propriété UVW, mais j'ai un message d'erreur avec la propriété Normale :


var prop = op->GetFirstTag(); // Je sélectionne ma propriété Normale
var infos = prop->GetData(); // Erreur... « Member not found ».

De même avec GetDataCount, j'ai la même erreur, je pige pas.



Ma propriété Normale est ajouté avec le module Add Normal Tag (http://skinprops.com/addnormals.php).

xs_yann
04/11/2010, 14h29
Aie, effectivement, tu as raison.

Le code suivant échoue :


var vtag = AllocVariableTag(Tnormal, 2);
println(vtag->GetDataCount());

alors que celui-ci fonctionne :


var vtag = AllocVariableTag(Tuvw, 2); // Tparticle, Tsegment, etc
println(vtag->GetDataCount());
:blink:

En Python cela fonctionne :


def main():
vt = c4d.VariableTag(c4d.Tnormal, 2)
print vt.GetDataCount()

Il te reste plus qu'a passer en Python (tu y gagneras). :P

César Vonc
04/11/2010, 15h36
Je vois.

J'ai donc télécharger Pyhton pour C4d 11.5 afin de retranscrire mon script actuel dans ce langage, mais ne connaissant rien au Python, je rencontre quelques soucis (je risque de venir vous emmerder souvent).

Voici mon avancement actuel, je vais essayer de traduire ligne par ligne, mais je me heurte déjà un problème.

Comment fait-on le « if (!op) return; » du Coffee, en Python ?


import c4d
from c4d import *

doc = c4d.documents.GetActiveDocument()
op = doc.GetActiveObject()

nbPolys = op.GetPolygonCount()
nbPts = op.GetPointCount()

xs_yann
04/11/2010, 16h26
Pas de souci, je devrais être là pour te répondre (sauf si c'est vraiment long).


if op is None:
return
;)

evites de faire 'from c4d import *' importe les modules dont tu as besoin 'from c4d import gui' 'from cd4 import gui, documents'

César Vonc
04/11/2010, 18h54
Hmm, j'ai peur que ce ne soit peine perdue, la version de Python pour C4d 11.5 est la version bêta (0.9.9983).

La syntaxe et certaines fonction ont du changer depuis, car j'obtiens une erreur de syntaxe si je colle ton petit bout de code dans mon script...

xs_yann
05/11/2010, 11h36
Hmm, j'ai peur que ce ne soit peine perdue, la version de Python pour C4d 11.5 est la version bêta (0.9.9983).

La syntaxe et certaines fonction ont du changer depuis, car j'obtiens une erreur de syntaxe si je colle ton petit bout de code dans mon script...

Là c'est toi qui a du mal t'y prendre. Mais tu as raison ton script n'est pas portable pour Py4D R11.5 étant donné que ce bout de code ne fonctionne pas en R11.5 :


import c4d

def main():
op = c4d.PolygonObject(2, 3)
op.ResizeObject(2) # R11.5 : 'TypeError: ResizeObject() takes no arguments (1 given)'

if __name__=='__main__':
main()

Si tu as vraiment besoin des normales, apparemment il faut soit que tu passe R12, soit tu peux les calculer a la main en COFFEE, soit recoder une fonction qui fait un "ResizeObject" en Python.

Voilà un début de traduction de ton script :


import c4d
from c4d import gui, documents

def main():
doc = documents.GetActiveDocument();
op = doc.GetActiveObject();
if op is None or op.GetType() != c4d.Opolygon:
gui.MessageDialog("You must select a polygon object")
return

nbPolys = op.GetPolygonCount();
nbPts = op.GetPointCount();

selPts = op.GetPointS();
nbSelPts = selPts.GetCount();
if nbSelPts != 0:
tabSelPts = [] # ID du point
tabSelPol = [] # ID du poly
tabSelPop = [] # (abcd) du poly
selected = selPts.GetAll(nbPts)
for i in range(nbPolys):
poly = op.GetAllPolygons()[i]
if selected[poly.a]:
tabSelPts.append(poly.a)
tabSelPol.append(i)
tabSelPop.append("a")
if selected[poly.b]:
tabSelPts.append(poly.b)
tabSelPol.append(i)
tabSelPop.append("b")
if selected[poly.c]:
tabSelPts.append(poly.c)
tabSelPol.append(i)
tabSelPop.append("c")
if selected[poly.d] and (poly.c != poly.d): # check triangle
tabSelPts.append(poly.d)
tabSelPol.append(i)
tabSelPop.append("d")

ii = len(tabSelPts)
if ii > 1:
doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)
op.ResizeObject(nbPts + ii)
polys = op.GetAllPolygons()
for j in range(ii):
op.SetPoint(nbPts + j, op.GetPoint(tabSelPts[j]))

poly = polys[tabSelPol[j]]
if tabSelPop[j] == "a":
poly.a = nbPts + j
if tabSelPop[j] == "b":
poly.b = nbPts + j
if tabSelPop[j] == "c":
poly.c = nbPts + j
if tabSelPop[j] == "d":
poly.d = nbPts + j

op.SetPolygon(tabSelPol[j], poly)
op.Message(c4d.MSG_UPDATE)
c4d.CallCommand(12109) # Supprime les anciens points.

if __name__=='__main__':
main()

Pas encore de 'BaseSelect.IsSelected' non plus en 11.5

Seb-bbl
05/11/2010, 12h47
Je vais peut-être dire une bêtise, mais pourquoi ne pas utiliser la démo R12 et le python qui y est intégré ?

xs_yann
05/11/2010, 14h47
Je vais peut-être dire une bêtise, mais pourquoi ne pas utiliser la démo R12 et le python qui y est intégré ?

Moi c'est ce que je fais, mais étant donné que kpj est en R11.5 je ne pense pas que cela lui serve de développer son plugin pour la R12.

César Vonc
05/11/2010, 23h54
Oh !

Ben dis donc, xs_yann, je ne t'en demandais pas tant, j'étais vraiment pas motivé à l'idée de retranscrire mon script en Python.

Ce serait plus simple si je passais à la version R12 de c4d, en effet.


En tout cas merci, je ne m'y attendais pas du tout, je vais pouvoir décortiquer tout ça et comprendre comment fonctionne le Python. Je vous tiens au courant.

PS : Tu as converti mon script en Python pour c4d 11.5 ou 12 ? Car je compte passer en version 12.

xs_yann
06/11/2010, 08h12
Pour la R12. Py4D R11.5 ne permet pas ResizeObject. Mais pour l'instant j'ai essayé de traduire ton script mot à mot, je ne suis pas sûr du fonctionnement.

César Vonc
07/11/2010, 01h37
Une question toute bête, mais qui n'empêche pas de me bloquer : comment accède-t-on aux coordonnées d'un point d'indice n, en Python ?

xs_yann
07/11/2010, 16h29
Une question toute bête, mais qui n'empêche pas de me bloquer : comment accède-t-on aux coordonnées d'un point d'indice n, en Python ?


op.GetAllPoints()[i] # [PointObject] op