Fast Modelling 9 - Mecha

Quando sono preoccupato per qualcosa e non trovo modo di distrarmi o pensare ad altro (non posso studiare perchè le cose non mi resterebbero in testa) mi metto a lavorare a qualcosa.

Questa è l'ultima fatica (ancora incompleta) data dalla mia disperata mente!

Può darsi che sarà il nuovo lavoro per un bel WIP.
Si vedrà come va avanti.
Cosa ne pensate? Vi piace? Oppure come "stile" non va bene?

Sarà comunque servito a distrarmi?
No, affatto...
Il problema di riuscire a fare più cose contemporaneamente è che anche i brutti pensieri permangono. Solo il sonno forse mi darà pace, e ora mi sta venendo una grande voglia di dormire...

Alla prossima...
Continua a leggere!

Seifer Gunblade

In questi giorni proprio non so cosa fare per ternemi occupato.
Ho tanti troppi pensieri per la testa, ma al contempo tanta troppe cose che vorrei fare...
Non mi succedeva da tanto tempo, e devo dire che è frustrante non avere la possibilità di realizzare tutto quello che si vorrebbe nell'arco di un solo giorno.

Comunque proseguendo sulla retta via cominciamo a descrivere cosa ho fatto.

Ho notato che parecchi degli accesi al blog sono stati fatti ricercando "Gunblade" o come costruirne uno (magari fossi in grado di farne uno vero XD).
Quindi ieri sera (mentre guardavo qualcosa alla tv... mi pare aspettassi Wasabi :P) mi sono detto "Cosa potrei fare come lavoro sempre in tema Gunblade?".
Eh purtroppo di Gunblade ce ne sta solo uno!
NO INVECE! C'è anche quello di quel maledetto ed antipatico di Seifer -.-

E allora non ci ho pensato troppo su, ho trovato una cavolo di immagine (a bassa risoluzione -.-) e mi sono messo a modellarlo!

Come forma è certamente più semplice rispetto al Revolver di Squall, con meno dettagli direi.
Poi avendo un'immagine a bassa risoluzione non ho potuto mettere tutti i dettagli che avrei voluto ?_?
Il risultato però non mi dispiace (per averci lavoraro al massimo un'oretta).

Come si può vedere è molto più semplice.
E mi chiedo come facesse Seifer a tirare quelle pizze tremente impugnando questo affare a mo di pistola e con una mano sola :O
Almeno quello di Squall lo si poteva usare a 2 mani e aveva una forma più a spada che a pistola...
I misteri della vita! :O

Poi devo dire che il modello "pistola automatica" mi piace poco, poi come ho detto, non ho potuto particolareggiare molto: anche così sono andato abbastanza a fantasia.
E anche usando una foto di una pistola automatica non posso mettere troppa roba che non "esiste" nel progetto gunblade, anche perchè dopo non tornano forme e posizioni.

Poi mi sono detto "E a metterli assieme entrambi come rende il tutto?"
Ecco a voi :)

Diaciamocelo....
Il gunblade di Seifer a confronto con quello di Squall sembra un coltellino svizzero XD
Dai quello di Squall è troppo più bello e massiccio!
Credo che l'unica arma che ispira più potenza sia la Buster Sword di Cloud :P

Bè come al solito spero vi piaccia, e se avete delle critiche da fare, anche sulla forma e sui dettagli dei modelli ditelo che provvedo a cambiare e a modifcare!

Inoltre una piccola richiesta: se qualcuno trova delle foto ad alta definizione del gunblade di Seifer me lo può dire? In questo modo potrò aggiungere altri dettagli :)

Eccovi i link per le immagini ad alta risoluzione :)
Seifer's Gunblade
Both Gunblade
Continua a leggere!

The Xna-Way: Tutorial 4: Input

Ok eccoci di nuovo qua.
Dopo aver visto la telecamera della scena, come si carica e renderizza un semplice modello voglio vedere ora come organizzare la gestione dell'input!

Come ho deciso di organizzare questa cosa?
Bè XNA ci da tutte le funzioni per gestire l'input da tastiera, da mouse e da gamePad. Come sempre lavoro solo su Windows, quindi io gestirò solo quello da mouse e da tastiera, anche se per ora mi dedicherò solo a quello da tastiera.

