Probleme d'affichage sur un code "3d"

Programmation d'applications complexes
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Probleme d'affichage sur un code "3d"

Message par graph100 »

j'ai essaye de faire un prog qui affiche de la 3d mais je n'arrive pas
a cacher les points qui sont derriere une face :
ca fait n'importe quoi et ca cache des point qui sont "devant"

Code : Tout sélectionner

Resultat = InitSprite()

EcranX = GetSystemMetrics_(#SM_CXSCREEN) : ; =largeur de l'ecran
EcranY = GetSystemMetrics_(#SM_CYSCREEN) : ; =hauteur de l'ecran
WindowID = OpenWindow(1, 100, 100, 800, 600, #PB_Window_SystemMenu | #PB_Window_BorderLess, "hello")

WindowID = WindowID(1)
Result = OpenWindowedScreen(WindowID, 0, 0, 800, 600, 1, 0, 0)

InitKeyboard()

KeyboardMode(1)

#pi = 3.1415
#DEGRE = #PI / 180

Structure d3
  x.f
  y.f
  z.f
EndStructure

Structure d3long
  x.l
  y.l
  z.l
EndStructure

DataSection
  point :
    Data.l 8 ; nombre de point
    Data.l 0, 0, 100, 100, 0, 0, 100, 100  ; coordonée x des points
    Data.l 0, 0, 0, 0, 100, 100, 100, 100  ; coordonée y des points
    Data.l 0, 100, 100, 0, 0, 100, 100, 0  ; coordonée z des points
    
  ligne :
    Data.l 12 ; nombre de ligne
    Data.l 1, 2 ; couples de point qui forment une ligne
    Data.l 2, 3
    Data.l 3, 4
    Data.l 4, 1
    Data.l 5, 6
    Data.l 6, 7
    Data.l 7, 8
    Data.l 8, 5
    Data.l 1, 5
    Data.l 2, 6
    Data.l 3, 7
    Data.l 4, 8
    
  plan:
    Data.l 12 ; nombre de plan
    Data.l 1, 2, 3 ; ensemble de trois points formant une face / plan
    Data.l 1, 3, 4
    Data.l 5, 6, 7
    Data.l 5, 8, 7
    Data.l 6, 7, 3
    Data.l 6, 2, 3
    Data.l 5, 6, 2
    Data.l 2, 1, 6
    Data.l 5, 8, 1
    Data.l 1, 4, 8
    Data.l 7, 8, 4
    Data.l 7, 3, 4
EndDataSection

Global Dimentionp, Dimentionl, nombreplan

; chargement des points

Restore point

Read z

Dimentionp = z

Dim Poin.d3(z)
Dim angle.f(z)

For ligne = 1 To 3
  For colonne = 1 To z
    If ligne = 1
      Read z1
      Poin(colonne)\x = z1
    ElseIf ligne = 2
      Read z2
      Poin(colonne)\y = z2
    ElseIf ligne = 3
      Read z3
      Poin(colonne)\z = z3
    EndIf
  Next
Next

; chargement des lignes

Restore ligne

Read z

Dimentionl = z

Dim ligne.Point(z)

For colonne = 1 To z
  Read z1
  ligne(colonne)\x = z1
  Read z1
  ligne(colonne)\y = z1
Next

; chargement des plans 

Restore plan

Read z

nombreplan = z

Dim plan.d3long(z)

For colonne = 1 To z
  Read z1
  plan(colonne)\x = z1
  Read z1
  plan(colonne)\y = z1
  Read z1
  plan(colonne)\z = z1
Next

Procedure PointPlan(xd.f, yd.F, zd.f, xa.F, ya.f, za.f, xb.f, yb.F, zb.F, xc.F, yc.F, zc.F)
  
  ; teste si les points sont confondus
  If (xa = xb And ya = yb) Or (xa = xc And ya = yc) Or (xb = xc And yb = yc) Or (xd = xa And yd = ya) Or (xd = xb And yd = yb) Or (xd = xc And yd = yc)
    ProcedureReturn -1
  EndIf
  
  ; calcul des longueurs avec :
;      B
;      |\
;      |  \
;      |    \
;      |  *D  \
;      |        \
;      -----------  C
;      A
  
  ab.f = Sqr((xa - xb) * (xa - xb) + (ya - yb) * (ya - yb))
  bc.f = Sqr((xb - xc) * (xb - xc) + (yb - yc) * (yb - yc))
  ac.f = Sqr((xa - xc) * (xa - xc) + (ya - yc) * (ya - yc))
  ad.f = Sqr((xa - xd) * (xa - xd) + (ya - yd) * (ya - yd))
  bd.f = Sqr((xb - xd) * (xb - xd) + (yb - yd) * (yb - yd))
  dc.f = Sqr((xd - xc) * (xd - xc) + (yd - yc) * (yd - yc))
  
  
  ; calcul des differents angles
  bad.f = ACos((bd * bd - ab * ab - ad * ad) / (-2 * ab * ad))
  dac.f = ACos((dc * dc - ad * ad - ac * ac) / (-2 * ad * ac))
  bac.f = ACos((bc * bc - ab * ab - ac * ac) / (-2 * ab * ac))
  acd.f = ACos((ad * ad - ac * ac - dc * dc) / (-2 * ac * dc))
  dcb.f = ACos((bd * bd - dc * dc - bc * bc) / (-2 * dc * bc))
  acb.f = ACos((ab * ab - ac * ac - bc * bc) / (-2 * ac * bc))
    
  If EgalApproxime(acd + dcb, acb, 0.001) And EgalApproxime(bad + dac, bac, 0.001) ; teste si le point D est a l'interieur du triangle ABC
    ; calcul des coordonnées x y z pour le point E ( point d'intersection de (AD) avec (BC)
    If xa - xd = 0
      aprime.f = (yb - yc) / (xb - xc)
      bprime.f = yb + aprime * xb
      
      xe.f = xa
      ye.f = aprime * xe + bprime
    ElseIf xb - xc = 0
      a.f = (ya - yd) / (xa - xd)
      b.f = ya - a * xa
      
      xe.f = xb
      ye.f = a * xe + b
    Else
      a.f = (ya - yd) / (xa - xd)
      b.f = ya - a * xa
      aprime.f = (yb - yc) / (xb - xc)
      bprime.f = yb + aprime * xb
      
      xe.f = (bprime - b) / (a - aprime)
      ye.f = a * xe + b
    EndIf
    
    If xa - xc = 0
      m.f = (zb - zc) / (yb - yc)
      n.f = zb - m * yb
      
      ze.f = m * ye + n
    Else
      m.f = (zb - zc) / (xb - xc)
      n.f = zb - m * xb
      
      ze.f = m * xe + n
    EndIf
    
    ; calcul de la cote de la projection orthogonale de D sur le plan forme par le triangle ABC
    If xa - xe = 0
      mprime.f = (za - ze) / (ya - ye)
      nprime.f = za - mprime * ya
      
      Z.f = mprime * yd + nprime
    Else
      mprime.f = (za - ze) / (xa - xe)
      nprime.f = za - mprime * xa
      
      Z.f = mprime * xd + nprime
    EndIf
    
    ; comparaison de la cote avec la cote de D
    
    If xd > Z : ProcedureReturn 1 : EndIf ; le point D est derriere le triangle ABC : on ne devrai pas le voir
    If xd = Z : ProcedureReturn 2 : EndIf ; le point D est sur le triangle ABC
    If xd < Z : ProcedureReturn 3 : EndIf ; le point D est devant le triangle ABC
    
  Else
    ProcedureReturn 0
  EndIf
EndProcedure

Procedure Display3d(coorx, coory, rotationz.f, rotationy.f, rotationx.f, color)

  ; rotation autour de z
 If rotationz 
 For curseur = 1 To Dimentionp
    If Poin(curseur)\x = 0 : Poin(curseur)\x = 0.000001 : EndIf
    If poin(curseur)\x <> 0
      angle(curseur) = rotationz + ATan(poin(curseur)\y / poin(curseur)\x)
      If poin(curseur)\x <= 0
        angle(curseur) = #pi + angle(curseur)
      EndIf
    ElseIf poin(curseur)\y > 0
      angle(curseur) = #pi / 2 + rotationz
    ElseIf poin(curseur)\y <= 0
      angle(curseur) = #pi + rotationz
    EndIf
    
    distance.f = Sqr(poin(curseur)\x * poin(curseur)\x + poin(curseur)\y * poin(curseur)\y)
    poin(curseur)\x = distance * Cos(angle(curseur))
    poin(curseur)\y = distance * Sin(angle(curseur))
  Next
  EndIf
  
  ;rotation autour de y
  If rotationy
  For curseur = 1 To Dimentionp
    If Poin(curseur)\x = 0 : Poin(curseur)\x = 0.000001 : EndIf
    If poin(curseur)\x <> 0
      angle(curseur) = rotationy + ATan(poin(curseur)\z / poin(curseur)\x)
      If poin(curseur)\x <= 0
        angle(curseur) = #pi + angle(curseur)
      EndIf
    ElseIf poin(curseur)\z > 0
      angle(curseur) = #pi / 2 + rotationy
    ElseIf poin(curseur)\z <= 0
      angle(curseur) = #pi - rotationy
    EndIf
    
    distance.f = Sqr(poin(curseur)\x * poin(curseur)\x + poin(curseur)\z * poin(curseur)\z)
    poin(curseur)\x = distance * Cos(angle(curseur))
    poin(curseur)\z = distance * Sin(angle(curseur))
  Next
  EndIf
  
  ;rotation autour de x
  If rotationx
  For curseur = 1 To Dimentionp
    If Poin(curseur)\z = 0 : Poin(curseur)\z = 0.000001 : EndIf
    If poin(curseur)\z <> 0
      angle(curseur) = rotationx + ATan(poin(curseur)\y / poin(curseur)\z)
      If poin(curseur)\z <= 0
        angle(curseur) = #pi + angle(curseur)
      EndIf
    ElseIf poin(curseur)\y > 0
      angle(curseur) = #pi / 2 + rotationx
    ElseIf poin(curseur)\y <= 0
      angle(curseur) = #pi + rotationx
    EndIf
    
    distance.f = Sqr(poin(curseur)\z * poin(curseur)\z + poin(curseur)\y * poin(curseur)\y)
    poin(curseur)\z = distance * Cos(angle(curseur))
    poin(curseur)\y = distance * Sin(angle(curseur))
  Next
  EndIf
  
  ; dessin de coté
  For curseur = 1 To Dimentionl
    point1 = ligne(curseur)\x
    point2 = ligne(curseur)\y
    
    pointx1 = poin(point1)\x + coorx
    pointy1 = poin(point1)\y + coory
    pointx2 = poin(point2)\x + coorx
    pointy2 = poin(point2)\y + coory
    
    result = 0
    
    ; test si les points sont visibles
    For plan = 1 To nombreplan
      result = PointPlan(poin(point1)\x, poin(point1)\y, poin(point1)\z, poin(plan(plan)\x)\x, poin(plan(plan)\x)\y, poin(plan(plan)\x)\z, poin(plan(plan)\y)\x, poin(plan(plan)\y)\y, poin(plan(plan)\y)\z, poin(plan(plan)\z)\x, poin(plan(plan)\z)\y, poin(plan(plan)\z)\z)
      If result = 1
        Break
      EndIf
      result = PointPlan(poin(point2)\x, poin(point2)\y, poin(point2)\z, poin(plan(plan)\x)\x, poin(plan(plan)\x)\y, poin(plan(plan)\x)\z, poin(plan(plan)\y)\x, poin(plan(plan)\y)\y, poin(plan(plan)\y)\z, poin(plan(plan)\z)\x, poin(plan(plan)\z)\y, poin(plan(plan)\z)\z)
      If result = 1
        Break
      EndIf
    Next
    
    If result <> 1
      LineXY(pointx1, pointy1, pointx2, pointy2, color)
    Else
      LineXY(pointx1, pointy1, pointx2, pointy2, color / 5)
    EndIf
  Next
EndProcedure

Repeat
  event = WindowEvent()
  Delay(10)
  rotz.f = 0
  roty.f = 0
  rotx.f = 0
  
  ExamineKeyboard()
  
  If KeyboardPushed(#PB_Key_Up) : rotx = #degre * 2
  ElseIf KeyboardPushed(#PB_Key_Down) : rotx = - #DEGRE * 2
  ElseIf KeyboardPushed(#PB_Key_Right) : roty = #DEGRE * 2
  ElseIf KeyboardPushed(#PB_Key_Left) : roty = - #DEGRE * 2
  ElseIf KeyboardPushed(#PB_Key_A) : rotz = #DEGRE * 2
  ElseIf KeyboardPushed(#PB_Key_Z) : rotz = - #DEGRE * 2
  EndIf
  
  ClearScreen(0, 0, 0)
  
  StartDrawing(ScreenOutput())
    Display3d(WindowMouseX(), WindowMouseY(), rotz, roty, rotx, RGB(0, 0, 255))
  StopDrawing()
  
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape) Or event = #PB_Event_CloseWindow
ca doit etre la procedure poinplan qui ne va pas mais je ne trouve pas l'erreur (pa faute d'avoir essayer ! )
Avatar de l’utilisateur
flaith
Messages : 1487
Inscription : jeu. 07/avr./2005 1:06
Localisation : Rennes
Contact :

Message par flaith »

Difficile de tester, il manque la procedure EgalApproxime() ;)
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Message par graph100 »

j'avais fait une lib dsl

Code : Tout sélectionner

ProcedureDLL EgalApproxime(nombre1.f, nombre2.f, approximation.f)
  If nombre1 + Abs(approximation) >= nombre2 And nombre1 - Abs(approximation) <= nombre2
    ProcedureReturn 1
  EndIf
  ProcedureReturn 0
EndProcedure
voila :D
Répondre