Probleme d'affichage sur un code "3d"
Publié : lun. 29/mai/2006 10:37
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"
ca doit etre la procedure poinplan qui ne va pas mais je ne trouve pas l'erreur (pa faute d'avoir essayer ! )
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