Lo stato della tastiera va aggiornato e controllato ad ogni ciclo di esecuzione, e il posto migliore per farlo è il metodo update.
Quindi posso pensare di organizzare un gameComponent per la gestione e aggiornamento dell'input da tastiera. Ma quanti e quali componenti devono/possono usare l'input?
Be così ad occhio io direi la nostra telecamera, e per ora un eventuale personaggio da muovere. Se poi ci fossero altri componenti potremmo avere dei problemi di accesso ai dati per l'input.
Sarebbe auspicabile che ogni componente che vuole accedere all'input acceda agli stessi dati, cioè alla stessa copia in memoria dei dati relativi all'input.

Come per la telecamera anche il gestore dell'input sarà visto come un servizio, al quale poi potremo accedere da ogni punto del nostro gioco.
Per fare questo quindi useremo un'interfaccia, che esporrà i metodi e le proprietà che ci servono, e una classe (un gameComponent) che implementi l'interfaccia.
L'interfaccia e la classe saranno rispettivamente InputI e MyInput.

Ecco il codice del file che andremo ad aggiungere alla nostra libreria di classi:
MyInput.cs
Show/Hide


Come sempre se in futuro ci servono nuove funzionalità esse verranno implementate, ma per ora non ci servono e basta quello che abbiamo.

Cosa fa il codice?
Bè la classe definisce un oggetto di tipo KeyboardState, il quale andrà a contenere lo stato della tastiera, è cioè quali sono i tasti premuni e non premuti.
Nel costrutture, come pensato, vado ad aggiungere il gameComponent alla lista dei Servizi.

Il metodo update fa una cosa semplicissima: ad ogni esecuzione aggiorna il valore attuale contenuto nella variabile kState, in modo che quando un altro componente vuole ottenere informazioni sulla tastiera otterrà sempre lo stato aggioranto.

Come posso recuperare il riferimento al servizio ed utilizzarlo?
Andiamo nella nostra classe Model3D, e andiamo ad aggiungere un campo di classe così:
InputI inputDevice;

che sarà usato per contenere il riferimento al nostro gestore dell'input.
Ne costruttore di Model3D andiamo ad aggiungere questa riga:
inputDevice = (InputI)game.Services.GetService(typeof(InputI));

è simile a quella usata per recuperare il riferimento al servizio che gestisce la telecamera, solo che questa recupera il servizio per l'output.
Nel metodo update della classe Model3D aggiugiamo queste righe sotto l'incremento dell'angolo sull'asse Y:
if(inputDevice.KeyBoardState.IsKeyDown(Keys.Up))
angleX += 5f * (float)gameTime.ElapsedRealTime.TotalSeconds;


in modo che quando premiamo il tasto "up" l'angolo sull'asse X venga incrementato.
Bene quasi finito!

Andiamo nel file Game1.cs, aggiungiamo anche qui il campo
inputDevice = (InputI)game.Services.GetService(typeof(InputI));

e il costruttore trasfromiamolo così:
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
counter = new FPSCounter(this);
Components.Add(counter);

myInput = new MyInput(this);
Components.Add(myInput);

myCamera = new Camera(this);
Components.Add(myCamera);
}

Come possiamo vedere ho creato ed aggiunto un oggetto di tipo MyInput alla collezione dei componenti.
Ma come mai l'ho fatto prima della telecamera?
Perchè se in un futuro amplierò le funzionalità della mia telecamera e vorrò usare l'input, se aggiungo prima la camera e poi l'input, quando nel costrutire la telecamera andrò a cercare di recuperare il riferimento al servizio che implementa l'interfaccia InputI mi ritornerà NULL, dato che tale servizio non sarà stato ancora aggiunto. Così facendo invece la telecamera lo troverebbe pronto.

Se ora avviamo il gioco, dovremmo vedere sempre il nostro asteroide che ruota, ma premendo il tasto SU ruoterà anche attorno all'asse X.
Fantastico! E anche molto semplice direi ^^

