Commentçamarche.net
CodeS-SourceS
Rechercher un code, un tuto, une réponse

M3d (moteur 3d pour mirc)

4/5 (9 avis)

Vue 7 931 fois - Téléchargée 208 fois

Description

ceci est un moteur 3D pour mirc, il n'utilise aucune api 3D donc est tres lent
c'est pour cela que je l'est recoder en C avec SDL
http://www.cppfrance.com/code.aspx?ID=21731
Il vous permetra de coprendre les base de la 3D
-rotation (trigo)
-chargement de map (loader fichier)
-eclairage (vecteur normal)
-...

Source / Exemple :


;m3D V1.2 par aerith "fabidou_aeris@hotmail.com"
;Pour une utilisation partiel ou complette dans un script me prevenir svp

;##htable m3d.option##
;1 : zoom <n>
;2 : cliping <n>
;3 : camera <x> <y> <z>
;4 : rotate <angle> <x> <y> <z>
;5 : planar <0|1>
;6 : allface <0|1>

;##interface utilisateur##
alias m3d.option hadd m3d.option $1-

;##initialisation moteur, creation de la htable m3d.option##
;/init <zoom> <cliping> <camera>
alias m3d.init {
  hfree -w m3d.*
  hmake m3d.option 10
  hadd m3d.option zoom $1
  hadd m3d.option cliping $2
  hadd m3d.option camera $3 $4 $5
  hadd m3d.option rotate 0 0 0 0
  hadd m3d.option planar 0
  hadd m3d.option allface 0
}

