Page 1 of 1

Kolmiulotteinen kuutio

Posted: Mon Dec 02, 2013 9:02 pm
by CosmoConsole
Netistä löysin koodia, jolla saa piirrettyä 3D-kuution - en varma millä kielellä - mutta päätin portata koodin CoolBasicia varten ja tulos oli yllättävän hyvä. Sain aikaan itse myös wireframe-piirtotoiminnon, eli kuution voi piirtää kahdeksalla pisteellä, tai wireframena.

Code: Select all

SCREEN 800, 600

Function IIf(cond,truev,falsev)
 If cond Then
  Return truev
 Else
  Return falsev
 EndIf
EndFunction

Scale# = 1
Size = 5
Mode = 0
DMode = 0
CamX = 0
CamY = 0
CamZ = 300
MoveX = 0
MoveY = 0
MoveZ = 0
AngleX = 0
AngleY = 0
AngleZ = 0
ARot = False
PivX = 0
PivY = 0
PivZ = 0
Dim X (8)
Dim Y (8)
Dim Z (8)
Dim TX (8)
Dim TY (8)
I = 60
For j = 1 To 8
 X (j) = I * IIf(j>4,-1,1)
 Y (j) = I * IIf((j Mod 4)>1,-1,1)
 Z (j) = I * IIf((j Mod 2),-1,1)
Next j
Repeat
 For N = 1 To 8
  XD = X (N) - PivX
  YD = Y (N) - PivY
  ZD = Z (N) - PivZ
  
  ZX = XD*Cos(ANGLEZ) - YD*Sin(ANGLEZ) - XD
  ZY = XD*Sin(ANGLEZ) + YD*Cos(ANGLEZ) - YD
  
  YX = (XD+ZX)*Cos(AngleY) - ZD*Sin(AngleY) - (XD+ZX)
  YZ = (XD+ZX)*Sin(AngleY) + ZD*Cos(AngleY) - ZD
  
  XY = (YD+ZY)*Cos(AngleX) - (ZD+YZ)*Sin(AngleX) - (YD+ZY)
  XZ = (YD+ZY)*Sin(AngleX) + (ZD+YZ)*Cos(AngleX) - (ZD+YZ)
  
  XROTOFFSET = YX+ZX
  YROTOFFSET = ZY+XY
  ZROTOFFSET = XZ+YZ
  
  If Mode = 0 Then
   SX = ( X (N) + XROTOFFSET + CamX ) / Scale + MoveX
   SY = ( Y (N) + YROTOFFSET + CamY ) / Scale + MoveY
  Else
   SZ = ( Z (N) + ZROTOFFSET + CamZ )
   SX = ( X (N) + XROTOFFSET + CamX ) / SZ / Scale + MoveX
   SY = ( Y (N) + YROTOFFSET + CamY ) / SZ / Scale + MoveY
  EndIf
  Color cbWhite
  If Mode = 0 Then
   If Not DMode Then
    Circle SX + 400, SY + 300, Size / Scale
   Else
    TX (N-1) = SX + 400
    TY (N-1) = SY + 300
   EndIf
  Else
   PZ = (Z (N) + ZROTOFFSET + CamZ)
   Circle SX + 400, SY + 300, Size / PZ / Scale
   
   PX = ( ( PivX + CamX ) / ( PivZ + CamZ ) ) / Scale + MoveX + 400
   PY = ( ( PivY + CamY ) / ( PivZ + CamZ ) ) / Scale + MoveY + 300
   Dot PX, PY
  EndIf
 Next N
 
 FG = 1 + (KeyDown(cbkeylcontrol) * 3)
 
 If KeyDown(cbKeyLeft) Then MoveX = MoveX - (2 * FG)
 If KeyDown(cbKeyRight) Then MoveX = MoveX + (2 * FG)
 If KeyDown(cbKeyUp) Then MoveY = MoveY - (2 * FG)
 If KeyDown(cbKeyDown) Then MoveY = MoveY + (2 * FG)
 If KeyDown(cbKeyO) Then Scale# = Scale# * 1.02
 If KeyDown(cbKeyP) Then Scale# = Scale# / 1.02
 
 If KeyDown(cbKeyQ) Then AngleY = AngleY - FG
 If KeyDown(cbKeyE) Then AngleY = AngleY + FG
 If KeyDown(cbKeyW) Then AngleX = AngleX - FG
 If KeyDown(cbKeyS) Then AngleX = AngleX + FG
 If KeyDown(cbKeyA) Then AngleZ = AngleZ - FG
 If KeyDown(cbKeyD) Then AngleZ = AngleZ + FG
 
 If KeyDown(cbKeyF) Then PivX = PivX - (2 * FG)
 If KeyDown(cbKeyH) Then PivX = PivX + (2 * FG)
 If KeyDown(cbKeyT) Then PivY = PivY - (2 * FG)
 If KeyDown(cbKeyG) Then PivY = PivY + (2 * FG)
 If KeyDown(cbKeyR) Then PivZ = PivZ - (2 * FG)
 If KeyDown(cbKeyY) Then PivZ = PivZ + (2 * FG)
 
 If KeyDown(cbKey1) Then CamX = CamX - (4 * FG)
 If KeyDown(cbKey2) Then CamX = CamX + (4 * FG)
 If KeyDown(cbKey3) Then CamY = CamY - (4 * FG)
 If KeyDown(cbKey4) Then CamY = CamY + (4 * FG)
 If KeyDown(cbKey5) Then CamZ = CamZ - (4 * FG)
 If KeyDown(cbKey6) Then CamZ = CamZ + (4 * FG)
 
 If ARot Then AngleY = AngleY + FG
 If ARot Then AngleX = AngleX - FG
 If ARot Then AngleZ = AngleZ - FG
 
 If DMode Then
  Color 128, 128, 128
  Line TX (4), TY (4), TX (2), TY (2)
  Line TX (0), TY (0), TX (7), TY (7)
  Line TX (0), TY (0), TX (1), TY (1)
  Line TX (2), TY (2), TX (3), TY (3)
  Line TX (4), TY (4), TX (5), TY (5)
  Line TX (7), TY (7), TX (6), TY (6)
  Line TX (0), TY (0), TX (6), TY (6)
  Line TX (4), TY (4), TX (3), TY (3)
  Line TX (2), TY (2), TX (5), TY (5)
  Line TX (7), TY (7), TX (1), TY (1)
  Line TX (3), TY (3), TX (5), TY (5)
  Line TX (6), TY (6), TX (1), TY (1)
  Color 255, 255, 255
  Line TX (0), TY (0), TX (4), TY (4)
  Line TX (0), TY (0), TX (2), TY (2)
  Line TX (4), TY (4), TX (7), TY (7)
  Line TX (2), TY (2), TX (6), TY (6)
  Line TX (0), TY (0), TX (3), TY (3)
  Line TX (3), TY (3), TX (1), TY (1)
  Line TX (2), TY (2), TX (1), TY (1)
  Line TX (4), TY (4), TX (6), TY (6)
  Line TX (7), TY (7), TX (5), TY (5)
  Line TX (6), TY (6), TX (5), TY (5)
  Line TX (3), TY (3), TX (7), TY (7)
  Line TX (1), TY (1), TX (5), TY (5)
 EndIf
 
 If KeyHit(cbKeySpace) Then
  If Mode = 0 Then
   Mode = 1
   Scale# = Scale# / CamZ
  Else
   Mode = 0
   Scale# = Scale# * CamZ
  EndIf
 EndIf
 If KeyHit(cbKeyReturn) Then
  ARot = Not ARot
 EndIf
 If KeyHit(cbKeyBackspace) Then
  DMode = Not DMode
 EndIf 
 DrawScreen