Bene facciamo un'ultima modifca e poi abbiamo finito per oggi!
Nel metodo update della classe Game1.cs andiamo ad eliminare la condizione del costrutto if (che riguarda il gamePad) con questa:
if (myInput.KeyBoardState.IsKeyDown(Keys.Escape))
this.Exit();


in modo che premendo il tasto Escape allora il gioco verrà terminato!

Ok per oggi è tutto!
Spero di essere stato chiaro.
Anche questa volta niente sorgenti, dato che il file per il componente di Input è tutto listato qua sopra, e le modifiche da fare sono esigue.

Se qualcosa non vi torna ditelo senza problemi e correggo! :)

Alla prossima!

Continua a leggere!

The Xna-Way: Tutorial 3: Modelli 3D

Piccola introduzione all'uso dei modelli tridimensionali!
Ma proprio minimale eh ^^

Intanto ecco a voi il codice di questa piccola classe che ho creato per gestire un modello 3D.
Da dire che il concetto è sbagliato, perchè è errato pensare di fare e di creare un game component per ogni oggetto che vogliamo gestire. Avremmo in questo modo un aumento della complessità realizzativa e un calo di prestazioni dovuto al grande numero di componenenti in gioco. Di solito si userà un gestore per quegli oggetti che hanno un comportamento comune, e un oggetto apposito per quelli che hanno un comportamento particolare.
Ma per ora, per questi esempi semplici va più che bene.
Questo componenten va aggiunto al progetto myLibrary.

Model3D.cs
Show

Come si può vedere la classe Model3D.cs deriva da DrawableGameComponent, in questo modo ha il suo metodo Draw.

Model3D ha come campi privati un oggetto myModel di tipo Model che servirà per contenere il modello che andremo a caricare.
Poi ha un vettore per la sua posizione nel mondo 3D della scena, 3 variabili per il valore della rotazione lungo i 2 assi (X, Y, e Z) e una variabile per la scala dell'oggetto (cioè per dire quanto deve essere grande l'oggetto).

La matrice chiamata world è la matrice che costruiremo usando le varabili che caratterizzano la posizione del nostro oggetto nel mondo.

Ha anche un oggetto di tipo CameraI che andrà a contenere il riferimento al servizio della telecamera. Ma come lo recuperiamo? :O

Al costruttore gli passiamo (oltre al game) il percorso dove è situato il modello che vogliamo caricare. In questo modo possiamo caricarlo ed assegnarlo al nostro oggetto.
Per fare questo usiamo il metodo Load di Content. Questo Metodo ci permette di caricare molti dei contenuti multimediali che vogliamo usare nel nostro gioco, come i modelli appunto, musica, immagini, etc.
Non mi dilungo nello spiegare cosa faccia, ma in parole povere è come se riscrivesse l'oggetto che vogliamo caricare in un formato compatibile ed utilizzabile da XNA sia su pc che sulla 360.

Concentriamoci un attimo su questa riga:
myCamera = (CameraI)game.Services.GetService(typeof(CameraI));

Cosa fa? Abbiamo visto nel file Camera.cs come aggiungere un servizio, che poi non era altro che un gameComponent che implementava un'interfaccia.
Questo metodo ci permette di recuperare il riferimento ad un servizio che abbiamo aggiunto, e di far riferimento sempre alla solita copia di quel servizio da ogni punto del nostro gioco.
In questo caso andiamo a prendere il riferimento al serivizio che si occupa gestire la telecamera.
Naturalmente potremo accedere solo ai metodi e proprietà definite nell'interfaccia.
Ci serve di recuperare il riferimento alla telecamera perchè per la fase di rendering dell'oggetto abbiamo bisogno di un paio di informazioni da parte della camera.

Fatto questo cambiamo il valore z del vettore position, in modo che sia distante dal punto di osservazione della telecamera e sia ben visibile.

Nel metodo update aggiungiamo questo:
angleY += 5f;
world = Matrix.CreateScale(scale) *
Matrix.CreateFromYawPitchRoll(angleY, angleX, angleZ) *
Matrix.CreateTranslation(position);
Questo codice incrementa il valore dell'angolo di rotazione sull'asse Y di 5 gradi ad ogni esecuzione del metodo update, e dopo ricostruisce la matrice world.
La matrice world è costruita prima calcoando la matrice per la scala, poi per la rotazione ed infine per la traslazione.
Per calcolare la rotazione usiamo il CreateFromYawPitchRoll: questi termini (Yaw, Pitch, Roll) indicano rispettivamente il valore della rotazione attorno agli assi Y, X, e Z (cioè Yaw = Y, Pitch = X, e Roll = Z). Ecco perchè al metodo gli passo prima l'angolo per l'asse Y, poi per X ed infine per Z.

