Antin blogi

Tietokonegrafiikkablogi

 

3D projektio Flashilla.

 

Tiedän, olen jo tässä blogissa käsitellyt tätä aihetta, mutta viimeksi esittelin alkeellisemman joskin helposti ymmärrettävissä olevan tavan projisoida 3d pisteitä 2d tasolle. Tällä kertaa kirjoitan "oikeasta" perspektiiviprojektiosta projektiomatriisin avulla.

Itse perspektiiviprojektiomatriisi on harvinaisen monimutkainen ja vaikeasti ymmärrettävä kasa epämääräisiä numeroita. Mistä numerot tulevat ja miksi käyttää juuri niitä laskuja, jotka tässä esittelen on toissijaista tietoa. Tätä tietoa ei tarvitse ellei aio tehdä jotain todella vänkää projektiomatriisilla. Pinnan alla piilevästä matematiikasta kiinnostuneille suosittelen tätä saittia http://www.codeguru.com/cpp/misc/misc/math/article.php/c10123. Tässä artikellissa keskitytään siihen miten oman projektiomatriisi saadaan implementoitua omaan koodiin.

Kameran "näkökenttä" eli view frustum on pyramiidin muotoinen alue (volume), jonka sisällä on kaikki se kama jonka kamera näkee. Ulkopuolelle jäävä roju clipataan pois, jolloin puhutaan view frustum cullingista. Emme paneudu tähän aiheeseen nyt, mutta halusin mainita millä nimellä aiheesta löytää lisää tietoa.

Kuvassa näkyy kameran view frustum.

Perspektiiviprojektiomatriisin avulla projisoidessa ei projisoida pisteitä 2d tasolle vaan uuteen "alueeseen" jota kutsutaan canonical view volume (tälle on varmasti jokin pyöristyttävä suomennoskin). Alue on laatikko kokoa [-1,-1,0] - [1,1,1]. Eli arvot tulevat välille -1.0 - 1.0 paitsi Z arvo, jonka on välillä 0.0 - 1.0. Canonical view volume edustaa "3d-monitoria". 2D X ja Y arvot saadaan mapattua ruudun kordinaatteihin kertomalla X resoluution leveydellä ja Y resoluution korkeudella.

Flashissa voimme käyttää projektiomatriisia näin.

var xy:Vector3D = Utils3D.projectVector(m_projectionMatrix, v1);

Eli Utils3D luokan projectVector projisoi vektorin annetulla matriisilla. Tuloksena on Vector3D, jonka X ja Y arvot ovat 3d-pisteen paikka 2d avaruudessa. Itse funktio, joka luo m_projectionMatrix matriisin näyttää tältä.

private function createProjectionMatrix():void
{
    m_center = new Point( 400, 300);            
    m_focalLength = m_screenWidth * 0.5 /
        Math.tan( m_fieldOfView * 0.5 );
    m_center = new Point( m_screenWidth / 2,
        m_screenHeight / 2 );
    m_projectionMatrix = new Matrix3D();
    m_projectionMatrix.identity();
    var fov:Number = Math.PI * m_fieldOfView / 180.0;
    var a:Number = 1.0 / (m_screenWidth / m_screenHeight) /
        Math.tan( fov * 0.5 );
    var b:Number = 1.0 / Math.tan( fov * 0.5 );
    var c:Number = m_zFar / (m_zFar - m_zNear);
    var d:Number = 1.0;
    var e:Number = -c * m_zNear;
    var pm:Vector. = m_projectionMatrix.rawData;
    pm[0] = a;        pm[1] = 0;        pm[2] = 0;        pm[3] = 0;
    pm[4] = 0;      pm[5] = b;        pm[6] = 0;        pm[7] = 0;
    pm[8] = 0;      pm[9] = 0;        pm[10] = c;        pm[11] = d;
    pm[12] = 0;     pm[13] = 0;        pm[14] = e;        pm[15] = 0;
    m_projectionMatrix.rawData = pm;
}
//-----------------------------------------------------------------------

Melko pelottavan näköinen funktio, mutta onneksi tämän täydellistä ymmärtämistä ei tarvita. Lähinnä tärkeitä asioita ovat Field Of View ja ruudun koko.

Eli jos nyt teemme 3d mallin ja projisoimme sen tällä matriisilla saisimme mallin joka on hyvin pieni. Kaikki verteksit olisivat -1 - 1 alueella.