Forever
Seuraavat näppäimet toimivat (lista spoilerissa, koska pitkä):
Askelpalautin (backspace) - Vaihda piste- ja viiva (wireframe) piirtotilan välillä.
Palautusnäppäin (enter/return) - Kytke päälle/pois päältä automaattinen pyöritys.
Välilyönti (space) - Alkuperäisessä koodissa vaihtoi isometriseen tilaan, joka ei tässä kuitenkaan vaikuttaisi tekevän paljon mitään kuin jähmettävän piirron kunnes painetaan uudestaan.
W/S - Pyöritys pystysuunnassa
A/D - Pyöritys vaakasuunnassa
Q/E - Pyöritys 2D-kuvasuunnassa (vaikea selittää)
T/G - Liikuta kuutiota W/S kääntymisen mukaan
F/H - Liikuta kuutiota A/D kääntymisen mukaan
R/Y - Liikuta kuutiota Q/E kääntymisen mukaan
P/O - Siirrä kuutiota lähemmäs/kauemmas
Ylös/alas - Siirrä kuutiota ylös / alas (nuolinäppäimet)
Vasen/oikea - Siirrä kuutiota vasemmalle / oikealle (nuolinäppäimet)
1/2 - Liikuttaa kameraa suhteessa kuutioon vaakasuunnassa.
3/4 - Liikuttaa kameraa suhteessa kuutioon pystysuunnassa.
5/6 - Liikuttaa kameraa suhteessa kuutioon syvyyssuunnassa (tosin ei näkyvää eroa)

Re: Kolmiulotteinen kuutio

Posted: Thu Dec 05, 2013 5:01 pm
by MaGetzUb
Ihan komea, tosin tuo on vain ortograaffisesti esitetty 3-ulotteinen kuutio, koska syvyysvaikutelma eli perspektiivi puuttuu kokonaan. :)

Re: Kolmiulotteinen kuutio

Posted: Fri Dec 06, 2013 5:12 pm
by CosmoConsole
MaGetzUb wrote:Ihan komea, tosin tuo on vain ortograaffisesti esitetty 3-ulotteinen kuutio, koska syvyysvaikutelma eli perspektiivi puuttuu kokonaan. :)
Tiedän, esitys on täysin isometrinen. Saatiin kuitenkin yhden kamun kanssa aikaan syvyysvaikutelma, tosin se on melko buginen, ehkä julkaisen senkin version kunhan olen hionut vielä pikkuisen.

Re: Kolmiulotteinen kuutio

Posted: Sat Dec 07, 2013 12:05 pm
by koodaaja
Bugittomastikin projektion saa tehtyä verraten yksinkertaisesti. Projisoitu 2D-koordinaatti on (w/2+C*x/(z+D), h/2+C*y/(z+D)), missä (x,y,z) on piirrettävä piste, w ja h näytön koko ja C projektion voimakkuuden kertova vakio. Z-arvoihin on usein hyvä lisätä suhteellisen suuria vakioita (kaavassa D) jotta projektiosta saa vähemmän vääristävän ja kappaleet ovat silti nähtävissä olevan kokoisia. Ainakin omien 3D-viritelmieni alkuongelmia oli myös unohtaa käyttää floatteja - kokonaisluvuilla liikkeistä tulee erittäin töksähteleviä.

Varsin lupaavalta se tähän asti näyttää, nyt vaan joku mielekkäämpi modelli kehiin ja peliä tulemaan!