Démo - mesh axial

Généralités sur la programmation 3D
Avatar de l’utilisateur
Guillot
Messages : 672
Inscription : jeu. 25/juin/2015 16:18

Démo - mesh axial

Message par Guillot »

Image

salut à tous,
j'ai fais une fonction pour dessiner des meshs genre : verre, bouteille (eh oui, fait chaud !), vase... , enfin tous ce qui présente une symétrie axial, et même plus
et j'ai pas été déçu par le résultat !
je vous mets cette démo pour illustrer mes fonctions:
- CreateAxialMeshCircular
- CreateAxialMeshCustom
(eh oui, j'ai même traduit in english!)
le principe est de définir un profil (et une section pour la fonction 'custom') decrivant le mesh
ces profils et sections sont définit par une série de point que j'interpole par une spline
une seule instruction permet de définir le mesh
vous verrez dans le code
ces fonctions sont assez abouties, j'espere que ça vous sera utile
en revanche pour les formes complexes, c’est un peu galère d'entrer les coordonnées des points de la spline
faudra que je fasse un petit éditeur..

(un petit defaut concernant l'ombrage au niveau de la jointure, j'ai pas trouvé la fonction qui va bien, j'espere que quelqu'un va corriger ça)

sinon j'ai remis mon petit mirroir qui bug sur les bord (à cause de Cameraprojection qui retourne -1 quand on sort de l'écran)

voilà

Code : Tout sélectionner

;Mesh Axial - Pf shadoko - 2015 

EnableExplicit

Global.w ex,ey,dx,dx1,dy,dy1,nb

;###############################################################################
;###############################################################################
;###############################################################################
Structure coo2d
  x.f
  y.f
EndStructure
  
Procedure Bspline(Array pe.coo2d(1), Array PS.coo2d(1),nd.w)
  Protected.f t,tt
  Protected np,i,j,jj,k,c
  Protected Dim m.w(4, 4)
  Protected Dim ttt.f(4)
  np = ArraySize(pe()) 
  Protected Dim PS((np - 2) * nd)
  
  m(0, 0) = -1: m(1, 0) =  3: m(2, 0) = -3: m(3, 0) =  1
  m(0, 1) =  2: m(1, 1) = -5: m(2, 1) =  4: m(3, 1) = -1
  m(0, 2) = -1: m(1, 2) =  0: m(2, 2) =  1: m(3, 2) =  0
  m(0, 3) =  0: m(1, 3) =  2: m(2, 3) =  0: m(3, 3) =  0

  If pe(np - 1)\X = pe(1)\X And pe(np - 1)\Y = pe(1)\Y
    pe(0) = pe(np - 2): pe(np) = pe(2)
  Else 
    pe(0) = pe(1):pe(np) = pe(np - 1)
  EndIf
  
  For jj = 0 To np - 3
    For i = 0 To nd - 1
      t = i / nd
      For j = 0 To 3
        ttt(j) = 0: tt = 1
        For k = 3 To 0 Step -1: ttt(j) + tt * m(j, k) / 2: tt = tt * t: Next
        PS(c)\X = PS(c)\X + ttt(j) * pe(j + jj)\X
        PS(c)\Y = PS(c)\Y + ttt(j) * pe(j + jj)\Y
      Next
      c + 1
    Next
  Next
  PS(c) = pe(np - 1)
EndProcedure

Procedure string2coo2d(Array s.coo2d(1),t.s) ;pas tres élégant !
  Protected Dim a.f(0, 0)
  Protected n
  t="0,0/"+t+"/0,0"
  ParseJSON(0, "[["+ReplaceString(t,"/","],[")+"]]")
  ExtractJSONArray(JSONValue(0), a())
  n=ArraySize(a())
  Dim s.coo2d(n)
  CopyMemory(@a(0,0),@s(0),4*2*(n+1))
EndProcedure

Procedure.f lg2D(x.f,y.f)
  ProcedureReturn Sqr(x.f*x.f+y.f*y.f)
EndProcedure