Verteksit pitää nyt skaalaa sopivaksi kulloiseenkin resolutioon. Eli verteksin 2d X arvo on X * (resoX/2) ja Y arvo on Y * (resoY/2). Resolutio jaetaan kahdella koska verteksien arvot ovat -1.0 - 1.0 eikä 0.0 - 1.0.

Näin mallisi on oikean kokoinen. Tosin on turhaa jakaa ja kertoa arvoja joka verteksille erikseen, koska tämä voidaan tehdä suoraan matriisissa. Kts. uusi createProjectionMatrix() funktio.

private function createProjectionMatrix():void
{
    m_center = new Point( 400, 300);            
    m_focalLength = m_screenWidth * 0.5 /
        Math.tan( m_fieldOfView * 0.5 );
    m_center = new Point( m_screenWidth / 2,
        m_screenHeight / 2 );
    m_projectionMatrix = new Matrix3D();
    m_projectionMatrix.identity();
    var fov:Number = Math.PI * m_fieldOfView / 180.0;
    var a:Number = 1.0 / (m_screenWidth / m_screenHeight) /
        Math.tan( fov * 0.5 ) * m_center.x;
    var b:Number = 1.0 / Math.tan( fov * 0.5 ) * m_center.y;
    var c:Number = m_zFar / (m_zFar - m_zNear);
    var d:Number = 1.0;
    var e:Number = -c * m_zNear;
    var pm:Vector. = m_projectionMatrix.rawData;
    pm[0] = a;        pm[1] = 0;        pm[2] = 0;        pm[3] = 0;
    pm[4] = 0;      pm[5] = b;        pm[6] = 0;        pm[7] = 0;
    pm[8] = 0;      pm[9] = 0;        pm[10] = c;        pm[11] = d;
    pm[12] = 0;     pm[13] = 0;        pm[14] = e;        pm[15] = 0;
    m_projectionMatrix.rawData = pm;
}
//-----------------------------------------------------------------------

Nyt mallisi on heti oikean kokoinen voit rendaa sen ruudulle.

Esimerkkiohjelma renderoi kuvan mukaisen mallin ruudulle projisoiden pisteet yllä olevan projektiomatriisin kanssa.

Lataa lähdekoodi

Responses (26) to "3D projektio Flashilla."

  1.  

    Cool,

    Siistiä rompetta... millos siirryt kokonaan flash propelipääksi?

    Ootko muuten ihan ite värkänny blogin ilmeen?

    --pole

  2.  

    Kuka tietää mihin elo heittelee näinä päivinä, ehkä sitä joskus astuu Flashin ihmeelliseen maailmaan ihan elääkseen.

    Blogin ilme on OpenBlogin mukana tullut leiska. Tosin pitää varmaan tää OpenBlog heivaa mäkeen ja asentaa joku oikea CMS ja tehdä koko sivusto samalla leiskalla.

  3.  

    TucwE5 twsmijitmhdg, qbedgzdouixk, jjfwukmdwfnh, http://kzurvjptxxyt.com/

  4.  
  5.  

    If you are passing through the moderate or severe phases of pain Tramadol may prove to be an instant reliever. accutane 8688 order xanax lmgkd order acomplia laughing

  6.  

    2GUT0W eovhrwvxfygp, nrbnecsdbbqx, okvrrzujkqmz, http://qzejxtqcveom.com/

  7.  

    cialis 393 prednisone tonguePP soma 8-))) viagra 326 auto insurance wqqkeq

  8.  
  9.  
  10.  

    ambien 75699 propecia 8-[[ meridia 8[ buy acomplia :O

  11.  

    viagra %-(

  12.  
  13.  
  14.  
  15.  

    1NO6Wn djiuiopexmxb, ontewmsmmibg, oqdxlelnpxeq, http://tryrpdqxnawl.com/

  16.  

    ZiRNL9 guhdxtcoizmr, aramuhshshfb, lrgvpowrrsin, http://gjtqxmojseof.com/

  17.  
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  

    I found that Avira when tried on a pendrive used from this laptop shows virus. while McAfee doesnt detect any. could anybody tell me about the dependability on McAfee santoramaa

  24.  

    в конце концов: благодарю... а82ч

  25.  
  26.  

    pP69Q2 xfolvrskjwac, omasqcddnynz, pmmteqtxhfqo, http://bgolxzjrjkod.com/

Leave a reply

Feel free to share your thoughts about this entry.

Nickname
Email
Website
Comment