;##charge un .ase dans le moteur##
alias m3d.loader {
  if (!$exists($1-)) { echo fichier inexistant | halt }
  set %m3d.numvertex $gettok($read($1-,w,*MESH_NUMVERTEX*),2,32)
  set %m3d.numface $gettok($read($1-,w,*MESH_NUMFACES*),2,32)
  hfree -w m3d.mesh.*
  hmake m3d.mesh.vertex.X %m3d.numvertex
  hmake m3d.mesh.vertex.Y %m3d.numvertex
  hmake m3d.mesh.vertex.Z %m3d.numvertex

  hmake m3d.mesh.vertex.out %m3d.numvertex

  hmake m3d.mesh.face.A %m3d.numface
  hmake m3d.mesh.face.B %m3d.numface
  hmake m3d.mesh.face.C %m3d.numface

  hmake m3d.mesh.normal.X %m3d.numface
  hmake m3d.mesh.normal.Y %m3d.numface
  hmake m3d.mesh.normal.Z %m3d.numface

  hmake m3d.mesh.centre.X %m3d.numface
  hmake m3d.mesh.centre.Y %m3d.numface
  hmake m3d.mesh.centre.Z %m3d.numface

  hmake m3d.mesh.centre.out %m3d.numface

  ;merci visionz :p
  if ($fopen(m3d)) .fclose m3d
  .fopen m3d $shortfn($1-)
  var %no_ligne = 1, %t = $lines($1-), %ligne, %cur
  while (%no_ligne <= %t) {
    %ligne = $replace($fread(m3d),*,$chr(32),$chr(9),$chr(32),:,$chr(32),",$chr(32))
    %cur = $gettok(%ligne,1,32)
    var %a
    if (%cur == MESH_VERTEX) {
      %a = $calc($gettok(%ligne,2,32) + 1)
      hadd m3d.mesh.vertex.X %a $gettok(%ligne,3,32)
      hadd m3d.mesh.vertex.Y %a $gettok(%ligne,4,32)
      hadd m3d.mesh.vertex.Z %a $gettok(%ligne,5,32)
    }
    elseif (%cur == MESH_FACE) {
      %a = $calc($gettok(%ligne,2,32) + 1)
      hadd m3d.mesh.face.A %a $calc($gettok(%ligne,4,32) + 1)
      hadd m3d.mesh.face.B %a $calc($gettok(%ligne,6,32) + 1)
      hadd m3d.mesh.face.C %a $calc($gettok(%ligne,8,32) + 1)
    }
    elseif (%cur == MESH_FACENORMAL) {
      %a = $calc($gettok(%ligne,2,32) + 1)
      hadd m3d.mesh.normal.X %a $gettok(%ligne,3,32)
      hadd m3d.mesh.normal.Y %a $gettok(%ligne,4,32)
      hadd m3d.mesh.normal.Z %a $gettok(%ligne,5,32)
    }
    inc %no_ligne 1
  }
  .fclose m3d

  var %no_ligne 1
  while (%no_ligne <= %m3d.numface) {
    hadd m3d.mesh.centre.X %no_ligne $calc(($hget(m3d.mesh.vertex.X,$hget(m3d.mesh.face.A)) + $hget(m3d.mesh.vertex.X,$hget(m3d.mesh.face.B)) + $hget(m3d.mesh.vertex.X,$hget(m3d.mesh.face.C))) / 3)
    hadd m3d.mesh.centre.Y %no_ligne $calc(($hget(m3d.mesh.vertex.Y,$hget(m3d.mesh.face.A)) + $hget(m3d.mesh.vertex.Y,$hget(m3d.mesh.face.B)) + $hget(m3d.mesh.vertex.Y,$hget(m3d.mesh.face.C))) / 3)
    hadd m3d.mesh.centre.Z %no_ligne $calc(($hget(m3d.mesh.vertex.Z,$hget(m3d.mesh.face.A)) + $hget(m3d.mesh.vertex.Z,$hget(m3d.mesh.face.B)) + $hget(m3d.mesh.vertex.Z,$hget(m3d.mesh.face.C))) / 3)
    inc %no_ligne
  }
}

;##calcul##
alias m3d.calcul {
  if (!$window($1)) { echo fenetre inexistante | halt }
  var %zoom = $hget(m3d.option,zoom)
  var %cliping = $hget(m3d.option,cliping)
  var %cm = $hget(m3d.option,camera)
  var %cmx = $gettok(%cm,1,32)
  var %cmy = $gettok(%cm,2,32)
  var %cmz = $gettok(%cm,3,32)
  var %rotate = $hget(m3d.option,rotate)
  var %angle = $gettok(%rotate,1,32)
  var %x = $gettok(%rotate,2,32)
  var %y = $gettok(%rotate,3,32)
  var %z = $gettok(%rotate,4,32)
  var %cosT = $cos(%angle)
  var %sinT = $sin(%angle)
  var %cosT1 = $calc(1 - %cosT)
  var %cosT2 = $calc(1 + %cosT)
  var %xs = $calc(%x * %sinT)
  var %ys = $calc(%y * %sinT)
  var %zs = $calc(%z * %sinT)
  var %ex1 = $calc(%cosT + %cosT1 * (%x * %x))
  var %ex2 = $calc(%cosT1 * %x * %y - %zs)
  var %ex3 = $calc(%cosT1 * %x * %z + %ys)
  var %ey1 = $calc(%cosT2 * %x * %y + %zs)
  var %ey2 = $calc(%cosT + %cosT1 * (%y * %y))
  var %ey3 = $calc(%cosT1 * %y * %z - %xs)
  var %ez1 = $calc(%cosT2 * %x * %z - %ys)
  var %ez2 = $calc(%cosT1 * %y * %z + %xs)
  var %ez3 = $calc(%cosT + %cosT1 * (%z * %z))

  var %no_ligne 1
  while (%no_ligne <= %m3d.numvertex) {
    var %vx = $hget(m3d.mesh.vertex.X,%no_ligne)
    var %vy = $hget(m3d.mesh.vertex.Y,%no_ligne)
    var %vz = $hget(m3d.mesh.vertex.Z,%no_ligne)
    hadd m3d.mesh.vertex.X %no_ligne $calc(%ex1 * %vx + %ex2 * %vy + %ex3 * %vz)
    hadd m3d.mesh.vertex.Y %no_ligne $calc(%ey1 * %vx + %ey2 * %vy + %ey3 * %vz)
    hadd m3d.mesh.vertex.Z %no_ligne $calc(%ez1 * %vx + %ez2 * %vy + %ez3 * %vz)

    hadd m3d.mesh.vertex.out %no_ligne $calc(($hget(m3d.mesh.vertex.X,%no_ligne) + %cmx) * %zoom / (($hget(m3d.mesh.vertex.Z,%no_ligne) + %cmz) / %cliping) + ($window($1).w / 2)) $calc(($hget(m3d.mesh.vertex.Y,%no_ligne) + %cmy) * %zoom / (($hget(m3d.mesh.vertex.Z,%no_ligne) + %cmz) / %cliping) + ($window($1).h / 2))

    inc %no_ligne
  }

  var %no_ligne 1
  while (%no_ligne <= %m3d.numface) {
    var %vx = $hget(m3d.mesh.normal.X,%no_ligne)
    var %vy = $hget(m3d.mesh.normal.Y,%no_ligne)
    var %vz = $hget(m3d.mesh.normal.Z,%no_ligne)
    hadd m3d.mesh.normal.X %no_ligne $calc(%ex1 * %vx + %ex2 * %vy + %ex3 * %vz)
    hadd m3d.mesh.normal.Y %no_ligne $calc(%ey1 * %vx + %ey2 * %vy + %ey3 * %vz)
    hadd m3d.mesh.normal.Z %no_ligne $calc(%ez1 * %vx + %ez2 * %vy + %ez3 * %vz)

    hadd m3d.mesh.centre.X %no_ligne $calc(($hget(m3d.mesh.vertex.X,$hget(m3d.mesh.face.A,%no_ligne)) + $hget(m3d.mesh.vertex.X,$hget(m3d.mesh.face.B,%no_ligne)) + $hget(m3d.mesh.vertex.X,$hget(m3d.mesh.face.C,%no_ligne))) / 3)
    hadd m3d.mesh.centre.Y %no_ligne $calc(($hget(m3d.mesh.vertex.Y,$hget(m3d.mesh.face.A,%no_ligne)) + $hget(m3d.mesh.vertex.Y,$hget(m3d.mesh.face.B,%no_ligne)) + $hget(m3d.mesh.vertex.Y,$hget(m3d.mesh.face.C,%no_ligne))) / 3)
    hadd m3d.mesh.centre.Z %no_ligne $calc(($hget(m3d.mesh.vertex.Z,$hget(m3d.mesh.face.A,%no_ligne)) + $hget(m3d.mesh.vertex.Z,$hget(m3d.mesh.face.B,%no_ligne)) + $hget(m3d.mesh.vertex.Z,$hget(m3d.mesh.face.C,%no_ligne))) / 3)

    hadd m3d.mesh.centre.out %no_ligne $calc(($hget(m3d.mesh.centre.X,%no_ligne) + %cmx) * %zoom / (($hget(m3d.mesh.centre.Z,%no_ligne) + %cmz) / %cliping) + ($window($1).w / 2)) $calc(($hget(m3d.mesh.centre.Y,%no_ligne) + %cmy) * %zoom / (($hget(m3d.mesh.centre.Z,%no_ligne) + %cmz) / %cliping) + ($window($1).h / 2))

    inc %no_ligne
  }
}

;##rendu##
alias m3d.render {
  var %ticks = $ticks
  var %a
  drawrect -nrf $1 0 1 0 0 $window($1).w $window($1).h
  var %no_ligne 1
  var %cm = $hget(m3d.option,camera)
  var %cmx = $gettok(%cm,1,32)
  var %cmy = $gettok(%cm,2,32)
  var %cmz = $gettok(%cm,3,32)
  var %cmsqrt = $sqrt($calc((%cmx * %cmx) + (%cmy * %cmy) + (%cmz * %cmz)))
  while (%no_ligne <= %m3d.numface) {
    if (($hget(m3d.mesh.normal.Z,%no_ligne) < 0) || ($hget(m3d.option,allface) == 1)) {
      %a = $sqrt($abs($calc((%cmx - $hget(m3d.mesh.centre.X, %no_ligne)) * (%cmx - $hget(m3d.mesh.centre.X, %no_ligne)))) + $abs($calc((%cmy - $hget(m3d.mesh.centre.Y, %no_ligne)) * (%cmy - $hget(m3d.mesh.centre.Y, %no_ligne)))) + $abs($calc((%cmz - $hget(m3d.mesh.centre.Z, %no_ligne)) * (%cmz - $hget(m3d.mesh.centre.Z, %no_ligne)))))
      %a = $calc($hget(m3d.mesh.normal.Z,%no_ligne) * (%a / %cmsqrt) * -255)
      echo - %a

      drawline -n $1 $rgb(%a,%a,%a) 1 $hget(m3d.mesh.vertex.out,$hget(m3d.mesh.face.A,%no_ligne)) $hget(m3d.mesh.vertex.out,$hget(m3d.mesh.face.B,%no_ligne)) $hget(m3d.mesh.vertex.out,$hget(m3d.mesh.face.C,%no_ligne)) $hget(m3d.mesh.vertex.out,$hget(m3d.mesh.face.A,%no_ligne))

      if ($hget(m3d.option,planar) == 1) drawfill -nr $1 $rgb(%a,%a,%a) 16777215 $hget(m3d.mesh.centre.out,%no_ligne)
    }
    inc %no_ligne
  }
  drawtext -bnr $1 16777215 0 tahoma 15 5 5 vertex : %m3d.numvertex , faces : %m3d.numface , fps : $int($calc(1000 / ($ticks - %ticks)))
  drawtext -bnr $1 16777215 0 tahoma 15 5 22 camera : tx ty tz $hget(m3d.option,camera) , an rx ry rz $hget(m3d.option,rotate) , zoom $hget(m3d.option,zoom) , cliping $hget(m3d.option,cliping)
  drawline $1
}

;##fermeture du moteur##
alias m3d.fermer {
  hfree -w m3d.*
  unset %m3d.*
}

Conclusion :


pour l'installer :
-taper alt + R
-ensuite menu File / Load
-et charger m3d.mrc et test.mrc contenu dans le repertoire m3d

pout lancer une demo :
-taper /test dans mirc et choisissez la mesh .ase a charger dans le repertoire
mesh .ase, apres un cour instant l'objet se met a tourner
-taper /test2 choisissez une map et utiliser les touches pour deplacer la camera
2 : rx+
8 : rx-
4 : ry+
6 : ry-
1 : rz+
3 : rz-
gauche : tx+
droite : tx-
ctrl droit : ty+
µ : ty-
haut : tz+
bas : tz-
+ : zoom+
- : zoom-
/ : clip+
  • : clip-


le moteur fonction grace a tres peut de fonctions
-permet de configurer le moteur
/m3d.option <option...>
<option> :
zoom <n>
cliping <n>
camera <x> <y> <z>
rotate <angle> <x> <y> <z>
light <0|1>
allface <0|1>

-initialise le moteur
/m3d.init <zoom> <cliping> <camera x y z>

-charge un .ase dans le moteur
/m3d.loader <fihier>

-effectue tout les calcul avec les parametre configurer
/m3d.calcul <fenetre>

-rendu de la scene
/m3d.render <fenetre>

-fermeture du moteur
/m3d.fermer

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.