Procedure CreateAxialMesh(mesh,Array profils.coo2d(1),Array section.coo2d(1))
  Macro profilsJ()
    ar=r
    ah=h
    r=profils(j)\x
    h=profils(j)\y
    v+lg2D(r-ar,h-ah)
  EndMacro
  
  Protected i,j,r.f,h.f,ar.f,ah.f,a.f,v.f,vv.f,n,n1,m
  n=ArraySize(section()):n1=n+1
  m=ArraySize(profils())
  
  r=profils(0)\x:h=profils(0)\y:v=0
  For j=0 To m:profilsJ():Next:vv=v
  
  r=profils(0)\x:h=profils(0)\y:v=0
  CreateMesh(mesh,#PB_Mesh_TriangleList,#PB_Mesh_Dynamic)
  For j=0 To m
    profilsJ()
    For i=0 To n    
      MeshVertexPosition(section(i)\x* r,h,section(i)\y* r)
      MeshVertexTextureCoordinate(i/n,v/vv)
      MeshVertexNormal(0,0,0)
      MeshVertexColor($ffffff)
    Next
  Next
  For j=0 To m-1
  For i=0 To n-1
    MeshFace(i+j*n1,i+(j+1)*n1,(i%n1+1)+j*n1)
    MeshFace((i%n1+1)+(j+1)*n1,(i%n1+1)+j*n1,i+(j+1)*n1)
  Next
  Next
  FinishMesh(1)
  NormalizeMesh(mesh) 
  ;BuildMeshTangents(Mesh)
EndProcedure

Procedure CreateAxialMeshCustom(mesh,ProfilList.s,ProfilSubDiv,sectionList.s,SectionSubDiv)
  Protected Dim profil.coo2d(0)
  Protected Dim profils.coo2d(0)
  string2coo2d(profil(),ProfilList)
  Bspline(profil(),profils(),ProfilSubDiv)
  
  Protected Dim section.coo2d(0)
  Protected Dim sections.coo2d(0)
  string2coo2d(section(),sectionList)
  Bspline(section(),sections(),SectionSubDiv)
  
  CreateAxialMesh(mesh,profils(),sections())
EndProcedure

Procedure CreateAxialMeshCircular(mesh,ProfilList.s,ProfilSubDiv=16 ,cercleSubDiv=16)
  Protected i,a.f
  Protected Dim profil.coo2d(0)
  Protected Dim profils.coo2d(0)
  string2coo2d(profil(),ProfilList)
  Bspline(profil(),profils(),ProfilSubDiv)
  
  Protected Dim section.coo2d(cercleSubDiv)
  For i=0 To cercleSubDiv:a=Radian(360/cercleSubDiv)*i:section(i)\x=Cos(a):section(i)\y=Sin(a):Next
  
  CreateAxialMesh(mesh,profils(),section())
EndProcedure
;###############################################################################
;###############################################################################
;###############################################################################

Procedure degrade(Array pal.l(1),l,c1.l,c2.l)
  Dim pal(l-1)
  CreateImage(0,l,1,32)
  StartDrawing(ImageOutput(0))
  DrawingMode(#PB_2DDrawing_Gradient)
  GradientColor(0.0,c1)
  GradientColor(1.0,c2)
  LinearGradient(0,0,l-1,0)
  Box(0,0,l,1)
  CopyMemory(DrawingBuffer(),@pal(0),l*4)
  StopDrawing()
  FreeImage(0)
EndProcedure

Procedure generematiere(num,dx,dy,c1,c2,type)
  Protected i,j,y
  Protected Dim pal.l(0):degrade(pal(),256,c1,c2)
  CreateTexture(num,dx,dy)
  StartDrawing(TextureOutput(num))
  Select type
    Case 1; point (assiette /pomme / coupe)
      For j=0 To dy-1:For i=0 To dx-1:Plot(i,j,pal(Random(255))):Next:Next
    Case 2; tissu (boite)
      For i=0 To 2000:Line(Random(dx),0,1,dy,pal(Random(127)+128)):Line(0,Random(dy),dx,1,pal(Random(127))):Next  
    Case 3; brasselet
      For i=-dx To dx:LineXY(i,0,i+dx,dy,pal(Bool(i & 30)*255)):Next  
    Case 4; vase
      For j=0 To dy-1:For i=0 To dx-1:y=((Cos(i*4*#PI/dx)*255)): Plot(i ,j,pal((j*5+y) & 255)):Next:Next  
    Case 5; verre
      Box(0,0,dx,dy,$ffffff):For j=0 To dy Step 32:Box (0,j,dx,4,$8800):Box (j,0,4,dy,$88):Next
  EndSelect  
  StopDrawing()
  CreateMaterial(num, TextureID(num))
EndProcedure

Procedure scene()
  Protected i,j,k,c,x,y,dx=8,dy=8
    
  ;######################################## cameras 
  ;principale
  CreateCamera(0, 0, 0, 100, 100):MoveCamera(0, 1000, 500, 0, #PB_Absolute):CameraLookAt(0, 0, 100, 0):CameraBackColor(0, $333333) 
  ;miroir
  CreateCamera(1, 0, 0,50,50):CameraBackColor(1, $333333)
  
  CreateLight(0,$ffffff, 10000, 10000, 5000)
  AmbientColor($222222)
  ;WorldShadows(#PB_Shadow_Additive,-1,$aaaaaa)
  
  ;######################################## textures / material  
  CreateRenderTexture(0,CameraID(1),ex,ey)
  CreateMaterial(0, TextureID(0))
  SetMaterialColor(0,#PB_Material_DiffuseColor,$777777):MaterialBlendingMode(0,#PB_Material_Add)
 
  generematiere(1,256,256,$ff0000,$ffff00,2) :ScaleMaterial(1,0.25,0.25) 
  generematiere(2,256,256,$ffcc88,$ccaa66,1)
  generematiere(3,128,256,$443300,$222200,1)
  generematiere(4,64,64,$aaaaff,$ffffaa,1)
  generematiere(5,256,256,$0000ff,$ffcc22,3)
  generematiere(6,256,256,$ffffff,$cc9999,4) :ScaleMaterial(6,0.25,0.25)
  generematiere(7,256,256,$ffffff,$ffcc00,5)
  generematiere(8,8,8,$999900,$cc0000,1)
  generematiere(9,256,256,$ff8800,$88ff88,2)  :ScaleMaterial(9,0.25,0.25)
     
  ;######################################## mesh/entity
   ;CreateSphere (2,100):CreateEntity(2, MeshID(2), MaterialID(1),0,100,0)
  
  ;table+vitre
  CreateAxialMeshCircular(1,"500,0/0,0",8,32)
  CreateEntity(1, MeshID(1), MaterialID(0))
  CreateAxialMeshCircular(2,"500,0/0,0",1,32)
  CreateEntity(2, MeshID(2), MaterialID(3),0,-1,0)
  ;coupes
  CreateAxialMeshCircular(10,"0,0/50,1/10,20/10,100/55,200/50,200/0,100",4,32)
  CreateEntity(10, MeshID(10), MaterialID(4),0,0,-300)
  CreateEntity(11, MeshID(10), MaterialID(4),200,0,-320)
  ;assiette
  CreateAxialMeshCircular(12,"0,0/100,1/160,47/157,50/75,10/0,10",1,8)
  CreateEntity(12, MeshID(12), MaterialID(2),250,0,250)
  ;vases
  CreateAxialMeshCircular(13,"0,0/80,1/120,150/80,250/110,300/100,300/75,250/75,20/0,20",8,32)
  CreateEntity(13, MeshID(13), MaterialID(6),-0,0,0)
  ;boite
  CreateAxialMeshCircular(14,"0,0/80,1/110,70/85,140/90,140/90,150/10,160/20,190/0,200",4,4)
  CreateEntity(14, MeshID(14), MaterialID(1),-200,0,-200)
  ;brasselet                              !!!! pour faire un tore, le premier point doit etre similaire au premier !!!!
  CreateAxialMeshCircular(15,"45,15/45,0/55,15/45,30/45,15",4,32)
  CreateEntity(15, MeshID(15), MaterialID(5),400,0,100)
  ;verre
  CreateAxialMeshCircular(16,"0,0/50,1/60,150/55,150/45,10/0,10",1,32)
  CreateEntity(16, MeshID(16), MaterialID(7),0,0,200)
  ;pommes
  CreateAxialMeshCircular(17,"0,10/20,0/45,30/50,80/20,100/2,90/1,100/0,105",4,32)
  CreateEntity(17, MeshID(17), MaterialID(8),230,10+10,300)
  CreateEntity(18, MeshID(17), MaterialID(8),320,10+10,250)
  CreateEntity(19, MeshID(17), MaterialID(8),260,10+10,170)
  ;truc (custom (ici on definit la section))
  CreateAxialMeshCustom(20,"0,0/56,1/62,34/64,40/61,43/58,40/60,34/52,6/0,4",4,"-0.8,0/-1,-1/1,-1/0.8,0/1,1/-1,1/-0.8,0",8)
  CreateEntity(20, MeshID(20), MaterialID(9),300,0,-100)

EndProcedure


Procedure rendermirror2(mesh,camP,camM)
  Protected c,n,mx,my
  Protected.f xp,yp,zp,xd,yd,zd
  Protected Dim T.PB_MeshVertex(0)
  
  xp=CameraX(camP):xd=CameraDirectionX(camP)
  yp=CameraY(camP):yd=CameraDirectionY(camP)
  zp=CameraZ(camP):zd=CameraDirectionZ(camP)
  CameraDirection(camM,xd,-yd,zd)
  MoveCamera(camM,xp,-yp,zp,#PB_Absolute)
  mx=ex   ;CameraViewWidth (camM) ;marche pas,
  my=ey   ;CameraViewHeight(camM) ;pas compris !
  n=MeshVertexCount(mesh)-1
  GetMeshData(mesh,0,t(),#PB_Mesh_Vertex|#PB_Mesh_UVCoordinate ,0,n)
  For c=0 To n
    With t(c)
      \u=  CameraProjectionX(1,\x, 0,\z)/mx
      \v=  CameraProjectionY(1,\x, 0,\z)/my
    EndWith
  Next
  SetMeshData(mesh,0,t(),#PB_Mesh_Vertex|#PB_Mesh_UVCoordinate,0,MeshVertexCount(mesh)-1)
EndProcedure


Define.f KeyX, KeyY,keyz, MouseX, MouseY,time,v,a,x,y,z,r.l
Define i,j,c,px,py,p,shadingmode
InitEngine3D()   
InitSprite()
InitKeyboard()
InitMouse()
OpenWindow(0, 0, 0, 0,0, " Mesh Axial",#PB_Window_Maximize)
ex=WindowWidth (0,#PB_Window_InnerCoordinate)
ey=WindowHeight(0,#PB_Window_InnerCoordinate)
OpenWindowedScreen(WindowID(0), 0, 0, ex, ey, 0, 0, 0)

Macro DT(t1,t2)
  DrawText(4,p,t1)
  DrawText(40,p,t2)
  p+16
EndMacro
CreateSprite(0,120,170,#PB_Sprite_AlphaBlending)
StartDrawing(SpriteOutput(0))
DrawingMode(#PB_2DDrawing_AlphaClip|#PB_2DDrawing_Outlined )
Box(0,0,120,170)
BackColor($0000ff)
dt("Déplacements:","")
dt("[Left]","")
dt("[Right]","")
dt("[Up]","")
dt("[Down]","")
dt("Mouse+wheel","")
dt("","")
dt("Commandes:","")
dt("[F1]","fil de fer")
dt("[Esc]","Quitter")
StopDrawing()

scene()

Repeat    
  WindowEvent()  
  ExamineMouse()
  MouseX = -MouseDeltaX() *  0.05
  MouseY = -MouseDeltaY() *  0.05
  ExamineKeyboard()
  keyx=(-Bool(KeyboardPushed(#PB_Key_Left)<>0)+Bool(KeyboardPushed(#PB_Key_Right)<>0))*4
  keyz=(-Bool(KeyboardPushed(#PB_Key_Down)<>0)+Bool(KeyboardPushed(#PB_Key_Up   )<>0))*4+MouseWheel()*50
  RotateCamera(0, MouseY, MouseX, 0, #PB_Relative):MoveCamera  (0, KeyX, keyy, -keyz)  
  If KeyboardReleased(#PB_Key_F1)
    If shadingmode=#PB_Material_Wireframe:shadingmode=#PB_Material_Solid:Else:shadingmode=#PB_Material_Wireframe:EndIf
    For i=0 To 9:MaterialShadingMode(i, shadingmode):Next
  EndIf  
  rendermirror2(1,0,1)
  time+RenderWorld()/200
  DisplayTransparentSprite(0, 8,8,128)
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
End
aucune dépendance
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: Démo - mesh axial

Message par comtois »

C'est magnifique, tu devrais aussi proposer ton code sur le forum anglais, il y a 2 ou 3 amateurs de 3D qui apprécieront ;)
Guillot a écrit :(un petit defaut concernant l'ombrage au niveau de la jointure, j'ai pas trouvé la fonction qui va bien, j'espere que quelqu'un va corriger ça)
C'est sans doute lié à la façon dont les normales sont calculées avec la fonction NormalizeMesh(). Je crois que la normale est calculée par triangle sans tenir compte des voisins.
la solution serait de calculer dans le code la moyenne des normales ayant un vertex en commun. (ou recalculer uniquement les normales des vertices dans la jointure)
sinon j'ai remis mon petit mirroir qui bug sur les bord (à cause de Cameraprojection qui retourne -1 quand on sort de l'écran)
Que devrait retourner CameraProjection quand on sort de l'écran ?
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Avatar de l’utilisateur
falsam
Messages : 7317
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Démo - mesh axial

Message par falsam »

La langue m'en tombe .... Magnifique

Image

Vous avez vu Droopy avec sa gueule de blasé parce que lui préfère le style old school. Il me fait penser à un membre du forum qui aime bien ce style. Un indice ? Modération. héhé.
Dernière modification par falsam le mer. 08/juil./2015 23:01, modifié 1 fois.
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
crisot
Messages : 98
Inscription : lun. 30/août/2004 21:03

Re: Démo - mesh axial

Message par crisot »

Le problème d'ombrage au niveau de la jointure est lié à la création de la normale. Il faut "fermer" ton objet, c'est à dire que l'avant dernier vertex doit être lié au premier vertex, et non pas au "dernier vertex qui est une copie conforme du premier".

Tout simplement.

EDIT: Non l'idée n'est pas viable, je viens de le faire, et malheureusement les UV ne collent plus, la texture se répète "n" fois dans le dernier triangle. Logique aussi... Cela dit ça réglait le problème d'ombre :)
Avatar de l’utilisateur
Guillot
Messages : 672
Inscription : jeu. 25/juin/2015 16:18

Re: Démo - mesh axial

Message par Guillot »

à comtois:
- ok
- ce défaut est present même avec createsphere, mais j'ai pas encore isolé le contexte
(je l'ai parfois vu disparaitre en mettant en staticgeometry)
- valeurs négative ou superieur aux limites, ça serai utile un paramètre optionnel pour avoir la valeur hors cadre

à falsam:
- ;o)

à crisot:
- ah, si c'était si simple !
le probleme, c'est le bouclage de la texture
imagine la face d'un cube, les coordonnées UV(position dans la texture) serai 0, 0.25, 0.75, et...0 si bouclé
du coup on passe de 0.75 à 0 (retour en arrière)
le bug est bien visible avec createcylender, la sphère, elle, est faite en doublant les points de la bordure
Avatar de l’utilisateur
microdevweb
Messages : 1802
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: Démo - mesh axial

Message par microdevweb »

@Guillot,

C'est beau le tallent, et la tu n'en manque pas...
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
crisot
Messages : 98
Inscription : lun. 30/août/2004 21:03

Re: Démo - mesh axial

Message par crisot »

Pour générer les bonnes normales, le moteur se sert toujours des vertexs encadrant.

2 solutions:

-Soit générer soit même les normales des vertex de début et fin pour chaque ligne.

-Soit ajouter deux polygones supplémentaires. Un "avant le premier", et un "après le dernier", puis demander au moteur de ne pas afficher les polygones en question, ils ne sont là que pour la création des normale.

Comme je n'utilise pas le moteur 3D de PB, je ne sais pas ce qui est le plus simple à réaliser.
Frenchy Pilou
Messages : 2194
Inscription : jeu. 27/janv./2005 19:07

Re: Démo - mesh axial

Message par Frenchy Pilou »

Mais cela est fait par un professeur Shadock! :D
Est beau ce qui plaît sans concept :)
Speedy Galerie
Avatar de l’utilisateur
Micoute
Messages : 2583
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: Démo - mesh axial

Message par Micoute »

Frenchy Pilou a écrit :Mais cela est fait par un professeur Shadock! :D
Et comment !!!
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 6.20 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: Démo - mesh axial

Message par comtois »

Je viens de créer un module pour calculer les normales d'un mesh, et en guise de test j'ai utilisé ton code.
Il faudrait que je teste une autre méthode , en pondérant par les angles , ou en pondérant en fonction de la surface du triangle. Un gros triangle influence plus qu'un petit pour un vertex en commun.

Le module seul

Code : Tout sélectionner

DeclareModule Mesh
	Declare Normalize(Mesh)
EndDeclareModule

Module Mesh
	Structure Vector3
		x.f
		y.f
		z.f
	EndStructure
	
	Macro SubVector3(n, v, w)
		n\x = v\x - w\x
		n\y = v\y - w\y
		n\z = v\z - w\z
	EndMacro
	
	Procedure NormalizeVector(*V.Vector3)
		Define.f magSq, oneOverMag
		
		magSq = *V\x * *V\x + *V\y * *V\y + *V\z * *V\z
		If magsq > 0
			oneOverMag = 1.0 / Sqr(magSq)
			*V\x * oneOverMag
			*V\y * oneOverMag
			*V\z * oneOverMag
		EndIf 
		
	EndProcedure
	
	Procedure Normalize(Mesh)
		
		Protected i, j
		Dim Vertex.PB_MeshVertex(0)
		Dim Face.PB_MeshFace(0)
		Protected.Vector3 v2v1, v3v1, v1,v2,v3,n
		
		For j=0 To SubMeshCount(mesh)-1
			GetMeshData(Mesh, j, Vertex(),   #PB_Mesh_Vertex | #PB_Mesh_Normal , 0, MeshVertexCount(Mesh)-1)
			GetMeshData(Mesh, j, Face(),   #PB_Mesh_Face , 0, MeshIndexCount(Mesh)-1)
			
			For i = 0 To ArraySize(Vertex())
				Vertex(i)\NormalX = 0
				Vertex(i)\NormalY = 0
				Vertex(i)\NormalZ = 0
			Next
			
			For i = 0 To ArraySize(Face()) Step 3
				
				v1\x = Vertex(Face(i)\Index)\x
				v1\y = Vertex(Face(i)\Index)\y
				v1\z = Vertex(Face(i)\Index)\z
				
				v2\x = Vertex(Face(i+1)\Index)\x
				v2\y = Vertex(Face(i+1)\Index)\y
				v2\z = Vertex(Face(i+1)\Index)\z
				
				v3\x = Vertex(Face(i+2)\Index)\x
				v3\y = Vertex(Face(i+2)\Index)\y
				v3\z = Vertex(Face(i+2)\Index)\z
				
				SubVector3(v2v1, v2, v1)
				SubVector3(v3v1, v3, v1)
				
				n\x = v2v1\y * v3v1\z - v2v1\z * v3v1\y
				n\y = v2v1\z * v3v1\x - v2v1\x * v3v1\z
				n\z = v2v1\x * v3v1\y - v2v1\y * v3v1\x
				
				NormalizeVector(@n)
				
				Vertex(Face(i)\Index)\NormalX + n\x
				Vertex(Face(i)\Index)\NormalY + n\y
				Vertex(Face(i)\Index)\NormalZ + n\z
				
				Vertex(Face(i+1)\Index)\NormalX + n\x
				Vertex(Face(i+1)\Index)\NormalY + n\y
				Vertex(Face(i+1)\Index)\NormalZ + n\z
				
				Vertex(Face(i+2)\Index)\NormalX + n\x
				Vertex(Face(i+2)\Index)\NormalY + n\y
				Vertex(Face(i+2)\Index)\NormalZ + n\z
			Next
			
			For i = 0 To ArraySize(Vertex())
				n\x = Vertex(i)\NormalX
				n\y = Vertex(i)\NormalY
				n\z = Vertex(i)\NormalZ
				NormalizeVector(@n)
				Vertex(i)\NormalX = n\x
				Vertex(i)\NormalY = n\y
				Vertex(i)\NormalZ = n\z
				
			Next
			SetMeshData(mesh,j,Vertex(),#PB_Mesh_Vertex | #PB_Mesh_Normal , 0, MeshVertexCount(Mesh)-1)
		Next
	EndProcedure	
EndModule

Ton code avec le module intégré :

Code : Tout sélectionner

DeclareModule Mesh
	Declare Normalize(Mesh)
	Declare NormalizeJointure(Mesh,n)
EndDeclareModule

Module Mesh
	Structure Vector3
		x.f
		y.f
		z.f
	EndStructure
	
	Macro SubVector3(n, v, w)
		n\x = v\x - w\x
		n\y = v\y - w\y
		n\z = v\z - w\z
	EndMacro
	
	Macro PRODUIT_SCALAIRE(V1, V2)
		(V1\x * V2\x + V1\y * V2\y  + V1\z * V2\z)
	EndMacro
	
	Procedure NormalizeVector(*V.Vector3)
		Define.f magSq, oneOverMag
		
		magSq = *V\x * *V\x + *V\y * *V\y + *V\z * *V\z
		If magsq > 0
			oneOverMag = 1.0 / Sqr(magSq)
			*V\x * oneOverMag
			*V\y * oneOverMag
			*V\z * oneOverMag
		EndIf 
		
	EndProcedure
	
	Procedure.f Area()
		;https://fr.wikipedia.org/wiki/Formule_de_H%C3%A9ron
		Protected.f area, p
		area = 0
		ProcedureReturn area	
	EndProcedure
	
	Procedure Normalize(Mesh)
		
		Protected i, j
		Dim Vertex.PB_MeshVertex(0)
		Dim Face.PB_MeshFace(0)
		Protected.Vector3 v2v1, v3v1, v1,v2,v3,n
		
		For j=0 To SubMeshCount(mesh)-1
			GetMeshData(Mesh, j, Vertex(),   #PB_Mesh_Vertex | #PB_Mesh_Normal , 0, MeshVertexCount(Mesh)-1)
			GetMeshData(Mesh, j, Face(),   #PB_Mesh_Face , 0, MeshIndexCount(Mesh)-1)
			
			For i = 0 To ArraySize(Vertex())
				Vertex(i)\NormalX = 0
				Vertex(i)\NormalY = 0
				Vertex(i)\NormalZ = 0
			Next
			
			For i = 0 To ArraySize(Face()) Step 3
				
				v1\x = Vertex(Face(i)\Index)\x
				v1\y = Vertex(Face(i)\Index)\y
				v1\z = Vertex(Face(i)\Index)\z
				
				v2\x = Vertex(Face(i+1)\Index)\x
				v2\y = Vertex(Face(i+1)\Index)\y
				v2\z = Vertex(Face(i+1)\Index)\z
				
				v3\x = Vertex(Face(i+2)\Index)\x
				v3\y = Vertex(Face(i+2)\Index)\y
				v3\z = Vertex(Face(i+2)\Index)\z
				
				SubVector3(v2v1, v2, v1)
				SubVector3(v3v1, v3, v1)
				
				n\x = v2v1\y * v3v1\z - v2v1\z * v3v1\y
				n\y = v2v1\z * v3v1\x - v2v1\x * v3v1\z
				n\z = v2v1\x * v3v1\y - v2v1\y * v3v1\x
				
				NormalizeVector(@n)
				
				Vertex(Face(i)\Index)\NormalX + n\x
				Vertex(Face(i)\Index)\NormalY + n\y
				Vertex(Face(i)\Index)\NormalZ + n\z
				
				Vertex(Face(i+1)\Index)\NormalX + n\x
				Vertex(Face(i+1)\Index)\NormalY + n\y
				Vertex(Face(i+1)\Index)\NormalZ + n\z
				
				Vertex(Face(i+2)\Index)\NormalX + n\x
				Vertex(Face(i+2)\Index)\NormalY + n\y
				Vertex(Face(i+2)\Index)\NormalZ + n\z
			Next
			
			For i = 0 To ArraySize(Vertex())
				n\x = Vertex(i)\NormalX
				n\y = Vertex(i)\NormalY
				n\z = Vertex(i)\NormalZ
				NormalizeVector(@n)
				Vertex(i)\NormalX = n\x
				Vertex(i)\NormalY = n\y
				Vertex(i)\NormalZ = n\z
				
			Next
			
			SetMeshData(mesh,j,Vertex(),#PB_Mesh_Vertex | #PB_Mesh_Normal , 0, MeshVertexCount(Mesh)-1)
		Next
	EndProcedure	
	
	Procedure NormalizeJointure(Mesh, n)
		
		Protected i, j
		Dim Vertex.PB_MeshVertex(0)
		Dim Face.PB_MeshFace(0)
		Protected.Vector3 n1, n2,n3
		
		For j=0 To SubMeshCount(mesh)-1
			GetMeshData(Mesh, j, Vertex(),  #PB_Mesh_Vertex | #PB_Mesh_Normal , 0, MeshVertexCount(Mesh)-1)
			
			With Vertex(i)
				i=0
				While i <= ArraySize(Vertex()) 
					n1\x = Vertex(i)\NormalX
					n1\y = Vertex(i)\NormalY
					n1\z = Vertex(i)\NormalZ
					n2\x = Vertex(i+32)\NormalX
					n2\y = Vertex(i+32)\NormalY
					n2\z = Vertex(i+32)\NormalZ						
					n3\x = (n1\x + n2\x)/2.0
					n3\y = (n1\y + n2\y)/2.0
					n3\z = (n1\z + n2\z)/2.0
					Vertex(i)\NormalX     	= n3\x
					Vertex(i)\NormalY				= n3\y
					Vertex(i)\NormalZ				= n3\z
					Vertex(i+32)\NormalX	= n3\x
					Vertex(i+32)\NormalY	= n3\y
					Vertex(i+32)\NormalZ	= n3\z							
					i + n
				Wend
				
			EndWith
			
			SetMeshData(mesh,j,Vertex(), #PB_Mesh_Normal , 0, MeshVertexCount(Mesh)-1)
		Next
	EndProcedure	
EndModule


;-Mesh Axial - Pf shadoko - 2015

EnableExplicit

Global.w ex,ey,dx,dx1,dy,dy1,nb

;###############################################################################
;###############################################################################
;###############################################################################
Structure coo2d
	x.f
	y.f
EndStructure

Procedure Bspline(Array pe.coo2d(1), Array PS.coo2d(1),nd.w)
	Protected.f t,tt
	Protected np,i,j,jj,k,c
	Protected Dim m.w(4, 4)
	Protected Dim ttt.f(4)
	np = ArraySize(pe())
	Protected Dim PS((np - 2) * nd)
	
	m(0, 0) = -1: m(1, 0) =  3: m(2, 0) = -3: m(3, 0) =  1
	m(0, 1) =  2: m(1, 1) = -5: m(2, 1) =  4: m(3, 1) = -1
	m(0, 2) = -1: m(1, 2) =  0: m(2, 2) =  1: m(3, 2) =  0
	m(0, 3) =  0: m(1, 3) =  2: m(2, 3) =  0: m(3, 3) =  0
	
	If pe(np - 1)\X = pe(1)\X And pe(np - 1)\Y = pe(1)\Y
		pe(0) = pe(np - 2): pe(np) = pe(2)
	Else
		pe(0) = pe(1):pe(np) = pe(np - 1)
	EndIf
	
	For jj = 0 To np - 3
		For i = 0 To nd - 1
			t = i / nd
			For j = 0 To 3
				ttt(j) = 0: tt = 1
				For k = 3 To 0 Step -1: ttt(j) + tt * m(j, k) / 2: tt = tt * t: Next
				PS(c)\X = PS(c)\X + ttt(j) * pe(j + jj)\X
				PS(c)\Y = PS(c)\Y + ttt(j) * pe(j + jj)\Y
			Next
			c + 1
		Next
	Next
	PS(c) = pe(np - 1)
EndProcedure

Procedure string2coo2d(Array s.coo2d(1),t.s) ;pas tres élégant !
	Protected Dim a.f(0, 0)
	Protected n
	t="0,0/"+t+"/0,0"
	ParseJSON(0, "[["+ReplaceString(t,"/","],[")+"]]")
	ExtractJSONArray(JSONValue(0), a())
	n=ArraySize(a())
	Dim s.coo2d(n)
	CopyMemory(@a(0,0),@s(0),4*2*(n+1))
EndProcedure

Procedure.f lg2D(x.f,y.f)
	ProcedureReturn Sqr(x.f*x.f+y.f*y.f)
EndProcedure

Procedure CreateAxialMesh(mesh,Array profils.coo2d(1),Array section.coo2d(1))
	Macro profilsJ()
		ar=r
		ah=h
		r=profils(j)\x
		h=profils(j)\y
		v+lg2D(r-ar,h-ah)
	EndMacro
	
	Protected i,j,r.f,h.f,ar.f,ah.f,a.f,v.f,vv.f,n,n1,m
	n=ArraySize(section()):n1=n+1
	m=ArraySize(profils())
	
	r=profils(0)\x:h=profils(0)\y:v=0
	For j=0 To m:profilsJ():Next:vv=v
	
	r=profils(0)\x:h=profils(0)\y:v=0
	CreateMesh(mesh,#PB_Mesh_TriangleList,#PB_Mesh_Dynamic)
	For j=0 To m
		profilsJ()
		For i=0 To n   
			MeshVertexPosition(section(i)\x* r,h,section(i)\y* r)
			MeshVertexTextureCoordinate(i/n,v/vv)
			MeshVertexNormal(0,0,0)
			MeshVertexColor($ffffff)
		Next
	Next
	For j=0 To m-1
		For i=0 To n-1
			MeshFace(i+j*n1,i+(j+1)*n1,(i%n1+1)+j*n1)
			MeshFace((i%n1+1)+(j+1)*n1,(i%n1+1)+j*n1,i+(j+1)*n1)
		Next
	Next
	FinishMesh(1)
	;NormalizeMesh(mesh)
	Mesh::Normalize(mesh)
	If mesh = 13 Or mesh = 10
		Mesh::NormalizeJointure(mesh,n+1)
	EndIf
	;BuildMeshTangents(Mesh)
EndProcedure

Procedure CreateAxialMeshCustom(mesh,ProfilList.s,ProfilSubDiv,sectionList.s,SectionSubDiv)
	Protected Dim profil.coo2d(0)
	Protected Dim profils.coo2d(0)
	string2coo2d(profil(),ProfilList)
	Bspline(profil(),profils(),ProfilSubDiv)
	
	Protected Dim section.coo2d(0)
	Protected Dim sections.coo2d(0)
	string2coo2d(section(),sectionList)
	Bspline(section(),sections(),SectionSubDiv)
	
	CreateAxialMesh(mesh,profils(),sections())
EndProcedure

Procedure CreateAxialMeshCircular(mesh,ProfilList.s,ProfilSubDiv=16 ,cercleSubDiv=16)
	Protected i,a.f
	Protected Dim profil.coo2d(0)
	Protected Dim profils.coo2d(0)
	string2coo2d(profil(),ProfilList)
	Bspline(profil(),profils(),ProfilSubDiv)
	
	Protected Dim section.coo2d(cercleSubDiv)
	For i=0 To cercleSubDiv:a=Radian(360/cercleSubDiv)*i:section(i)\x=Cos(a):section(i)\y=Sin(a):Next
	
	CreateAxialMesh(mesh,profils(),section())
EndProcedure
;###############################################################################
;###############################################################################
;###############################################################################

Procedure degrade(Array pal.l(1),l,c1.l,c2.l)
	Dim pal(l-1)
	CreateImage(0,l,1,32)
	StartDrawing(ImageOutput(0))
	DrawingMode(#PB_2DDrawing_Gradient)
	GradientColor(0.0,c1)
	GradientColor(1.0,c2)
	LinearGradient(0,0,l-1,0)
	Box(0,0,l,1)
	CopyMemory(DrawingBuffer(),@pal(0),l*4)
	StopDrawing()
	FreeImage(0)
EndProcedure

Procedure generematiere(num,dx,dy,c1,c2,type)
	Protected i,j,y
	Protected Dim pal.l(0):degrade(pal(),256,c1,c2)
	CreateTexture(num,dx,dy)
	StartDrawing(TextureOutput(num))
	Select type
		Case 1; point (assiette /pomme / coupe)
			For j=0 To dy-1:For i=0 To dx-1:Plot(i,j,pal(Random(255))):Next:Next
		Case 2; tissu (boite)
			For i=0 To 2000:Line(Random(dx),0,1,dy,pal(Random(127)+128)):Line(0,Random(dy),dx,1,pal(Random(127))):Next 
		Case 3; brasselet
			For i=-dx To dx:LineXY(i,0,i+dx,dy,pal(Bool(i & 30)*255)):Next 
		Case 4; vase
			For j=0 To dy-1:For i=0 To dx-1:y=((Cos(i*4*#PI/dx)*255)): Plot(i ,j,pal((j*5+y) & 255)):Next:Next 
		Case 5; verre
			Box(0,0,dx,dy,$ffffff):For j=0 To dy Step 32:Box (0,j,dx,4,$8800):Box (j,0,4,dy,$88):Next
	EndSelect 
	StopDrawing()
	CreateMaterial(num, TextureID(num))
EndProcedure

Procedure scene()
	Protected i,j,k,c,x,y,dx=8,dy=8
	
	;######################################## cameras
	;principale
	CreateCamera(0, 0, 0, 100, 100):MoveCamera(0, 1000, 500, 0, #PB_Absolute):CameraLookAt(0, 0, 100, 0):CameraBackColor(0, $333333)
	;miroir
	CreateCamera(1, 0, 0,50,50):CameraBackColor(1, $333333)
	
	CreateLight(0,$ffffff, 10000, 10000, 5000)
	AmbientColor($222222)
	;WorldShadows(#PB_Shadow_Additive,-1,$aaaaaa)
	
	;######################################## textures / material 
	CreateRenderTexture(0,CameraID(1),ex,ey)
	CreateMaterial(0, TextureID(0))
	SetMaterialColor(0,#PB_Material_DiffuseColor,$777777):MaterialBlendingMode(0,#PB_Material_Add)
	
	generematiere(1,256,256,$ff0000,$ffff00,2) :ScaleMaterial(1,0.25,0.25)
	generematiere(2,256,256,$ffcc88,$ccaa66,1)
	generematiere(3,128,256,$443300,$222200,1)
	generematiere(4,64,64,$aaaaff,$ffffaa,1)
	generematiere(5,256,256,$0000ff,$ffcc22,3)
	generematiere(6,256,256,$ffffff,$cc9999,4) :ScaleMaterial(6,0.25,0.25)
	generematiere(7,256,256,$ffffff,$ffcc00,5)
	generematiere(8,8,8,$999900,$cc0000,1)
	generematiere(9,256,256,$ff8800,$88ff88,2)  :ScaleMaterial(9,0.25,0.25)
	
	;######################################## mesh/entity
	;CreateSphere (2,100):CreateEntity(2, MeshID(2), MaterialID(1),0,100,0)
	
	;table+vitre
	CreateAxialMeshCircular(1,"500,0/0,0",8,32)
	CreateEntity(1, MeshID(1), MaterialID(0))
	CreateAxialMeshCircular(2,"500,0/0,0",1,32)
	CreateEntity(2, MeshID(2), MaterialID(3),0,-1,0)
	;coupes
	CreateAxialMeshCircular(10,"0,0/50,1/10,20/10,100/55,200/50,200/0,100",4,32)
	CreateEntity(10, MeshID(10), MaterialID(4),0,0,-300)
	CreateEntity(11, MeshID(10), MaterialID(4),200,0,-320)
	;assiette
	CreateAxialMeshCircular(12,"0,0/100,1/160,47/157,50/75,10/0,10",1,8)
	CreateEntity(12, MeshID(12), MaterialID(2),250,0,250)
	;vases
	CreateAxialMeshCircular(13,"0,0/80,1/120,150/80,250/110,300/100,300/75,250/75,20/0,20",8,32)
	CreateEntity(13, MeshID(13), MaterialID(6),-0,0,0)
	;boite
	CreateAxialMeshCircular(14,"0,0/80,1/110,70/85,140/90,140/90,150/10,160/20,190/0,200",4,4)
	CreateEntity(14, MeshID(14), MaterialID(1),-200,0,-200)
	;brasselet                              !!!! pour faire un tore, le premier point doit etre similaire au premier !!!!
	CreateAxialMeshCircular(15,"45,15/45,0/55,15/45,30/45,15",4,32)
	CreateEntity(15, MeshID(15), MaterialID(5),400,0,100)
	;verre
	CreateAxialMeshCircular(16,"0,0/50,1/60,150/55,150/45,10/0,10",1,32)
	CreateEntity(16, MeshID(16), MaterialID(7),0,0,200)
	;pommes
	CreateAxialMeshCircular(17,"0,10/20,0/45,30/50,80/20,100/2,90/1,100/0,105",4,32)
	CreateEntity(17, MeshID(17), MaterialID(8),230,10+10,300)
	CreateEntity(18, MeshID(17), MaterialID(8),320,10+10,250)
	CreateEntity(19, MeshID(17), MaterialID(8),260,10+10,170)
	;truc (custom (ici on definit la section))
	CreateAxialMeshCustom(20,"0,0/56,1/62,34/64,40/61,43/58,40/60,34/52,6/0,4",4,"-0.8,0/-1,-1/1,-1/0.8,0/1,1/-1,1/-0.8,0",8)
	CreateEntity(20, MeshID(20), MaterialID(9),300,0,-100)
	
EndProcedure


Procedure rendermirror2(mesh,camP,camM)
	Protected c,n,mx,my
	Protected.f xp,yp,zp,xd,yd,zd
	Protected Dim T.PB_MeshVertex(0)
	
	xp=CameraX(camP):xd=CameraDirectionX(camP)
	yp=CameraY(camP):yd=CameraDirectionY(camP)
	zp=CameraZ(camP):zd=CameraDirectionZ(camP)
	CameraDirection(camM,xd,-yd,zd)
	MoveCamera(camM,xp,-yp,zp,#PB_Absolute)
	mx=ex   ;CameraViewWidth (camM) ;marche pas,
	my=ey		;CameraViewHeight(camM) ;pas compris !
	n=MeshVertexCount(mesh)-1
	GetMeshData(mesh,0,t(),#PB_Mesh_Vertex|#PB_Mesh_UVCoordinate ,0,n)
	For c=0 To n
		With t(c)
			\u=  CameraProjectionX(1,\x, 0,\z)/mx
			\v=  CameraProjectionY(1,\x, 0,\z)/my
		EndWith
	Next
	SetMeshData(mesh,0,t(),#PB_Mesh_Vertex|#PB_Mesh_UVCoordinate,0,MeshVertexCount(mesh)-1)
EndProcedure


Define.f KeyX, KeyY,keyz, MouseX, MouseY,time,v,a,x,y,z,r.l
Define i,j,c,px,py,p,shadingmode
InitEngine3D()   
InitSprite()
InitKeyboard()
InitMouse()
OpenWindow(0, 0, 0, 0,0, " Mesh Axial",#PB_Window_Maximize)
ex=WindowWidth (0,#PB_Window_InnerCoordinate)
ey=WindowHeight(0,#PB_Window_InnerCoordinate)
OpenWindowedScreen(WindowID(0), 0, 0, ex, ey, 0, 0, 0)

Macro DT(t1,t2)
	DrawText(4,p,t1)
	DrawText(40,p,t2)
	p+16
EndMacro
CreateSprite(0,120,170,#PB_Sprite_AlphaBlending)
StartDrawing(SpriteOutput(0))
DrawingMode(#PB_2DDrawing_AlphaClip|#PB_2DDrawing_Outlined )
Box(0,0,120,170)
BackColor($0000ff)
dt("Déplacements:","")
dt("[Left]","")
dt("[Right]","")
dt("[Up]","")
dt("[Down]","")
dt("Mouse+wheel","")
dt("","")
dt("Commandes:","")
dt("[F1]","fil de fer")
dt("[Esc]","Quitter")
StopDrawing()

;WorldShadows(#PB_Shadow_Modulative)
scene()

Repeat   
	WindowEvent() 
	ExamineMouse()
	MouseX = -MouseDeltaX() *  0.05
	MouseY = -MouseDeltaY() *  0.05
	ExamineKeyboard()
	keyx=(-Bool(KeyboardPushed(#PB_Key_Left)<>0)+Bool(KeyboardPushed(#PB_Key_Right)<>0))*4
	keyz=(-Bool(KeyboardPushed(#PB_Key_Down)<>0)+Bool(KeyboardPushed(#PB_Key_Up   )<>0))*4+MouseWheel()*50
	RotateCamera(0, MouseY, MouseX, 0, #PB_Relative):MoveCamera  (0, KeyX, keyy, -keyz) 
	If KeyboardReleased(#PB_Key_F1)
		If shadingmode=#PB_Material_Wireframe:shadingmode=#PB_Material_Solid:Else:shadingmode=#PB_Material_Wireframe:EndIf
		For i=0 To 9:MaterialShadingMode(i, shadingmode):Next
	EndIf 
	rendermirror2(1,0,1)
	time+RenderWorld()/200
	DisplayTransparentSprite(0, 8,8,128)
	FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
End
Dernière modification par comtois le lun. 13/juil./2015 20:25, modifié 2 fois.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: Démo - mesh axial

Message par comtois »

nouvelle procédure dans le module. Elle permet de récupérer les normales dans la jointure, en fait la moyenne et l'affecte aux vertices concernés de la jointure.

Code : Tout sélectionner

	Procedure NormalizeJointure(Mesh, n)
		
		Protected i, j
		Dim Vertex.PB_MeshVertex(0)
		Dim Face.PB_MeshFace(0)
		Protected.Vector3 n1, n2,n3
		
		For j=0 To SubMeshCount(mesh)-1
			GetMeshData(Mesh, j, Vertex(),  #PB_Mesh_Vertex | #PB_Mesh_Normal , 0, MeshVertexCount(Mesh)-1)
			
			With Vertex(i)
				i=0
				While i <= ArraySize(Vertex()) 
					n1\x = Vertex(i)\NormalX
					n1\y = Vertex(i)\NormalY
					n1\z = Vertex(i)\NormalZ
					n2\x = Vertex(i+32)\NormalX
					n2\y = Vertex(i+32)\NormalY
					n2\z = Vertex(i+32)\NormalZ						
					n3\x = (n1\x + n2\x)/2.0
					n3\y = (n1\y + n2\y)/2.0
					n3\z = (n1\z + n2\z)/2.0
					Vertex(i)\NormalX     	= n3\x
					Vertex(i)\NormalY				= n3\y
					Vertex(i)\NormalZ				= n3\z
					Vertex(i+32)\NormalX	= n3\x
					Vertex(i+32)\NormalY	= n3\y
					Vertex(i+32)\NormalZ	= n3\z							
					i + n
				Wend
				
			EndWith
			
			SetMeshData(mesh,j,Vertex(), #PB_Mesh_Normal , 0, MeshVertexCount(Mesh)-1)
		Next
	EndProcedure	
J'ai mis ton code à jour avec le module dans le post précédent.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: Démo - mesh axial

Message par djes »

Cool, bravo ! :)
Répondre