Page 1 sur 2

creation d'une ligne 3D?? ****[RESOLUT]****

Publié : dim. 10/févr./2008 18:10
par Fortix
Salutation,

Actuellement je cherche un moyen pour relier par une ligne deux points de coordonnés xyz dans un espace 3D, j'éssais de faire des petites bricoles en redimentionnant un mesh cube de base de telle façon qu'il s'étire d'un point vers l'autre, mais c'est très compliqué et celà charge le code,

j'ais pensé réutilliser la procedure de Tmyke DM_createline mais maleureusement il fonctionne uniquement avec les autres composants de DM

donc, avez vous une solution ou une alternative à me proposer, svp? :oops:

merci :D

Publié : dim. 10/févr./2008 18:22
par Anonyme
Sans le savoir , tu t'attaques un un moteur 3D :D

je te rassure , c'est relativement simple.

- Tu stockes tes coordonnées 3D
- Tu Transforme les coordonnées 3D en 2D (projection)
- Tu affiches les coordonnées projetées.

La formule de projection est :
2Dx= (POINT3Dx*255) / (POINT3Dz+150) + SCREEN_W/2
2Dy= (POINT3Dy*255) / (POINT3Dz+150) + SCREEN_H/2
joue avec les 255, 150 , pour changer le fov ( j'ai pas de formule pour ca ^^ )

Publié : dim. 10/févr./2008 18:34
par Fortix
tu veux parler d'un "StartDrawing(ScreenOutput())"
avec une procedure qui reconvertit les coordonnés 3D en 2D en permanance!

bien, figure toi que j'ais pensé à cette solution moi aussi, mais j'ais laissé tombé parce que tout simplement je n'ais pas pus trouver le résonnemant
de ce system là, de plus le sujet doit bouger dynamiquement dans l'espace 3D et celà risque de compliquer les choses :?


en fait, pourquoi"+ SCREEN_W/2 " et "SCREEN_H/2 "?

Publié : dim. 10/févr./2008 18:48
par Le Soldat Inconnu
Voila un exemple :

Passage d'une coordonnée 3D vers un écran 2D, avec prise en charge de la perspective

(c'est pour un écran de veille alors ne bouge pas la souris)

Code : Tout sélectionner

; Auteur : Le Soldat Inconnu
; Version de PB : 3.90
;
; Explication du programme :
; Dessiner un cube filaire en 3D avec de la perspective

#TailleX = 1024
#TailleY = 768

#Couleur = $E5A974

#Cube = 175 ; Taille du cube
#Echo = 8 ; Nombre d'écho
#Echo_Espacement = 1 ; Espacement entre chaque écho

#VitesseMax = 70
#VitesseMin = 350
#VitesseEvolution = 20

Structure Point3D
  x.f ; Coordonnée X
  y.f ; Coordonnée Y
  z.f ; Coordonnée Z
  p.f ; Facteur pour la perspective
EndStructure

#Perspective = 600 ; Intensité de la perspective

Procedure XYFrom3D(x.f, y.f, z.f, ax.f, ay.f, az.f, XYZ)
  ; x, y, z : position de l'objet
  ; ax, ay, az : angle de rotation du point sur l'axe x, y et z, pour avoir un repère 3D décalé par rapport au repère de l'écran
  
  Protected x2.f, y2.f, z3.f, Coord.Point3D
  
  ; Rotation sur l'axe Z
  x2 = x * Cos(az) - y * Sin(az)
  y2 = x * Sin(az) + y * Cos(az)
  ; z2 = z
  ; Debug StrF(x2) + " , " + StrF(y2) + " , " + StrF(z)
  
  ; Rotation sur l'axe X
  ; x3 = x2
  Coord\y = y2 * Cos(ax) - z * Sin(ax)
  z3 = y2 * Sin(ax) + z * Cos(ax)
  ; Debug StrF(x2) + " , " + StrF(Coord\y) + " , " + StrF(z3)
  
  ; Rotation sur l'axe Y
  Coord\z = z3 * Cos(ay) - x2 * Sin(ay)
  Coord\x = z3 * Sin(ay) + x2 * Cos(ay)
  ; y4 = y3
  ; Debug StrF(Coord\x) + " , " + StrF(Coord\y) + " , " + StrF(z3)
  
  ; Prise en compte de la perspective
  Coord\p = 1 + Abs(Coord\z) / #Perspective
  If Coord\z < 0
    Coord\p = 1 / Coord\p
  EndIf
  Coord\x = Coord\x * Coord\p
  Coord\y = Coord\y * Coord\p
  
  ; On copie les données
  CopyMemory(@Coord, XYZ, SizeOf(Point3D))
EndProcedure

Procedure Cube3D(AngleX.f, AngleY.f, AngleZ.f, Couleur)
  StartDrawing(ScreenOutput())
    
    ; On dessine une ligne du cube
    XYFrom3D(#Cube, #Cube, #Cube, AngleX, AngleY, AngleZ, Coord1.Point3D) ; on calcul les coordonnées de l'extrémité de la ligne pour l'affichage sur l'écran
    XYFrom3D(#Cube, -#Cube, #Cube, AngleX, AngleY, AngleZ, Coord2.Point3D)
    LineXY(Int(#TailleX / 2 + Coord1\x), Int(#TailleY / 2 + Coord1\y), Int(#TailleX / 2 + Coord2\x), Int(#TailleY / 2 + Coord2\y), Couleur) ; on trace une ligne à partir des coordonnées calculées
    
    ; Et on dessine les autres lignes de la même manière
    XYFrom3D(#Cube, -#Cube, -#Cube, AngleX, AngleY, AngleZ, Coord1.Point3D)
    LineXY(Int(#TailleX / 2 + Coord1\x), Int(#TailleY / 2 + Coord1\y), Int(#TailleX / 2 + Coord2\x), Int(#TailleY / 2 + Coord2\y), Couleur)
    
    CopyMemory(@Coord2, @Coord1, SizeOf(Point3D)) ; On copie les valeurs de Coord2 dans Coord1
    XYFrom3D(-#Cube, -#Cube, #Cube, AngleX, AngleY, AngleZ, Coord2.Point3D)
    LineXY(Int(#TailleX / 2 + Coord1\x), Int(#TailleY / 2 + Coord1\y), Int(#TailleX / 2 + Coord2\x), Int(#TailleY / 2 + Coord2\y), Couleur)
    
    XYFrom3D(-#Cube, -#Cube, -#Cube, AngleX, AngleY, AngleZ, Coord1.Point3D)
    LineXY(Int(#TailleX / 2 + Coord1\x), Int(#TailleY / 2 + Coord1\y), Int(#TailleX / 2 + Coord2\x), Int(#TailleY / 2 + Coord2\y), Couleur)
    
    CopyMemory(@Coord2, @Coord1, SizeOf(Point3D)) ; On copie les valeurs de Coord2 dans Coord1
    XYFrom3D(-#Cube, #Cube, #Cube, AngleX, AngleY, AngleZ, Coord2.Point3D)
    LineXY(Int(#TailleX / 2 + Coord1\x), Int(#TailleY / 2 + Coord1\y), Int(#TailleX / 2 + Coord2\x), Int(#TailleY / 2 + Coord2\y), Couleur)
    
    XYFrom3D(-#Cube, #Cube, -#Cube, AngleX, AngleY, AngleZ, Coord1.Point3D)
    LineXY(Int(#TailleX / 2 + Coord1\x), Int(#TailleY / 2 + Coord1\y), Int(#TailleX / 2 + Coord2\x), Int(#TailleY / 2 + Coord2\y), Couleur)
    
    CopyMemory(@Coord2, @Coord1, SizeOf(Point3D)) ; On copie les valeurs de Coord2 dans Coord1
    XYFrom3D(#Cube, #Cube, #Cube, AngleX, AngleY, AngleZ, Coord2.Point3D)
    LineXY(Int(#TailleX / 2 + Coord1\x), Int(#TailleY / 2 + Coord1\y), Int(#TailleX / 2 + Coord2\x), Int(#TailleY / 2 + Coord2\y), Couleur)
    
    XYFrom3D(#Cube, #Cube, -#Cube, AngleX, AngleY, AngleZ, Coord1.Point3D)
    LineXY(Int(#TailleX / 2 + Coord1\x), Int(#TailleY / 2 + Coord1\y), Int(#TailleX / 2 + Coord2\x), Int(#TailleY / 2 + Coord2\y), Couleur)
    
    XYFrom3D(#Cube, -#Cube, -#Cube, AngleX, AngleY, AngleZ, Coord2.Point3D)
    LineXY(Int(#TailleX / 2 + Coord1\x), Int(#TailleY / 2 + Coord1\y), Int(#TailleX / 2 + Coord2\x), Int(#TailleY / 2 + Coord2\y), Couleur)
    
    CopyMemory(@Coord2, @Coord1, SizeOf(Point3D)) ; On copie les valeurs de Coord2 dans Coord1
    XYFrom3D(-#Cube, -#Cube, -#Cube, AngleX, AngleY, AngleZ, Coord2.Point3D)
    LineXY(Int(#TailleX / 2 + Coord1\x), Int(#TailleY / 2 + Coord1\y), Int(#TailleX / 2 + Coord2\x), Int(#TailleY / 2 + Coord2\y), Couleur)
    
    CopyMemory(@Coord2, @Coord1, SizeOf(Point3D)) ; On copie les valeurs de Coord2 dans Coord1
    XYFrom3D(-#Cube, #Cube, -#Cube, AngleX, AngleY, AngleZ, Coord2.Point3D)
    LineXY(Int(#TailleX / 2 + Coord1\x), Int(#TailleY / 2 + Coord1\y), Int(#TailleX / 2 + Coord2\x), Int(#TailleY / 2 + Coord2\y), Couleur)
    
    CopyMemory(@Coord2, @Coord1, SizeOf(Point3D)) ; On copie les valeurs de Coord2 dans Coord1
    XYFrom3D(#Cube, #Cube, -#Cube, AngleX, AngleY, AngleZ, Coord2.Point3D)
    LineXY(Int(#TailleX / 2 + Coord1\x), Int(#TailleY / 2 + Coord1\y), Int(#TailleX / 2 + Coord2\x), Int(#TailleY / 2 + Coord2\y), Couleur)
    
  StopDrawing()
EndProcedure

Procedure.l Objectif()
  ProcedureReturn Int((Random(#VitesseMin - #VitesseMax) + #VitesseMax) / #VitesseEvolution) * #VitesseEvolution
EndProcedure

;- Début du code

; Ecran de veille : Si on veut paramétrer, on ne lance rien
Param.s = Left(ProgramParameter(), 2)
If Param = "/p"
  MessageRequester("Information", "Concepteur : Le Soldat Inconnu [Bouguin Régis]" + Chr(10) + "Programmé sur PureBasic" + Chr(10) + Chr(10) + "http://perso.wanadoo.fr/lesoldatinconnu/", 4 * 16)
  End
EndIf

If OpenWindow(0, 0, 0, 100, 100, "Cube 3D", #PB_Window_BorderLess | #WS_MAXIMIZE) = 0
  End
EndIf
SetWindowPos_(WindowID(0), -1, 0, 0, 0, 0, #SWP_NOSIZE | #SWP_NOMOVE) ; Pour mettre la fenêtre toujours au premier plan
UpdateWindow_(WindowID(0))

If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0
  End
EndIf

If OpenScreen(#TailleX, #TailleY, 32, "Cube 3D") = 0
  End
EndIf

AngleX.f = 0
AngleY.f = 0
AngleZ.f = 0

; Paramètres des vitesses de rotation du cube
RotationX = Objectif()
RotationY = Objectif()
RotationZ = Objectif()
; Objectif des vitesses de rotation
RotationX_Objectif = Objectif()
RotationY_Objectif = Objectif()
RotationZ_Objectif = Objectif()

Repeat
  
  ; On change l'angle d'inclinaison du cube (en fait, on change les angles entre le repère écran et le repère du dessin)
  AngleX + #PI / RotationX
  AngleY + #PI / RotationY
  AngleZ + #PI / RotationZ
  
  ; Permet de faire varier la vitesse de rotation du cube
  If AngleX >= 2 * #PI Or AngleX <= -2 * #PI
    AngleX = 0 ; On initialise l'angle car un angle de 2*#Pi est équivalent à un angle de 0
    If RotationX > RotationX_Objectif
      RotationX - #VitesseEvolution
    ElseIf RotationX < RotationX_Objectif
      RotationX + #VitesseEvolution
    Else
      RotationX_Objectif = Objectif() ; On fixe une nouvelle vitesse de rotation en objectif
    EndIf
  EndIf
  If AngleY >= 2 * #PI Or AngleY <= -2 * #PI
    AngleY = 0
    If RotationY > RotationY_Objectif
      RotationY - #VitesseEvolution
    ElseIf RotationY < RotationY_Objectif
      RotationY + #VitesseEvolution
    Else
      RotationY_Objectif = Objectif()
    EndIf
  EndIf
  If AngleZ >= 2 * #PI Or AngleZ <= -2 * #PI
    AngleZ = 0
    If RotationZ > RotationZ_Objectif
      RotationZ - #VitesseEvolution
    ElseIf RotationZ < RotationZ_Objectif
      RotationZ + #VitesseEvolution
    Else
      RotationZ_Objectif = Objectif()
    EndIf
  EndIf
  
  ClearScreen(0)
  
  For n = #Echo To 0 Step -1
    Cube3D(AngleX - n * #PI / RotationX / #Echo_Espacement, AngleY - n * #PI / RotationY / #Echo_Espacement, AngleZ - n * #PI / RotationZ / #Echo_Espacement, ColorLuminosity(#Couleur, 1 - n / (#Echo + 1)))
  Next
  
  ; On affiche les différentes vitesses et les objectifs
;   StartDrawing(ScreenOutput())
;     Box(2, 2, 2 * RotationX / #VitesseEvolution, 3, $505050)
;     Line(2, 5, 2 * RotationX_Objectif / #VitesseEvolution, 0, $7800)
;     
;     Box(2, 9, 2 * RotationY / #VitesseEvolution, 3, $505050)
;     Line(2, 12, 2 * RotationY_Objectif / #VitesseEvolution, 0, $7800)
;     
;     Box(2, 16,  2 * RotationZ / #VitesseEvolution, 3, $505050)
;     Line(2, 19, 2 * RotationZ_Objectif / #VitesseEvolution, 0, $7800)
;   StopDrawing()
  
  FlipBuffers()
  
  ExamineKeyboard()
  ExamineMouse()
Until KeyboardPushed(#PB_Key_All) Or Abs(MouseDeltaX()) > 2 Or Abs(MouseDeltaY()) > 2

Publié : dim. 10/févr./2008 19:18
par Anonyme
Voici la fct° manquante du code plus haut

Code : Tout sélectionner

Procedure.l ColorLuminosity(Couleur, Echelle.f) 
  Protected Rouge, Vert, Bleu
 
  Rouge = Red(Couleur) * Echelle
  Vert = Green(Couleur) * Echelle
  Bleu = Blue(Couleur) * Echelle
 
  If Rouge > 255 : Rouge = 255 : EndIf
  If Vert > 255 : Vert = 255 : EndIf
  If Bleu > 255 : Bleu = 255 : EndIf
 
  ProcedureReturn RGB(Rouge, Vert, Bleu)
EndProcedure 

@Fortix

Cherche le topic " Moteur3D Software " pour comprendre le principe.
Le Screen/2 c'est pour le point de fuite

Publié : dim. 10/févr./2008 19:34
par Le Soldat Inconnu
oups, ma librairie Effect :)
Je ne pensais pas l'avoir utilisé dans ce code ...

Publié : dim. 10/févr./2008 20:12
par Fortix
Merci pour vos réactions :D

mais je trouve domage qu'il faille absolument passer en 2D pour realiser un tel effet qui semble être pourtant simple :lol:

question:

Tmyke a t il utilisé la même methode dans son Dreamotion?

parce que j'avoue avoir tanté un pliagia, mais sans succè car figurez vous que je n'ais même pas trouvé la procedure "DM_Createline" (en développé)et se qui va avec,
:oops:

donc si par le "pure" des hazard vous tombez dessus, n'hesitez pas à la poster en claire, ainssi nous pourrions examiner ensemble cette "technologie" :twisted:

Publié : dim. 10/févr./2008 20:35
par tmyke
Au sous Dreamotion3D, comme souvent en 3D, c'est en fait très simple.

Pour créer une vraie ligne 3D, il s'agit tout simplement d'un mesh3D qui comprend
seulement 2 points. Il se manipule comme une entité 3D comme les
autres, avec des possibilité de rotation, translation, etc...

Je créé un VertexBuffer avec un certains nombre de points à relier, avec
leurs coordonnées et leurs couleurs.
Pour le rendu je passe par une fonction de rendu standart (DrawPrimitive)
avec un flag particulier ( D3DPT_LINESTRIP) et ma liste de points.

Voila c'est tout. Si tu à téléchargé la pack, ce sont les fonctions contenues
dans le code CSpline.cpp qu'il faut regarder dans les sources du moteur.

Par contre, avec le moteur fournis avec PB, que je ne connais pas plus que cela
pour etre franc, je ne sais pas si ce genre de chose est faisable facilement...

Publié : dim. 10/févr./2008 23:24
par Fortix
Ok reçut 5sur5 Tmyke, :lol:

donc celà signifit que d'après ton explication l'idée que j'avais au depart (de manipuler un mesh cube de base en l'étirant) n'était pas si mauvaise,

mais le but du moment, est de rester dans le contest entierement 3D

Publié : dim. 10/févr./2008 23:45
par Anonyme
Tu n'as pas le choix de passé en 2D !
Ton écran est plat , donc en 2D. tous les jeux & co passe par une projection 2D

Publié : lun. 11/févr./2008 9:45
par tmyke
Hmmm, j'ai un peu de mal à suivre. C'est pour faire des lignes
en 2D sur un écran 3D ou de vrai ligne 3D ?

D'après ton message initial, il me semblais que c'était pour faire de vrai lignes
en 3D (x-y-z) à employer aussi dans un environnement 3D, alors tu as à mon
avis deux solutions:

Soit tu arrives à passer par les fonctions 3D du moteur de PB, et dans
ce cas la tu n'a pas à te soucier du reste, c'est le moteur qui s'occupe
de tout pour toi.

Soit tu simules la chose avec des fonctions 2D, dans ce cas c'est différent,
mais le soucis sera la cohabitation entre tes lignes et tes objets, en
particulier les objets qui seront théoriquement devant tes lignes...
;)

Publié : lun. 11/févr./2008 20:13
par Anonyme
Hmmm, j'ai un peu de mal à suivre. C'est pour faire des lignes
en 2D sur un écran 3D ou de vrai ligne 3D ?
Moi aussi j'ai du mal à te suivre :D
La vraie 3D n'existe pas sur un écran , que se soit un jeu , un modeleur , etc... ton écran est comme le miens , plat.
Donc , tu dois passé par une phase de projection 3D , donc virtuelle sur un plan 2D ( ton écran ) , la formule plus haut , c'est la projection d'un point en XYZ (en 3D) en XY sur l'écran ( 2D )

Toute ligne tracée est en 2D peut importe le moteur , Dreamotion , Ogre , irrlicht , ect.... tout ces moteur utilise une formule de projection , pour Tmyke , c'est directX qui s'en charge.


@Fortix
je t'envois de se pas consulté se post :

http://www.purebasic.fr/french/viewtopi ... ght=cube3d

Publié : lun. 11/févr./2008 20:43
par tmyke
Oui merci, je suis bien d'accords avec toi, mais quel rapport avec le dessin d'une ligne en vrai 3D ?
Comme tu dis, en final, il faut en passer par la, mais c'est la plupart du temps completement
transparent.

Tout ce qui est lié au projection, ce n'est pas l'utilisateur de s'en occuper( sauf dans certains cas particuliers),
quand tu dessine un mesh à l'ecran en 3D avec le moteur 3D fourni avec PB, tu ne t'occupe pas
des projection, tu définis tes mesh, une camera et puis c'est tout. (comme dans DM3D d'ailleurs)


machin = CreateEntity
camera=CreateCamera

repeat
Render3D()
until fin


Si Fortix définit un mesh 3D particulier, avec les fonctions de rendu de PB, pourquoi veux-tu
qu'il tripatouille les projection ?
C'est la que je ne comprend pas... 8)

Publié : lun. 11/févr./2008 21:16
par Anonyme
pourquoi veux-tu
qu'il tripatouille les projection ?
C'est la que je ne comprend pas... Cool
j'ais pensé réutilliser la procedure de Tmyke DM_createline mais maleureusement il fonctionne uniquement avec les autres composants de DM

donc, avez vous une solution ou une alternative à me proposer, svp? Embarassed
Je parle d'alternative moua :D , pour ce genre de code , pas besoin d'un moteur 3D :D

Publié : lun. 11/févr./2008 21:26
par tmyke
Certes, en lisant les premières réponses c'est en effet ce que j'ai pensé,
de procurer un code alternatif, et dans ce cas, oui.

Mais quand suite à ma première réponse, la réponse de Fortix était:
Fortix a écrit :Ok reçut 5sur5 Tmyke, :lol:
donc celà signifit que d'après ton explication l'idée que j'avais au depart (de manipuler un mesh cube de base en l'étirant) n'était pas si mauvaise,
mais le but du moment, est de rester dans le contest entierement 3D
... donc avec les instructions 3D de PB, c'est ensuite que je n'ai plus compris.

Enfin, l'essentiel c'est que Fortix arrive à ses fins, et que nous soyons sur la meme
longueur d'ondes... ;)