Di solito si segue questo ordine, anche perchè la moltiplicazione tra matrici non è commutativa ed eseguire questa moltiplicazione con un ordine diverso porta a risultati doversi.

Ora andiamo al metodo Draw!

foreach (ModelMesh mesh in myModel.Meshes)
{
foreach (BasicEffect be in mesh.Effects)
{
be.EnableDefaultLighting();
be.Projection = myCamera.Projection;
be.View = myCamera.View;
be.World = world;
}

mesh.Draw();
}

base.Draw(gameTime);


Questo è il classico ciclo di esecuzione per renderizzare un modello tridimensionale.
Fatto copia incolla dal manualone (vantiamocene eh XD).
Quello che fa è più o meno questo: per ogni mesh contenuta nel modello (dato che un modello può essere composto da più mesh) prende il basicEffect della mesh attuale, imposta i valori per la projection matrix, view matrix (per dire come è fatto il punto di osservazione) prelevandoli dal servizio che gestisce la telecamera (ecco a cosa ci serviva il riferimento ad essa!). Poi dobbiamo impostare il valore per la world matrix, che rappresenta la posizione, la rotazione e la scala del nostro oggetto nella scena. Infine renderizza la parte in esame.

Come si fa ad usare questo componente che abbiamo appena creato?
Nel progetto che stiamo usando, dopo aver aggiungo la telecamera come visto l'altra volta, andiamo nel file Game1.cs e nel metodo Inizialize aggiungiamo questo codice:
Model3D modell = new Model3D(this, @"Models\asteroid1");
Components.Add(modell);
Per fare questo dovrete aggiungere nella cartella Content del progetto due cartelle: una chiamata Models, dove andremo a mettere il modello del nostro asteroide, e un'altra chiamata Textures, dove andremo a mettere la texture del nostro modello (che verrà caricata in automatico assieme al modello).
Come possiamo notare, quando andiamo a caricare il modello, e a specificare il nome dell'oggetto da caricare, non mettiamo l'estensione. Questo perchè non ci serve, dato che l'oggetto è già stato passato nella content Pipeline di XNA. Se vogliamo quindi riferirci ad un oggetto per caricarlo, come in questo caso, gli dobbiamo dare solo il nome, senza estensione.
Questo codice crea ed aggiunge li componente per la gestione del modello.

Avviando il gioco se tutto va bene dovremmo vedere un meteorite che ruota su se stesso.
Ora abbiamo due possibilità: o il metorite ruota lentamente o va come una scheggia.
Se va lentamente è perchè non abbiamo creato ed aggiunto il gameComponente per il conteggio degli FPS, se va come una scheggià per perchè lo abbiamo creato.
Ricordo che il componente per il conteggio degli FPS toglie il limite al numero di volte che il metodo Update viene chiamato in un secondo.
Per usare l'FPSCounter e far ruotare il modello alla velocità giusta cambiamo il codice per l'aggiornamento dell'angolo in questo modo:

angleY += 5f * (float)gameTime.ElapsedRealTime.TotalSeconds;

Accedendo al gameTime, e prendendo il valore ElapsedRealTime non facciamo altro che recuperare il tempo passato dall'ultima invocazione del metodo Update. Così facendo l'incremento non sarà di 5 gradi ad ogni invocazione del metodo, ma di una frazione di 5 ad ogni invocazione del metodo.
In questo modo l'incremento sarà fatto alla giusta velocità, sia usando che non usando l'FPSCounter. Difatti se proviamo ad eseguire il codice prima con FPSCounter e poi senza notiamo che non c'è differenza nella velocità di rotazione dell'oggetto.

Spero sia chiaro.

Come ho detto questo è solo un esempio, e di solito non si fa una cosa del genere. Ma per addentrarci un po' nel caricamento e nella renderizzazione degli oggetti 3D credo possa andare.

