Gå til innhold

Visual Basic Roundup!


Anbefalte innlegg

Videoannonse
Annonse
Sinsykt pent, kaffenils! Takk skal du ha!

Hvis du har planer om å lage en enkel 3d-motor så kan jeg jo også informere deg om at alle 3d-objekter bygges opp av trekanter, og en trekant defineres selvfølgelig ved å velge tre punkter fra punkt-arrayet ditt. Trekant objektet kan du da tilegne egenskaper som f.eks. farge.

 

EDIT: "bygges opp" ikke "byttes opp"

Endret av kaffenils
Lenke til kommentar
Noe spesiell grund til akkurat 3 kanter? Blir det ikke mye lettere å lage texturer hvis det er bygd opp av 4 kanter?

Det er mye enklere å sette sammen trekanter i diverse størrelser og proposjoner til mer kompliserte figurer enn med firkanter. Prøv f.eks å sette sammen en kule med firkanter og deretter med trekanter så skjønner du hva jeg mener.

Lenke til kommentar

Skjønner, men hvordan kan jeg da lage texturer? Planen var å lage firkanter, og vri dem med en av de Blt'sa, men det går jo ikke med 3 kanter.

 

Har du noe anelse om hvordan jeg skal lage et såkalt "z-buffer"? Liksom .. Første veggen som blir loadet, kan jo ikke alltid blir tegnet først, og aldri være synlig. Nærmeste vegger må jo tegnes til sist.

 

Edit: En ting til! Lager slik at man kan styre med musa nå, og det funker sånn cirka. Problemet er dRotateX. Den roteres ikke fra players pos. Vannskelig å forklare. Man ser det når man prøver å gå litt rundt, og se ned i "bakken".

3d.zip

Endret av Jonas
Lenke til kommentar

en firkant er bare to trekanter, så du mapper bare en tekstur oppå de to trekantene.

 

når det gjelder z-buffer er det bare å sortere z-verdiene, de som ligger bakerst tegner du først.

 

når det gjelder det med at den ikke roterer fra "player pos" er det fordi måten du roterer/transformerer spiller en rolle på hvordan resultatet blir. f.eks transform først så rotere blir helt annerledes enn å rotere først så transformere.

igjen, de fleste matrisetutorialene forklarer dette bra :)

jeg hadde seriøst anbefalt deg å lese og forstå matriser. du kommer ikke utenom dem hvis du skal drive med 3d uansett.

 

du kan også bruke directx som gjør alt det jeg nevnte ovenfor for deg.

Endret av iobas
Lenke til kommentar
Skjønner, men hvordan kan jeg da lage texturer? Planen var å lage firkanter, og vri dem med en av de Blt'sa, men det går jo ikke med 3 kanter.

 

Har du noe anelse om hvordan jeg skal lage et såkalt "z-buffer"? Liksom .. Første veggen som blir loadet, kan jo ikke alltid blir tegnet først, og aldri være synlig. Nærmeste vegger må jo tegnes til sist.

 

Edit: En ting til! Lager slik at man kan styre med musa nå, og det funker sånn cirka. Problemet er dRotateX. Den roteres ikke fra players pos. Vannskelig å forklare. Man ser det når man prøver å gå litt rundt, og se ned i "bakken".

Rotasjon blir komplisert når du skal ha med tilt (se opp og ned) og "hodet på skakke".

 

Ta følgende eksempel.

 

Du står på et punkt og ser nedover z-aksen (dRotateY=0). Så vil du se nedover og endrer dermed dRotateZ til f.eks 45 grader (PI/8). Forelåpig ser de bra ut. Men så snur du deg 90 grader rundt y aksen (dRotateY=PI/4). Nå ser du noedover den negative X aksen, samtidig som dRotateX=PI/8 og du står plutselig med hodet på skakke. For at du skal se nedover så må nå dRotateZ være 45 grader og ikke dRotateX. Som du skjønner så vil dRotateX og dRotateZ være avhengig av dRotateY.

 

Jeg skal se hva jeg finner ut og komme tilbake til deg.

Lenke til kommentar

hmm skjønte ikke så mye av det der kaffenils. hvorfor er det komplisert med tilt?

 

hvis du skal se ned i bakken roterer du vel x-aksen og ikke z-aksen?

hvordan koordinatsystem har du isåfall?

 

y z

|/_ x

 

z-aksen går innover i skjermen

Lenke til kommentar
hmm skjønte ikke så mye av det der kaffenils. hvorfor er det komplisert med tilt?

 

hvis du skal se ned i bakken roterer du vel x-aksen og ikke z-aksen?

hvordan koordinatsystem har du isåfall?

 

y  z

|/_ x

 

z-aksen går innover i skjermen

Bar glem det jeg sa. Jeg fikset det ved å rotere aksene i en annen rekkefølge. Før så roterte jeg først x, så y og så z. Nå roterer jeg z, y og x og da virker det bedre.

 