Eccovi intanto i sorgeti di quanto fatto:
XNA-tut3.rar
Alla prossima :)
Continua a leggere!

The Xna-Way: Tutorial 2: Camera

Finalmente trovo il tempo e la voglia di scrivere qualche altra riga.
Questa volta mi sono occupato della camera della scena. Una semplice telecamera fissa, perchè per poter aggiungere altre funzionalità dovrò prima implementare altri servizi e componenti, tra i quali quelli per gestire l'input da tastiera (e mouse) e un modo semplice per renderizzare qualcosa a scena.

Purtroppo per vedere gli effetti di quanto scrivo dovremo attentere il prossimo articolo. Questo non perchè non funziona, ma solo perchè non ci sarà niente da renderizzare nella scena (come ho detto dovrò poi implementare un qualcosa per far renderizzare un modello tridimensionale!)
Questo componenten va aggiunto al progetto myLibrary.
Ecco il codice del file:

Camera.cs
Hide/Show


Naturalmente nessuno ci vieta di aggiungere funzionalità al nostro codice in futuro :)

Analizziamo il codice pezzo a pezzo:
il vettore position è quello che contiene la posizione dal quale stiamo osservando la scena, mentre target è il vettore che contiene il punto che stiamo osservando.
Up è il vettore che indica in quale direzione è l'alto nella scena.
Con il codice scritto abbiamo che la telecamera (o punto di osservazione) è posizionato in posizione X = 0, Y = 0, Z = 20.
Stiamo osservando il punto X = Y = Z = 0, e l'alto è dato dal vettore con componente Y positiva (in teoria [0,1,0]).

float aspectRatio = (float)Game.GraphicsDevice.Viewport.Width /
(float)Game.GraphicsDevice.Viewport.Height;
Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,
aspectRatio, 1.0f, 10000.0f, out projection);
Matrix.CreateLookAt(ref position, ref target, ref up, out view);

Con questo codice creiamo prima di tutto il rapporto tra le dimensioni del nostro schermo (di solito un televisore è in 4:3 o 16:9). Nel nostro caso il rapporto è tra la larghezza e l'altezza delle dimensioni dell'area di rendering.
Per accedere a questa informazione utiliziamo
Game.GraphicsDevice.Viewport.Width e Game.GraphicsDevice.Viewport.Height.

Queste informazioni vengono utilizzate poi per creare la projection matrix: questa matrice serve a definire come viene presentato a schermo quello che viene renderizzato nella scena. Gli ultimi due parametri numerici sono il nearPlane e il farPlane. Indicano i limiti di quanto è possibile vedere: cioè tutto quello che risulterà distante dalla telecameta e tra nearPlane e farPlane sarà visibile.
Come si può vedere gli passiamo anche l'aspectRatio calcolato prima.
L'ultimo parametro, quello con "out", definisce in quale variabile andrà a finire il risultato.

La view matrix identifca la telecamera, e ci serve a definire in quale punto siamo, cosa stiamo osservando, e dove si trova la direzione dell'alto. Come si vede per calcolarla si utilizza le tre variabili definite prima.

Per ora la telecamera è fissa, cioè non si muove, non cambia punto di osservazione... Nulla un punto fisso.
Questo è il più semplice tipo di telecamera che si piò creare. Si potrà poi utilizzare questa classe come base per ereditare altri tipi di telecamere.

Per poterla utilizzare, nel costruttore di Game1.cs si deve creare un oggetto di tipo camera ed aggiungerlo alla collezione dei components.