Jonas, her er en oppdatering av 3dWorld. Jeg har bl.a. laget en en array av sin og cos og sparer forhåpentligvis litt cpu på det. Dessuten fungerer bevegelse mye bedre med at du kan se opp og ned og tilte kameraet.

3dworld.zip

Endret av kaffenils
Lenke til kommentar
  • 2 uker senere...

Har laga en hjemmelaga Delay funksjon. Hadde som krav at man kunne avbryte en påbegynt delay pga. at dersom brukeren hadde satt en sample-delay på f.eks. 30 sekunder og vil endre denne, så var det uakseptabelt at brukeren skulle vente på at påbegynt delay skulle bli ferdig. Dersom denne funskjonaliteten ikke trengs, så er det lett å modde koden.

 

Det ser slik ut:

 

Private Sub Delay(Delay_ms) 'homemade Delay function

Dim scrap As Integer 'value never used

Dim ExitTime As Double 'Holds the time when the delay should exit

ExitDelay = False 'Allows early termination of the delay

ExitTime = (Timer * 1000) + Delay_ms 'Sets the ExitTime

Do While ExitTime > (Timer * 1000) 'Delay

scrap = DoEvents()

If ExitDelay Then 'check to see if the delay is aborted

Exit Do

End If

Loop

End Sub

 

Noen kommentarer på denne?

Feel free til å bruke denne fritt, men nevn meg gjerne i comment feltet dersom det blir shareware eller noe av det.. ;)

Kjell-Edmund Ims

Lenke til kommentar

Ikke dårlig, Dargar. Men jeg vil tro du sparer mye CPU-bruk hvis du slenger med en Sleep-kommando i tillegg. Dette fører selvsagt til at funksjonen kan bli mindre nøyaktig, men dette kan du jo kompensere for ved å la bruken av Sleep være definerbart gjennom en paramenter.

 

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Private Sub Delay(Delay_ms, Optional SuspendThread As Boolean) 'homemade Delay function

   Dim scrap As Integer 'value never used
   Dim ExitTime As Double 'Holds the time when the delay should exit
   
   ExitDelay = False 'Allows early termination of the delay
   ExitTime = (Timer * 1000) + Delay_ms 'Sets the ExitTime
   
   Do While ExitTime > (Timer * 1000) 'Delay
   
       scrap = DoEvents()
       
       If ExitDelay Then 'check to see if the delay is aborted
           Exit Do
       End If
       
       If SuspendThread Then
           Sleep 10 ' Reduce the CPU-usage
       End If
       
   Loop

End Sub

Lenke til kommentar

[edit]

unskyld min forferdelige norsk/engelsk/dialekt blanding her. Er fryktelig trøtt og orker ikke gjøre om gjøre rett...

[/edit]

er jo ett poeng det, sleep alltså, men burde det ikke være nokk med å bruke DoEvents siden CPU-cyklene da går til andre programmer iallefall?

 

Er vel litt mindre overhead på å kjøre sleep, siden man da tar programmet ut av OS'ets "Ready" queue og legger den i "suspended" køen, men er forskjellen stor nok til att det er "verd" å gjøre slik?

 

Når det gjelder nøyaktigheten, så har jeg de gangene jeg har brukt for høy tidsoppløsning kjørt en dynamisk korrigering av delay-tiden som jeg kaller Delay med.

 

slik omtrent: (obs pseudo-kode ikke kompilert = ikke garantert syntax1)

 

private sub MySamplingFunction(SampleFrequency) 'as double

Dim UsedTime As Double

Dim Check As Double

Dim Real As Double

 

do while SampleOn

UsedTime = Timer

'blabla bla

'funksjons-kall

'blabla bla

 

lblDelayMonitor.Caption = "Real Delay: " & Check 'Check = 0 first time the loop runs

Real = SampleFrequency - (1000 * (Timer - Waste))

Delay (Real)

Check = Timer - Waste

loop

 

I koden ovenfor kompenseres argumentet til Delay med den tiden som koden selv har tatt å gjennomføre. Ved å skrive ut Check så så jeg at delayer som var større enn noen få millisekunder var ganske nøyaktige. Når man kom opp på ca. 100+ms så var den nøyaktig på veldig mange decimaler. Vet jo ikke hvor god denne metoden er, men helt nøyaktig blir det ikke her heller siden koden vil ta ulik tid å kjøre. Det min kode gjør er jo å bruke tiden som forrige kode brukte på å justere neste delay om man kan si det sånn.. Resultatene ble iallefall mye bedre enn med en timer, og bra nok for meg.

Endret av Dargar
Lenke til kommentar

Hvis du trenger større nøyaktighet, er det bare å bruke QueryPerformanceCounter. Dessuten, Sleep hinder faktisk overbruk av CPU. Tro det eller ei, men Task Manager viser faktisk 100% når man kun har en DO-LOOP med DoEvents(). Dog er det ikke så farlig om det kun er korte intervaler du skal fryse programmet, men med lengre (10 sekund eller mer), tror jeg du bør bruke Sleep.

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...