Torniamo un attimo al costruttore della telecamera, ed osserviamo questa riga:
game.Services.AddService(typeof(CameraI), this);
Che cosa fa?
Be con l'FPSCounter avevamo visto come creare un component ed aggiungerlo alla collezione dei Components in modo che poi venisse gestito in automatico.
Quello che faccio ora è creare un servizio: un servizio è un componente che implementa un'interfaccia. Tramite questa interfaccia possiamo poi riferire il servizio ed accedere al servizio stesso tramite i metodi e le proprietà definite dall'interfaccia.
C'è da dire però che ci deve essere nei Services un solo oggetto che implementa una certa interfaccia. Quindi non posso aggiungere due gestori per la camera che implementano la CameraI, dato che poi non sapremo come recupere l'uno o l'altro. Se voglio aggiungere due telecamere diverse i due oggetti devono implementare due interfacce diverse.
Per aggiungerlo alla collezione dei servizi dobbiamo prima di tutto accedere tramite l'oggetto game alla collezione dei servizi, e poi gli dobbiamo dire di che tipo considerare l'oggetto che stiamo aggiungendo (in questo caso come un tipo CameraI) e l'oggetto da aggiungere (in questo caso l'oggetto che stiamo costruendo e quindi this).
Vediamo infatti che la notra classe implementa l'interfaccia CameraI, la quale definisce delle proprietà che andranno a recuperare i valori della projection e della view matrix.
Quando in un altro punto del nostro gioco andremo a recuperare il riferimento al servizio che implementa la CameraI andremo a recuperare il riferimento del solito oggetto, e quindi andremo a recuperare sempre le stesse informazioni.

Per ora finisco qui.
La prossima volta vedrò di dire come si può creare un componente che si occupa di caricare e renderizzare nella scena un oggetto tridimensionale, e come recueperare il riferimento al servizio della camera appena creato ed aggiunto.

Questa volta niente sorgenti, dato che ho messo il file completo nel post :)
Spero di essere stato chiaro.
Se qualcosa è spiegato frettolosamente o in malo modo ditelo e provvederò a correggere! :D

Ciau! Alla prossima!
Continua a leggere!

Fast Modelling 8 - armchair

Altra giornata divisa tra un progetto per l'università (anche se portato avanti lentamente e con poca voglia), uno strano malumore generale, fatica fisica (le legne per l'inverno vanno messe a posto nella legnaia eh!)...
Si arriva alla sera e cosa si fa?
Da un lato il libro su XNA (che non ho abbandonato eh, solo che devo sperimentare alcune cose e scrivere qualche altro esempio per capire come funzionano delle cose poi vi farò sapere ^^), o la possibilità di modellare qualcosa di veloce e possibilmente indolore...

Secondo voi se state a leggere queste righe, cosa avrò mai fatto?

Quando stavo pensando a cosa poter fare, mi sono girato di scatto a destra sentondo un ronzio di una zanzare (maledetta!) e cosa ho visto?
La poltrona!
E allora ho cominciato a modellare la poltroncina che ho di fianco, cercando di mantenere una struttura semplice.
Il risultato dopo 15-20 minuti di lavoro è stato il seguente:
Devo dire che il mio stesso lavoro non mi è piaciuto più di tanto... Sinceramente speravo di giungere ad un risultato migliore.... Ok direte voi potevi interrompere o modificare il tutto, ma quanto mi prendono questi "attacchi" non posso: come chi butta giù una bozza non si ferma fino a lavoro finito io faccio lo stesso. Non mollo fino a quando non sento che sono arrivato alla fine.
Erò però deciso a fare di meglio.
Ho quindi cercanto sul mitico Google qualche immagine di poltrone (cavolo non pensavo ce ne potessero essere di tanti tipi, forme, stili, decorate e non, moderne o romantiche, etc....
Insomma dopo un quarto d'ora buono a spulciare poltrone, ho trovato quella con la forma che facaveva al caso mio.
Altri 20 minuti di lavoro ed ecco il risultato:
Ora si che ero abbastanza soddisfatto del mio operato.
Non ci avrei dormito bene la notte poi (tutte balle XD).
Quindi ora dovevo solo scegliere il colore, controllare il codice sul catalogo, compilare il modulo e l'ordinazione era pronta...
Ok sto delirando!

Dopo qualche prova di texturizzazione, e qualche rendering andato male, questo è stato il mio risultato:
Se volete il prezzo per il prodotto è di 70€ spese di spedizione escluse (XD).



Tutto sommato mi sono divertito.
Spero vi piaccia, anche se non è proprio il massimo lo so... come al solito potevo spenderci un po' più di tempo e forse veniva meglio...
Comunque basta piangere.

Se avete qualche commento, prego non esitate :)

Alla prossima!
Continua a leggere!

Donazioni

My Menu'