Wikibooks itwikibooks https://it.wikibooks.org/wiki/Pagina_principale MediaWiki 1.47.0-wmf.16 first-letter Media Speciale Discussione Utente Discussioni utente Wikibooks Discussioni Wikibooks File Discussioni file MediaWiki Discussioni MediaWiki Template Discussioni template Aiuto Discussioni aiuto Categoria Discussioni categoria Progetto Discussioni progetto Ripiano Discussioni ripiano TimedText TimedText talk Modulo Discussioni modulo Evento Discussioni evento Storia della letteratura italiana/Alberto Moravia 0 38277 501041 500209 2026-08-19T17:52:16Z Hippias 18281 revisione: aggiunti i riferimenti, eliminate le informazioni non verificate 501041 wikitext text/x-wiki {{storia della letteratura italiana|sezione=8}} Tra i più rappresentativi scrittori italiani del secondo dopoguerra, Alberto Moravia è un autore prolifico, animato da passione civile e curiosità culturale. Critico nei confronti della borghesia italiana, classe sociale da cui egli stesso proviene, si fa conoscere già con il suo primo romanzo, pubblicato quando è poco più che ventenne, ''Gli indifferenti''. Nel dopoguerra firma altre opere di successo, molte delle quali sono trasposte al cinema. == La vita == [[File:Paolo Monti - Servizio fotografico - BEIC 6361580.jpg|thumb|left|Alberto Moravia]] Nasce a Roma, con il nome di Alberto Pincherle, il 28 novembre 1907 in una agiata famiglia borghese. Firma però le sue opere con il cognome della nonna paterna, Moravia. La sua è un'infanzia difficile: malato di tubercolosi ossea, è costretto a letto per lunghi periodi e subisce vari ricoveri in sanatorio. Compie studi irregolari, leggendo per lo più classici e narratori contemporanei. Durante la convalescenza in un albergo di montagna scrive tra il 1925 e il 1928 il suo primo romanzo, ''Gli indifferenti'': pubblicato nel 1929, ottiene immediato successo. Si inserisce attivamente nel mondo intellettuale e letterario italiano: continua a pubblicare racconti e stringe rapporti con Alvaro, Bontempelli e la redazione della rivista ''900''. Viaggia a lungo all'estero: soggiorna a Londra, a Parigi, negli Stati Uniti (ospite di Prezzolini) e persino in Cina. Intrattiene buoni rapporti con influenti intellettuali fascisti, sebbene il regime guardi con sospetto alla sua produzione letteraria e imponga agli editori di darle scarsa visibilità. Infine nel 1941, con la pubblicazione del romanzo ''La mascherata'', la censura interviene in modo duro e gli proibisce di scrivere sui quotidiani se non dietro pseudonimo. Nello stesso anno sposa la scrittrice [[../Elsa Morante|Elsa Morante]]. Dopo l'8 settembre 1943 la coppia fugge da Roma e ripara a Fondi, per tornare nella capitale solo dopo la Liberazione. Riprende l'attività letteraria e giornalistica, collaborando con ''Il Mondo'', ''L'Europeo'', il ''Corriere della Sera''. Pubblica vari interventi, reportage, riflessioni su argomenti di attualità. La sua attività di scrittore impegnato si intreccia con la partecipazione alla vita mondana. Nel 1947 il successo del romanzo ''La romana'' lo fa conoscere e apprezzare da un pubblico sempre più ampio. Vari suoi libri si rivelano spunti per riduzioni cinematografiche. Tra i film tratti dalle sue opere si ricordano ''La provinciale'' (1952) di Mario Soldati, ''La romana'' (1954) di Luigi Zampa, ''La ciociara'' (1960) di Vittorio De Sica, ''Agostino o la perdita dell'innocenza'' (1962) di Mauro Bolognini e ''Il conformista'' (1970) di Bernardo Bertolucci. Attivo anche come sceneggiatore, Moravia si avvicina, durante gli anni cinquanta, alla scrittura per il teatro. Nel 1953 fonda, insieme ad Alberto Carocci, la rivista culturale «Nuovi Argomenti», che dirige fino agli ultimi anni di vita. Nel 1957 inizia a collaborare con ''l'Espresso'', sul quale firma una rubrica di critica cinematografica. Nel 1960 la sua notorietà si amplifica ancora di più dopo il successo del romanzo ''La noia''. Nel 1962 rompe con Elsa Morante e inizia una relazione con la giovane scrittrice [[../Postmoderno#Dacia Maraini|Dacia Maraini]]. Negli anni ottanta il suo impegno politico lo porta a candidarsi alle elezioni europee come indipendente nelle liste del Partito Comunista: eletto, siede al parlamento di Strasburgo dal 1984 al 1989. Muore a Roma il 26 settembre 1990.<ref name="Ferroni1066">{{cita libro | Giulio | Ferroni | Profilo storico della letteratura italiana | 2003 | Einaudi | Torino | p=1066 }}</ref> == Poetica == La passione civile e la curiosità culturale, che hanno accompagnato Moravia per tutta la sua attività letteraria, lo rendono scrittore impegnato. L'opera di Moravia è legata al realismo e indaga le patologie delle classi sociali, specialmente dell'alta e della media borghesia. Il suo è uno stile esclusivamente da narratore che non si compiace di effetti lirici ma si affida esclusivamente allo svolgersi del periodo. Moravia guarda la realtà dall'esterno, lo stile della sua prosa è spoglio e disadorno, sempre regolare e privo di ogni slancio.<ref>{{cita libro | Giulio | Ferroni | Profilo storico della letteratura italiana | 2003 | Einaudi | Torino | p=1068 }}</ref> == I primi scritti e ''Gli indifferenti'' == Moravia inizia a scrivere i suoi primi racconti sulla rivista ''900'' alla quale collabora a partire dal 1927:<ref name="Ferroni1066" /> ''Cortigiana stanca'' (1927), ''Delitto al circolo del tennis'' (1928), ''Il ladro curioso'' e ''Apparizione'' (1929). Il successo ottenuto con il primo romanzo ''Gli indifferenti'' (1929), che viene visto dalla critica come esempio di romanzo esistenzialista e di stampo dostoevskijano,<ref>{{cita pubblicazione|autore=Stefano Guerriero|titolo=«Gli indifferenti» nella storia del romanzo|pubblicazione=Belfagor|vol=63|numero=3|data=31 maggio 2008|p=264|url=https://www.jstor.org/stable/26150663}}</ref> gli permette di proseguire la sua attività di scrittore e gli apre le porte del giornalismo. Scritto quando l'autore aveva solo 22 anni, il romanzo si presenta come uno dei primi esempi della nuova letteratura che stava nascendo negli anni del [[../Letteratura e fascismo|fascismo]]. L'opera non è il risultato di una riflessione teorica, ma piuttosto da un impulso istintivo che spinge Moravia alla narrazione. Si tratta di una caratteristica tipica del suo stile, che si osserva anche nelle opere successive. Quella descritta negli ''Indifferenti'' è una realtà vuota, in cui i personaggi sono mossi unicamente dal proprio egoismo e non mostrano nessun interesse per la tragedia che si sta consumando. Ne esce un'immagine risentita e violenta della borghesia italiana negli anni del regime.<ref>{{cita libro | Giulio | Ferroni | Profilo storico della letteratura italiana | 2003 | Einaudi | Torino | pp=1068-1069 }}</ref> Durante il fascismo, che penalizzava la sua origine ebraica da parte del padre, la sua opera viene tenuta sotto controllo e alcuni suoi scritti vietati, come le recensioni a ''Le ambizioni sbagliate'' (1935), o sequestrati, come ''La mascherata'' (1941).<ref name="Ferroni1066" /> In alcuni casi ne viene addirittura impedita la pubblicazione, come avviene per ''Agostino'' (terminato nel 1943). Moravia però non rinuncia alla letteratura e scrive comunque opere di carattere allegorico. Continua inoltre l'attività giornalistica firmando i suoi interventi con uno pseudonimo. Esce in questo periodo la raccolta di racconti ''La bella vita'' (1935), ''L'imbroglio'' (1937) e ''I sogni del pigro'' (1940).<ref name="treccani">{{treccani|alberto-moravia|Moràvia, Alberto}}</ref> == Gli scritti del dopoguerra: il neorealismo == Terminata la seconda guerra mondiale e trascorsi alcuni anni all'estero, Moravia riprende a scrivere e, oltre a dedicarsi al giornalismo, s'interessa di cinema, di teatro e di saggistica. Per il teatro scriverà ''Beatrice Cenci'' (1958), ''Il dio Kurt'' (1968), ''La vita è gioco'' (1969) e come saggista ''L'uomo come fine'' (1963) e l'''Impegno controvoglia'' (1980).<ref name="treccani" /> Nel 1945 lo scrittore pubblica ''Agostino''. Il romanzo segue i turbamenti di un tredicenne, Agostino, che scopre il sesso venendo a sapere di una relazione della madre con un uomo più giovane. Frequentando un gruppo di coetanei disposti a qualsiasi esperienza, il protagonista esce dall'ingenuità, attratto dagli aspetti torbidi della realtà attorno a lui. Tuttavia è frenato nei suoi impulsi dalla sua posizione di bravo ragazzo borghese, che gli impedisce di godere appieno della vitalità a cui possono accedere i ragazzi del popolo. Moravia aggredisce così il mito dell'adolescenza diffuso nella letteratura degli anni trenta, descrivendola come una fase della vita in cui la realtà appare come qualcosa di estraneo e sordido.<ref>{{cita libro | Giulio | Ferroni | Profilo storico della letteratura italiana | 2003 | Einaudi | Torino | p=1069 }}</ref> [[File:Lollo+moravia la romana 1954.jpg|thumb|Alberto Moravia sul set de ''La romana'' (Zampa) si intrattiene con Gina Lollobrigida]] Due anni dopo, nel 1947, vede la luce il romanzo ''La romana'', che narra la storia di una giovane prostituta che agisce in un ambiente di polizia fascista e di cospiratori antifascisti. Moravia viene così consacrato come autore [[../Neorealismo|neorealista]]. Seguono, al ritmo di un anno di distanza, ''La disubbidienza'' (1948) e ''L'amore coniugale'' (1949) nei quali lo scrittore fa una critica all'istituzione borghese del matrimonio. Nel romanzo ''Il conformista'' (1951) racconta la storia di un uomo che diventa una spia dell'OVRA, ispirata all'assassinio dei fratelli Rosselli. Una tra le opere più famose dello scrittore è ''La ciociara'' (1957), storia di una donna del popolo e di sua figlia che vengono mortificate dalla guerra.<ref name="Asor Rosa 406">{{cita libro | autore=Alberto Asor Rosa | titolo=Storia europea della letteratura italiana | editore=Einaudi | città=Torino | anno=2009 | vol=3: ''La letteratura della Nazione'' | p=406 }}</ref> Si annovera anche ''I due amici'', scritto nel 1952 ma rimasto incompiuto e pubblicato da Bompiani nel 2007. A questa fase sono riconducibili anche i ''Racconti romani'', scritti negli anni cinquanta, e nati dall'osservazione della realtà popolare.<ref name="Asor Rosa 406" /> == Alienazione e crisi esistenziale == Nel romanzo ''Il disprezzo'' (1954) e nei successivi, lo scrittore propone le tematiche adeguate alle nuove tendenze letterarie e culturali, come quella dell'alienazione, anche se la linea essenziale che lo guida rimane sempre l'osservazione della realtà. Tra i più noti è ''La noia'' (1960), al quale segue la raccolta di novelle ''L'automa'' (1962), ''L'uomo come fine'' (1964), ''L'attenzione'' (1965), ''Una cosa è una cosa'' (1967). ''La noia'' è, insieme a ''Gli indifferenti'', il romanzo più rappresentativo di Moravia e della sua analisi critica del mondo borghese. Il protagonista Dino è un intellettuale proveniente da una ricca famiglia romana, che fa di sé un'analisi psicologica e morale a partire dal senso di noia che prova. La "noia" non è altro che l'indifferenza di cui parlava il primo romanzo, l'estraneità nei confronti della realtà. Moravia porta avanti un affondo alla borghesia italiana degli anni cinquanta: la noia di Dino è un senso di inadeguatezza della realtà, che non riesce a persuaderlo della sua effettiva esistenza. L'unico modo per uscire da questa incomunicabilità sembra l'esperienza erotica. Anche questa però finisce per far ricadere nella noia, proprio per la sua ansia di possesso.<ref>{{cita libro | Giulio | Ferroni | Profilo storico della letteratura italiana | 2003 | Einaudi | Torino | p=1070 }}</ref> L'attualità contemporanea rimane un tema centrale anche nei romanzi dei decenni successivi, incentrati sulla sessualità o temi politici, e in specifico quello del terrorismo: ''Il paradiso'' (1970), ''Io e lui'' (1971), ''La vita interiore'' (1978), ''La cosa'' (1983), ''L'uomo che guarda'' (1985), ''Viaggio a Roma'' (1988), ''Palocco'' (1990). == Note == <references /> {{avanzamento|100%|23 settembre 2017}} [[Categoria:Storia della letteratura italiana|Moravia]] 67wsvr7rt4bw8z2xspjasfwvb6o2mrr Software e didattica/Video e animazioni 0 39005 501054 444669 2026-08-19T22:09:26Z ~2026-45514-04 54704 /* Video e animazioni */ 501054 wikitext text/x-wiki <noinclude>{{Software e didattica}}</noinclude> ===Video e animazioni=== Le animazioni e le immagini in movimento sono elementi particolarmente apprezzati da alunni, genitori e insegnanti, ma la loro preparazione (e utilizzazione all'interno di learning objects) non è sempre agevole. La limitata presenza di strumenti freeware e open source per la composizione video costituisce un limite evidente, mentre leggermente migliore è il panorama dei software gratuiti per il trattamento di immagini .gif animate, di files .flv e di filmati .avi a bassa risoluzione. Ci permettiamo di suggerire un inserimento discreto di elementi video nei nostri oggetti di apprendimento, anche per non aumentarne eccessivamente dimensioni e pesantezza. Immediatamente di seguito riporteremo e descriveremo invece alcune applicazioni gratuite che possono risultare utili per preparare animazioni, ma non garantendo per esse in assoluto risultati soddisfacenti in ogni sistema operativo e in qualsiasi condizione e ben sapendo che alcuni software commerciali (come Pinnacle Studio e Nero Vision) sono obiettivamente inarrivabili (e irrinunciabili nel caso si vogliano ottenere risultati professionali). Peraltro non dobbiamo dimenticare che il mondo del multimediale in Windows è piuttosto complesso e sempre in evoluzione. Per governare i cambiamenti e risultare sempre aggiornati può essere utile considerare un'eccezionale raccolta di codec audio e video, ''K-Lite Codec Pack (Full)'' [http://www.codecguide.com/], con un comodissimo programma di installazione. ==== <u>Windows Movie Maker</u> ==== ''Windows Movie Maker'' è stato presente nei sistemi Windows fino alla versione Xp. Il programma non è più nemmeno disponibile dal sito della Microsoft. ==== <u>Synfig Studio</u> ==== ''Synfig Studio'' [https://www.synfig.org/] è un programma di animazione vettoriale 2D utilizzabile gratuitamente per Windows, Mac OS X e Linux. Una versione portatile molto comoda è stata preparata dagli esperti di WinPenPack [http://www.winpenpack.com/en/request.php?1275]. Synfig Studio permette di ottenere animazioni fluide senza doverne disegnare individualmente ogni fotogramma. Le tecniche di trasformazione morfologica (passaggio tra due immagini) e di ritaglio (piccole modifiche applicate nel tempo a un'immagine) consentono una facile creazione dei necessari fotogrammi intermedi. In effetti il programma applica effetti avanzati di interpolazione, limitando drasticamente la necessità dell'intervento umano. Occorre comunque una certa pratica per l'utilizzo efficace del programma, certamente non adatto a bambini e adolescenti. E' possibile importare immagini create da GIMP o nel formato .svg, mentre l'esportazione dei lavori può avvenire (ma in certi casi con alcuni artifizi) verso diversi formati di immagini (.bmp, .gif, .jpg, .png) e di video (.dv, .mpg, .flv). ==== <u>Pencil2D</u> ==== Più semplice da usare, pur essendo disponibile solo in lingua inglese, è ''Pencil2D'' [https://www.pencil2d.org/download/], un altro software multipiattaforma per l'animazione grafica 2D (bitmap e vettoriale). Il programma utilizza il formato immagine .ai (Adobe Illustrator Artwork), ma è possibile creare animazioni ed esportare i lavori realizzati in files .swf (Flash) e .mov (quest'ultimo solo per la versione Mac). Pencil gestisce i suoni e i livelli (per cui è possibile disegnare vedendo il resto in trasparenza) e può definire diversi punti di vista per le scene. Un'applicazione ipotizzabile del programma è la realizzazione di cartoni animati o di storie illustrate. Naturalmente i risultati migliori si possono ottenere con una tavoletta grafica di buona qualità. ==== <u>VirtualDub</u> ==== ''VirtualDub'' [http://www.virtualdub.org], open source (licenza GNU GPL) per Windows 98/ME/NT4/2000/XP/Vista/7/8/10, disponibile anche in versione portable [http://www.lupopensuite.com/db/virtualdubportable.htm], permette di acquisire ed elaborare contenuti video. Pur non offrendo caratteristiche paragonabili a prodotti professionali come Adobe Premiere, edita i video in modo veloce e lineare e permette di elaborare numerosi formati (ampliabili da filtri forniti da terze parti). Con VirtualDub è possibile: 1) acquisire filmati da TV, telecamere e altre periferiche esterne e comprimerli utilizzando vari formati; 2) importare files .avi anche di grandi dimensioni (oltre la barriera dei 2 GB) e modificarli tramite appositi filtri e/o numerosi parametri; 3) realizzare .gif animate da immagini statiche; 4) importare files .avi, .dvx, .mpg, .mpeg, .gif, .jpg, .png, .tga, .avs e .vdr; 5) esportare i filmati in formato .avi e .dvx; 6) usare funzioni batch per automatizzare le operazioni; 7) ottimizzare l'accesso all'hard disk; 8) ridimensionare e ridurre il rumore in tempo reale; 9) monitorare CPU e spazio libero sul disco; 10) usare scorciatoie per velocizzare le operazioni; 11) operare sulla traccia audio di un video; 12) tagliare, copiare, incollare, unire i filmati. Si può consultare il sito "The filters of Donald Graft" [http://neuron2.net] per prelevare nuovi filtri per il programma. ==== <u>Avisynth</u> ==== ''Avisynth'' [http://sourceforge.net/projects/avisynth2], open source (GNU GPL) per Windows, è orientato alla post-produzione e fornisce molti metodi per la modifica dei propri video. Il software funziona grazie a script in formato .avs ed è molto più complesso da usare rispetto a VirtualDub, anche perché non presenta alcuna interfaccia grafica. L'uso in ambienti didattici appare piuttosto problematico, tuttavia la formazione specifica al software di un operatore scolastico permetterebbe la soluzione dei vari problemi di composizione video che si presentano periodicamente nelle scuole. ==== <u>Kdenlive</u> ==== ''Kdenlive'' [http://kdenlive.org], acronimo di KDE Non-Linear Video Editor, è un software open source solo per GNU/Linux pensato per l'elaborazione video non lineare. Kdenlive è discretamente stabile e supporta i files QuickTime, .avi, .wmv, .mpeg, .flv, gli standard PAL, NTSC, HD, HDV e i formati 4:3 e 16:9. In output, il programma può scrivere DVD video con menu e capitoli. In fase di elaborazione video è possibile applicare effetti, transizioni, testi e clip di immagini. L'interfaccia grafica (che richiama quella di Adobe Premiere) è gradevole, intuitiva e semplice da capire, quindi, diversamente da Avisynth, Kdenlive, una volta installato in un sistema Linux compatibile, può essere utilizzato anche da insegnanti non particolarmente esperti. ==== <u>Moviesoup</u> ==== Al contrario di Avisynth e Kdenlive, ''Moviesoup'' [http://moviesoup.co.uk] è un software a pagamento, ma si segnala per la semplicità d'uso, che lo rende adatto anche a bambini della scuola primaria. ==== <u>Avidemux e DVDStyler</u> ==== ''Avidemux'' [http://sourceforge.net/projects/avidemux/][http://www.winpenpack.com/en/download.php?view.734], open source per Windows (32 e 64 Bit), Linux e Mac OS X, supporta i formati .avi, QuickTime e .mpeg ed è versatile e ricco di opzioni. Il programma in particolare può: 1) modificare, tagliare, unire video; 2) convertire i filmati in tutti i formati più importanti; 3) apporre filtri; 4) lavorare con i sottotitoli; 5) modificare, integrare e sostituire la traccia audio. L'interfaccia è piuttosto intuitiva e basta un po' di pratica per ottenere ottimi contenuti multimediali, anche se non paragonabili a quelli di corrispondenti software commerciali. Rispetto a VirtualDub, Avidemux è molto più curato esteticamente, è più completo ed è più semplice da usare. Avidemux, disponibile anche in italiano, è sicuramente consigliabile quando si devono tagliare alcuni fotogrammi o piccole parti da un video. Sotto l'area di visualizzazione (al centro) si trovano i comandi del player (nell'ordine: Play, Stop, Vai al frame precedente e successivo, Vai al keyframe precedente e successivo, Imposta l'inizio e la fine di un marcatore, Cerca i frames neri, Vai al primo o all'ultimo frame, Vai indietro o avanti di un minuto); ancora più sotto una barra di stato ci fornisce informazioni sull'avanzamento e sui tipi dei fotogrammi; e si può anche scegliere se visualizzare solo le parti eventualmente filtrate. Le configurazioni più complesse si trovano sulla sinistra e comprendono opzioni per il decoder video, l'output video, l'ouput audio, l'output contenitore. Infine nel ricco menù superiore, posto sopra le tre icone per il richiamo e il salvataggio dei files e per la richiesta di informazioni, si trovano sltre funzioni più complesse, come il salvataggio dei fotogrammi come immagini .bmp e .jpg, l'inserimento di un logo persistente, l'applicazione di vari tipi di zoom e la modifica del rumore video (noise), della nitidezza (sharpness) e dei colori. Da segnalare peraltro la presenza di un potente motore di scripting utile per gli utenti più esperti. Nel sito di YouTube, oltre a una guida rapida al programma [http://www.youtube.com/watch?v=fWikDX0g3FE], sono presenti numerosi tutorial sul programma [https://www.youtube.com/results?search_query=avidemux]. All'indirizzo [http://www.pcpercaso.com/video-editing/10-tutorial-dvd-avidemux-dvdstyler.html] troviamo invece una guida per l'uso del programma in combinazione con ''DVDStyler'' [http://www.digital-digest.com/software/download.php?sid=1101&ssid=0&did=30][http://www.winpenpack.com/en/download.php?view.1255] un software per la creazione di menu per DVD. Anche per DVDStyler non mancano tutorial dedicati in YouTube [https://www.youtube.com/results?search_query=dvdstyler]. ==== <u>Creazione e modifica di sottotitoli</u> ==== ''Subtitle Edit'' [http://www.nikse.dk/SubtitleEdit/][http://www.winpenpack.com/en/download.php?view.1333], freeware per Windows, richiede per il proprio funzionamento .NET Framework e si occupa specificamente dell'inserimento e della modifica di sottotitoli nei video. In modo simile funziona ''Subtitle Creator'' [http://sourceforge.net/projects/subtitlecreator/files/SubtitleCreator/], che si segnala per la facilità d'uso dell'interfaccia WYSIWYG. ''SubRip'' [http://sourceforge.net/projects/subrip/], open source per Windows, all'opposto, estrae dai video i sottotitoli con il loro timing esportandoli in un file di testo; il programma può risultare utile quando si vogliono tradurre dei sottotitoli in lingue diverse. ==== <u>Mpg2Cut2</u> ==== ''Mpg2Cut2'' [http://sourceforge.net/projects/mpg2cut2/], sempre gratuito per Windows, è studiato invece per la manipolazione (taglio, unione, divisione) di files video in formato .mpg, .mpv, .m2v, .vob, .m1v, .ts, .evo, .m2t, .pva e .mpeg. ==== <u>VideoLan Movie Creator</u> ==== ''VideoLan Movie Creator'' [ftp://ftp.videolan.org/pub/videolan/testing/vlmc/vlmc-0.1.0.exe] è un software open source multipiattaforma semi-professionale per l'editing video basato sul noto ''VLC Media Player'' [http://www.videolan.org/vlc] e [http://www.winpenpack.com/en/download.php?view.36]. Il programma, distribuito con licenza GNU GPL, pur essendo alle prime "releases" (con tutti i problemi di stabilità connessi), promette bene e supporta i formati video PAL<ref>Phase Alternating Line.</ref> e NTCS<ref>National Television System Committee, sistema televisivo usato soprattutto in Nord-America.</ref> con varie risoluzioni (VCD, SVCD,DVD, HDTVi, HDTVp). E' possibile [https://jjtiktok.com/id importare video], ridimensionarli, riprodurli in tempo reale, tagliarne alcune parti e molto altro. Al termine del montaggio video si può caricare il lavoro direttamente su Youtube. Il punto di forza di VideoLan Movie Creator è sicuramente la facilità d'uso, per cui il software è consigliato per ambienti educativi. ==== <u>Animata</u> ==== ''Animata'' [http://animata.kibu.hu/index.html] è un programma web particolare (e non molto immediato nell'uso) per la realizzazione di filmati con pupazzi filiformi da far muovere su sfondi animati. ==== <u>Creare filmati da più immagini</u> ==== Infine, per la creazione di filmati a partire da più immagini .jpg sono da segnalare alcuni software gratuiti: # ''PhotoLapse'' [http://www.softwaredidattico.org/files/photolapse.zip], stand-alone e leggerissimo (solo 152 Kb), è facile da usare, è disponibile per Windows e trasforma le immagini .jpg selezionate in semplici animazioni .avi; # ''PhotoFilmStrip'' [https://portableapps.com/apps/graphics_pictures/photofilmstrip-portable], open source per Linux e Windows, è disponibile anche in italiano con licenza GPL; PhotoFilmStrip crea, a partire dalle proprie immagini, animazioni e filmati in formato VCD, SVCD, DVD e FULL-HD; il tutto avviene molto facilmente e velocemente attraverso tre semplici passi: 1) selezione delle foto; 2) impostazione delle transizioni; 3) montaggio del video; una guida completa è stata realizzata da Gustavo Barbieri [http://punto-informatico.it/s_3363861/Download/News/photofilmstrip.aspx]. # ''Alternate Pic View ExeSlide'' [http://www.alternate-tools.com/pages/c_exeslide.php?lang=ENG] è un programma versatilissimo: partendo dalle immagini selezionate, si possono creare 4 tipi di eseguibili (.exe), compresi 3 diversi minigiochi, e poi files .scr, .swf, .avi e .gif animate. ==== <u>Servizi web per la produzione video</u> ==== Anche per la produzione video esistono diversi servizi web interessanti, orientati per lo più alla produzione di files Flash .swf: # ''Domo Animate'' [http://goanimate4schools.com/public_index], adatto a bambini molto piccoli, serve a creare vivaci cartoni animati; si possono realizzare splendide animazioni in un ambiente gradevole che consente l'inserimento nei vari frames di diversi elementi: personaggi animati (con varie azioni e differenti movimenti), fumetti (editabili e personalizzabili nello stile), sfondi vivacissimi, oggetti ridimensionabili e specchiabili, brani musicali, disegni/effetti grafici modificabili; sono disponibili ben 5 librerie di elementi: "Domo", "Cartoon Classics", "Holiday And Seasonal", "Monster Mayhen", "Stick Figure"; # con ''Make Comix Belief'' [http://www.makebeliefscomix.com] si possono realizzare fumetti composti di 2, 3 o 4 vignette; sono disponibili 7 colori di sfondo, oltre 50 personaggi ("characters"), 16 nuvole per colloqui e pensieri, diversi balloons espressivi e numerosi oggetti; tramite i comandi sulla barra a sinistra, gli oggetti posti nelle vignette possono essere spostati, scalati, invertiti (a specchio), cancellati, portati in primo piano o indietro; "Start Over" azzera il fumetto, "Print/Email" lo stampa o manda via e-mail; altri ambienti simili, ma molto meno performanti sono ''Creaza Cartoonist'' [http://www.creazaeducation.com/cartoonist] e ''Pixton'' [http://www.pixton.com]; molto più completo appare invece ''ComicMaster'' [http://www.comicmaster.org.uk], che consente la creazione di bellissimi fumetti e coloratissime strisce; è possibile impostare la distribuzione delle vignette, gli sfondi, i personaggi, le nuvolette (testo parlato e pensato), le caselle di narrazione, gli effetti speciali; il salvataggio del lavoro è permesso solo agli utenti registrati; # ''Animaps'' [http://www.animaps.com] crea carte geografiche animate utilizzando Google Maps; # ''TubeChop'' [http://www.tubechop.com] permette (tramite il codice "embed" fornito) la condivisione e l'utilizzo in propri siti di filmati video di YouTube o di loro parti specificate semplicemente indicando l'URL ed agendo sui parametri mostrati ("Start", "End"); # con ''Comment Bubble'' [http://www.commentbubble.com] si possono inserire commenti e note in filmati e video e condividerli on-line nella forma modificata. ==== <u>Convertitori</u> ==== Come convertitore tra formati video appare molto interessante ed efficace ''HandBrake'' [http://sourceforge.net/projects/handbrake], open source (con licenza GPL) per Linux, MacOS X e Windows. Il programma supporta tutti i più comuni formati multimediali, sia video (inclusi BluRay e DVD non protetti) che audio (.aac, .mp3, .flac, .ac3) e permette la modifica di sottotitoli e capitoli e l'inserimento di diversi filtri (Cropping, Scaling, Deblocking, DeInterlace, DeTelecine, ecc.). Oltre a questo programma è consigliabile anche ''TEncoder Video Converter'' [http://sourceforge.net/projects/tencoder], open source disponibile anche come portatile; l'applicazione supporta tutti i formati video considerando separatamente nelle conversioni lingue e sottotitoli degli originali. Con i principali formati video, ma anche audio, lavorano peraltro altri software: # ''Eusing Free Video Converter'' [http://www.eusing.com/free_video_converter/video_converter.htm] è facile da usare e non richiede codecs esterni; # ''Any Video Converter Free'' [http://www.anvsoft.com] si segnala sia perché offre numerosi profili di conversione già pronti, sia per le funzioni di editing (ad es. tagli ed unioni di video) e di cattura dei fotogrammi (in fase di setup fare attenzione a non installare i programmi di terze parti eventualmente proposti); # ''500th Video Converter'' [http://www.glorylogic.com/video-converter.html] è leggerissimo e di facile utilizzo; è possibile, rispetto ai video caricati: convertirli nei formati .avi, .mov, .mkv, .wmv, .vcd, .dvd, .mp4; estrarne l'audio e salvandolo in files .mp3, .wav, .ogg, .flac, .wma; registrarli su CD, DVD e dischi Blue-ray; visualizzarne un'anteprima e salvare fotogrammi singoli; è interessante notare come il software funziona con tutti i sistemi operativi Windows a partire da Windows Xp. ==== <u>Gif animate</u> ==== Molto interessante è anche ''OpenAviToGif'' [http://sourceforge.net/projects/openavitogif], open source per Windows; il programma converte files video .avi, .mkv, .mpg, .mp4, .flv, .mov e .rm in .gif animate sulla base delle impostazioni dell'utente (risoluzione, colori, ritardi tra i frames, iterazioni. ecc.). Simile è ''QGifer'' [http://sourceforge.net/projects/qgifer/], open source per Windows e Linux, disponibile anche portable, utile per la creazione di .gif animate a partire da frames estratti da video in formato .avi e .mp4. On-line per la creazione di .gif animate a partire dalle proprie immagini sono da segnalare diversi servizi, tutti gratuiti e senza bisogno di registrazione: 1) ''Picasion'' [http://picasion.com], con possibilità di impostare la grandezza (100, 125, 300, 400 pixel o libera fino a 450 pixel) e la velocità (Faster!, Fast, Normal, Slow, Slower, libera fino a 10 secondi) dei files prodotti; 2) ''GifUp'' [http://www.gifup.com], con il controllo della velocità dell'animazione e diverse possibilità di importazione delle immagini necessarie (cattura tramite webcam, upload dal proprio pc, link Internet, prelevamente dagli archivi Flickr); 3) ''GIFMake'' [http://gifmake.com], con caricamento delle immagini (max 1024 kb) da URL Internet o dal proprio hard disk, indicazione del numero di ripetizioni dell'animazione (0 = infinito) ed impostazione delle dimensioni (max 500x500 pixel) delle .gif animate da realizzare; 4) ''MakeAGif'' [http://makeagif.com], con il limite di 1024 kb per le immagini da utilizzare; 5) ''Gickr'' [http://www.gickr.com], con importazione delle immagini (max 10) da indirizzo web o dal proprio computer e praticamente le stesse impostazioni/caratteristiche di Picasion. TUTTI I COLLEGAMENTI: # [http://www.softwaredidattico.org/libro/links_3_2_6_1/index.html PARTE 1] # [http://www.softwaredidattico.org/libro/links_3_2_6_2/index.html PARTE 2] '''Note''' [[Categoria:Software e didattica|Video e animazioni]] {{Avanzamento|100%|13 luglio 2018}} fod71lo38fv0ccl8ptxn8d9qa1lh55i 501055 501054 2026-08-19T22:12:08Z ~2026-45514-04 54704 i found useful free video tools, so i seem it would be shared with people 501055 wikitext text/x-wiki <noinclude>{{Software e didattica}}</noinclude> ===Video e animazioni=== Le animazioni e le immagini in movimento sono elementi particolarmente apprezzati da alunni, genitori e insegnanti, ma la loro preparazione (e utilizzazione all'interno di learning objects) non è sempre agevole. La limitata presenza di strumenti freeware e open source per la composizione video costituisce un limite evidente, mentre leggermente migliore è il panorama dei software gratuiti per il trattamento di immagini .gif animate, di files .flv e di filmati .avi a bassa risoluzione. Ci permettiamo di suggerire un inserimento discreto di elementi video nei nostri oggetti di apprendimento, anche per non aumentarne eccessivamente dimensioni e pesantezza. Immediatamente di seguito riporteremo e descriveremo invece alcune applicazioni gratuite che possono risultare utili per preparare animazioni, ma non garantendo per esse in assoluto risultati soddisfacenti in ogni sistema operativo e in qualsiasi condizione e ben sapendo che alcuni software commerciali (come Pinnacle Studio e Nero Vision) sono obiettivamente inarrivabili (e irrinunciabili nel caso si vogliano ottenere risultati professionali). Peraltro non dobbiamo dimenticare che il mondo del multimediale in Windows è piuttosto complesso e sempre in evoluzione. Per governare i cambiamenti e risultare sempre aggiornati può essere utile considerare un'eccezionale raccolta di codec audio e video, ''K-Lite Codec Pack (Full)'' [http://www.codecguide.com/], con un comodissimo programma di installazione. ==== <u>Windows Movie Maker</u> ==== ''Windows Movie Maker'' è stato presente nei sistemi Windows fino alla versione Xp. Il programma non è più nemmeno disponibile dal sito della Microsoft. ==== <u>Synfig Studio</u> ==== ''Synfig Studio'' [https://www.synfig.org/] è un programma di animazione vettoriale 2D utilizzabile gratuitamente per Windows, Mac OS X e Linux. Una versione portatile molto comoda è stata preparata dagli esperti di WinPenPack [http://www.winpenpack.com/en/request.php?1275]. Synfig Studio permette di ottenere animazioni fluide senza doverne disegnare individualmente ogni fotogramma. Le tecniche di trasformazione morfologica (passaggio tra due immagini) e di ritaglio (piccole modifiche applicate nel tempo a un'immagine) consentono una facile creazione dei necessari fotogrammi intermedi. In effetti il programma applica effetti avanzati di interpolazione, limitando drasticamente la necessità dell'intervento umano. Occorre comunque una certa pratica per l'utilizzo efficace del programma, certamente non adatto a bambini e adolescenti. E' possibile importare immagini create da GIMP o nel formato .svg, mentre l'esportazione dei lavori può avvenire (ma in certi casi con alcuni artifizi) verso diversi formati di immagini (.bmp, .gif, .jpg, .png) e di video (.dv, .mpg, .flv). ==== <u>Pencil2D</u> ==== Più semplice da usare, pur essendo disponibile solo in lingua inglese, è ''Pencil2D'' [https://www.pencil2d.org/download/], un altro software multipiattaforma per l'animazione grafica 2D (bitmap e vettoriale). Il programma utilizza il formato immagine .ai (Adobe Illustrator Artwork), ma è possibile creare animazioni ed esportare i lavori realizzati in files .swf (Flash) e .mov (quest'ultimo solo per la versione Mac). Pencil gestisce i suoni e i livelli (per cui è possibile disegnare vedendo il resto in trasparenza) e può definire diversi punti di vista per le scene. Un'applicazione ipotizzabile del programma è la realizzazione di cartoni animati o di storie illustrate. Naturalmente i risultati migliori si possono ottenere con una tavoletta grafica di buona qualità. ==== <u>VirtualDub</u> ==== ''VirtualDub'' [http://www.virtualdub.org], open source (licenza GNU GPL) per Windows 98/ME/NT4/2000/XP/Vista/7/8/10, disponibile anche in versione portable [http://www.lupopensuite.com/db/virtualdubportable.htm], permette di acquisire ed elaborare contenuti video. Pur non offrendo caratteristiche paragonabili a prodotti professionali come Adobe Premiere, edita i video in modo veloce e lineare e permette di elaborare numerosi formati (ampliabili da filtri forniti da terze parti). Con VirtualDub è possibile: 1) acquisire filmati da TV, telecamere e altre periferiche esterne e comprimerli utilizzando vari formati; 2) importare files .avi anche di grandi dimensioni (oltre la barriera dei 2 GB) e modificarli tramite appositi filtri e/o numerosi parametri; 3) realizzare .gif animate da immagini statiche; 4) importare files .avi, .dvx, .mpg, .mpeg, .gif, .jpg, .png, .tga, .avs e .vdr; 5) esportare i filmati in formato .avi e .dvx; 6) usare funzioni batch per automatizzare le operazioni; 7) ottimizzare l'accesso all'hard disk; 8) ridimensionare e ridurre il rumore in tempo reale; 9) monitorare CPU e spazio libero sul disco; 10) usare scorciatoie per velocizzare le operazioni; 11) operare sulla traccia audio di un video; 12) tagliare, copiare, incollare, unire i filmati. Si può consultare il sito "The filters of Donald Graft" [http://neuron2.net] per prelevare nuovi filtri per il programma. ==== <u>Avisynth</u> ==== ''Avisynth'' [http://sourceforge.net/projects/avisynth2], open source (GNU GPL) per Windows, è orientato alla post-produzione e fornisce molti metodi per la modifica dei propri video. Il software funziona grazie a script in formato .avs ed è molto più complesso da usare rispetto a VirtualDub, anche perché non presenta alcuna interfaccia grafica. L'uso in ambienti didattici appare piuttosto problematico, tuttavia la formazione specifica al software di un operatore scolastico permetterebbe la soluzione dei vari problemi di composizione video che si presentano periodicamente nelle scuole. ==== <u>Kdenlive</u> ==== ''Kdenlive'' [http://kdenlive.org], acronimo di KDE Non-Linear Video Editor, è un software open source solo per GNU/Linux pensato per l'elaborazione video non lineare. Kdenlive è discretamente stabile e supporta i files QuickTime, .avi, .wmv, .mpeg, .flv, gli standard PAL, NTSC, HD, HDV e i formati 4:3 e 16:9. In output, il programma può scrivere DVD video con menu e capitoli. In fase di elaborazione video è possibile applicare effetti, transizioni, testi e clip di immagini. L'interfaccia grafica (che richiama quella di Adobe Premiere) è gradevole, intuitiva e semplice da capire, quindi, diversamente da Avisynth, Kdenlive, una volta installato in un sistema Linux compatibile, può essere utilizzato anche da insegnanti non particolarmente esperti. ==== <u>Moviesoup</u> ==== Al contrario di Avisynth e Kdenlive, ''Moviesoup'' [http://moviesoup.co.uk] è un software a pagamento, ma si segnala per la semplicità d'uso, che lo rende adatto anche a bambini della scuola primaria. ==== <u>Avidemux e DVDStyler</u> ==== ''Avidemux'' [http://sourceforge.net/projects/avidemux/][http://www.winpenpack.com/en/download.php?view.734], open source per Windows (32 e 64 Bit), Linux e Mac OS X, supporta i formati .avi, QuickTime e .mpeg ed è versatile e ricco di opzioni. Il programma in particolare può: 1) modificare, tagliare, unire video; 2) convertire i filmati in tutti i formati più importanti; 3) apporre filtri; 4) lavorare con i sottotitoli; 5) modificare, integrare e sostituire la traccia audio. L'interfaccia è piuttosto intuitiva e basta un po' di pratica per ottenere ottimi contenuti multimediali, anche se non paragonabili a quelli di corrispondenti software commerciali. Rispetto a VirtualDub, Avidemux è molto più curato esteticamente, è più completo ed è più semplice da usare. Avidemux, disponibile anche in italiano, è sicuramente consigliabile quando si devono tagliare alcuni fotogrammi o piccole parti da un video. Sotto l'area di visualizzazione (al centro) si trovano i comandi del player (nell'ordine: Play, Stop, Vai al frame precedente e successivo, Vai al keyframe precedente e successivo, Imposta l'inizio e la fine di un marcatore, Cerca i frames neri, Vai al primo o all'ultimo frame, Vai indietro o avanti di un minuto); ancora più sotto una barra di stato ci fornisce informazioni sull'avanzamento e sui tipi dei fotogrammi; e si può anche scegliere se visualizzare solo le parti eventualmente filtrate. Le configurazioni più complesse si trovano sulla sinistra e comprendono opzioni per il decoder video, l'output video, l'ouput audio, l'output contenitore. Infine nel ricco menù superiore, posto sopra le tre icone per il richiamo e il salvataggio dei files e per la richiesta di informazioni, si trovano sltre funzioni più complesse, come il salvataggio dei fotogrammi come immagini .bmp e .jpg, l'inserimento di un logo persistente, l'applicazione di vari tipi di zoom e la modifica del rumore video (noise), della nitidezza (sharpness) e dei colori. Da segnalare peraltro la presenza di un potente motore di scripting utile per gli utenti più esperti. Nel sito di YouTube, oltre a una guida rapida al programma [https://www.youtube.com/watch?v=fWikDX0g3FE], sono presenti numerosi tutorial sul programma [https://www.youtube.com/results?search_query=avidemux]. All'indirizzo [http://www.pcpercaso.com/video-editing/10-tutorial-dvd-avidemux-dvdstyler.html] troviamo invece una guida per l'uso del programma in combinazione con ''DVDStyler'' [http://www.digital-digest.com/software/download.php?sid=1101&ssid=0&did=30][http://www.winpenpack.com/en/download.php?view.1255] un software per la creazione di menu per DVD. Anche per DVDStyler non mancano tutorial dedicati in YouTube [https://www.youtube.com/results?search_query=dvdstyler]. ==== <u>Creazione e modifica di sottotitoli</u> ==== ''Subtitle Edit'' [http://www.nikse.dk/SubtitleEdit/][http://www.winpenpack.com/en/download.php?view.1333], freeware per Windows, richiede per il proprio funzionamento .NET Framework e si occupa specificamente dell'inserimento e della modifica di sottotitoli nei video. In modo simile funziona ''Subtitle Creator'' [http://sourceforge.net/projects/subtitlecreator/files/SubtitleCreator/], che si segnala per la facilità d'uso dell'interfaccia WYSIWYG. ''SubRip'' [http://sourceforge.net/projects/subrip/], open source per Windows, all'opposto, estrae dai video i sottotitoli con il loro timing esportandoli in un file di testo; il programma può risultare utile quando si vogliono tradurre dei sottotitoli in lingue diverse. ==== <u>Mpg2Cut2</u> ==== ''Mpg2Cut2'' [http://sourceforge.net/projects/mpg2cut2/], sempre gratuito per Windows, è studiato invece per la manipolazione (taglio, unione, divisione) di files video in formato .mpg, .mpv, .m2v, .vob, .m1v, .ts, .evo, .m2t, .pva e .mpeg. ==== <u>VideoLan Movie Creator</u> ==== ''VideoLan Movie Creator'' [ftp://ftp.videolan.org/pub/videolan/testing/vlmc/vlmc-0.1.0.exe] è un software open source multipiattaforma semi-professionale per l'editing video basato sul noto ''VLC Media Player'' [http://www.videolan.org/vlc] e [http://www.winpenpack.com/en/download.php?view.36]. Il programma, distribuito con licenza GNU GPL, pur essendo alle prime "releases" (con tutti i problemi di stabilità connessi), promette bene e supporta i formati video PAL<ref>Phase Alternating Line.</ref> e NTCS<ref>National Television System Committee, sistema televisivo usato soprattutto in Nord-America.</ref> con varie risoluzioni (VCD, SVCD,DVD, HDTVi, HDTVp). E' possibile [https://jjtiktok.com/id importare video], ridimensionarli, riprodurli in tempo reale, tagliarne alcune parti e molto altro. Al termine del montaggio video si può caricare il lavoro direttamente su Youtube. Il punto di forza di VideoLan Movie Creator è sicuramente la facilità d'uso, per cui il software è consigliato per ambienti educativi. ==== <u>Animata</u> ==== ''Animata'' [http://animata.kibu.hu/index.html] è un programma web particolare (e non molto immediato nell'uso) per la realizzazione di filmati con pupazzi filiformi da far muovere su sfondi animati. ==== <u>Creare filmati da più immagini</u> ==== Infine, per la creazione di filmati a partire da più immagini .jpg sono da segnalare alcuni software gratuiti: # ''PhotoLapse'' [http://www.softwaredidattico.org/files/photolapse.zip], stand-alone e leggerissimo (solo 152 Kb), è facile da usare, è disponibile per Windows e trasforma le immagini .jpg selezionate in semplici animazioni .avi; # ''PhotoFilmStrip'' [https://portableapps.com/apps/graphics_pictures/photofilmstrip-portable], open source per Linux e Windows, è disponibile anche in italiano con licenza GPL; PhotoFilmStrip crea, a partire dalle proprie immagini, animazioni e filmati in formato VCD, SVCD, DVD e FULL-HD; il tutto avviene molto facilmente e velocemente attraverso tre semplici passi: 1) selezione delle foto; 2) impostazione delle transizioni; 3) montaggio del video; una guida completa è stata realizzata da Gustavo Barbieri [http://punto-informatico.it/s_3363861/Download/News/photofilmstrip.aspx]. # ''Alternate Pic View ExeSlide'' [http://www.alternate-tools.com/pages/c_exeslide.php?lang=ENG] è un programma versatilissimo: partendo dalle immagini selezionate, si possono creare 4 tipi di eseguibili (.exe), compresi 3 diversi minigiochi, e poi files .scr, .swf, .avi e .gif animate. ==== <u>Servizi web per la produzione video</u> ==== Anche per la produzione video esistono diversi servizi web interessanti, orientati per lo più alla produzione di files Flash .swf: # ''Domo Animate'' [http://goanimate4schools.com/public_index], adatto a bambini molto piccoli, serve a creare vivaci cartoni animati; si possono realizzare splendide animazioni in un ambiente gradevole che consente l'inserimento nei vari frames di diversi elementi: personaggi animati (con varie azioni e differenti movimenti), fumetti (editabili e personalizzabili nello stile), sfondi vivacissimi, oggetti ridimensionabili e specchiabili, brani musicali, disegni/effetti grafici modificabili; sono disponibili ben 5 librerie di elementi: "Domo", "Cartoon Classics", "Holiday And Seasonal", "Monster Mayhen", "Stick Figure"; # con ''Make Comix Belief'' [http://www.makebeliefscomix.com] si possono realizzare fumetti composti di 2, 3 o 4 vignette; sono disponibili 7 colori di sfondo, oltre 50 personaggi ("characters"), 16 nuvole per colloqui e pensieri, diversi balloons espressivi e numerosi oggetti; tramite i comandi sulla barra a sinistra, gli oggetti posti nelle vignette possono essere spostati, scalati, invertiti (a specchio), cancellati, portati in primo piano o indietro; "Start Over" azzera il fumetto, "Print/Email" lo stampa o manda via e-mail; altri ambienti simili, ma molto meno performanti sono ''Creaza Cartoonist'' [http://www.creazaeducation.com/cartoonist] e ''Pixton'' [http://www.pixton.com]; molto più completo appare invece ''ComicMaster'' [http://www.comicmaster.org.uk], che consente la creazione di bellissimi fumetti e coloratissime strisce; è possibile impostare la distribuzione delle vignette, gli sfondi, i personaggi, le nuvolette (testo parlato e pensato), le caselle di narrazione, gli effetti speciali; il salvataggio del lavoro è permesso solo agli utenti registrati; # ''Animaps'' [http://www.animaps.com] crea carte geografiche animate utilizzando Google Maps; # ''TubeChop'' [http://www.tubechop.com] permette (tramite il codice "embed" fornito) la condivisione e l'utilizzo in propri siti di filmati video di YouTube o di loro parti specificate semplicemente indicando l'URL ed agendo sui parametri mostrati ("Start", "End"); # con ''Comment Bubble'' [http://www.commentbubble.com] si possono inserire commenti e note in filmati e video e condividerli on-line nella forma modificata. ==== <u>Convertitori</u> ==== Come convertitore tra formati video appare molto interessante ed efficace ''HandBrake'' [http://sourceforge.net/projects/handbrake], open source (con licenza GPL) per Linux, MacOS X e Windows. Il programma supporta tutti i più comuni formati multimediali, sia video (inclusi BluRay e DVD non protetti) che audio (.aac, .mp3, .flac, .ac3) e permette la modifica di sottotitoli e capitoli e l'inserimento di diversi filtri (Cropping, Scaling, Deblocking, DeInterlace, DeTelecine, ecc.). Oltre a questo programma è consigliabile anche ''TEncoder Video Converter'' [http://sourceforge.net/projects/tencoder], open source disponibile anche come portatile; l'applicazione supporta tutti i formati video considerando separatamente nelle conversioni lingue e sottotitoli degli originali. Con i principali formati video, ma anche audio, lavorano peraltro altri software: # ''Eusing Free Video Converter'' [http://www.eusing.com/free_video_converter/video_converter.htm] è facile da usare e non richiede codecs esterni; # ''Any Video Converter Free'' [http://www.anvsoft.com] si segnala sia perché offre numerosi profili di conversione già pronti, sia per le funzioni di editing (ad es. tagli ed unioni di video) e di cattura dei fotogrammi (in fase di setup fare attenzione a non installare i programmi di terze parti eventualmente proposti); # ''500th Video Converter'' [http://www.glorylogic.com/video-converter.html] è leggerissimo e di facile utilizzo; è possibile, rispetto ai video caricati: convertirli nei formati .avi, .mov, .mkv, .wmv, .vcd, .dvd, .mp4; estrarne l'audio e salvandolo in files .mp3, .wav, .ogg, .flac, .wma; registrarli su CD, DVD e dischi Blue-ray; visualizzarne un'anteprima e salvare fotogrammi singoli; è interessante notare come il software funziona con tutti i sistemi operativi Windows a partire da Windows Xp. ==== <u>Gif animate</u> ==== Molto interessante è anche ''OpenAviToGif'' [http://sourceforge.net/projects/openavitogif], open source per Windows; il programma converte files video .avi, .mkv, .mpg, .mp4, .flv, .mov e .rm in .gif animate sulla base delle impostazioni dell'utente (risoluzione, colori, ritardi tra i frames, iterazioni. ecc.). Simile è ''QGifer'' [http://sourceforge.net/projects/qgifer/], open source per Windows e Linux, disponibile anche portable, utile per la creazione di .gif animate a partire da frames estratti da video in formato .avi e .mp4. On-line per la creazione di .gif animate a partire dalle proprie immagini sono da segnalare diversi servizi, tutti gratuiti e senza bisogno di registrazione: 1) ''Picasion'' [http://picasion.com], con possibilità di impostare la grandezza (100, 125, 300, 400 pixel o libera fino a 450 pixel) e la velocità (Faster!, Fast, Normal, Slow, Slower, libera fino a 10 secondi) dei files prodotti; 2) ''GifUp'' [http://www.gifup.com], con il controllo della velocità dell'animazione e diverse possibilità di importazione delle immagini necessarie (cattura tramite webcam, upload dal proprio pc, link Internet, prelevamente dagli archivi Flickr); 3) ''GIFMake'' [http://gifmake.com], con caricamento delle immagini (max 1024 kb) da URL Internet o dal proprio hard disk, indicazione del numero di ripetizioni dell'animazione (0 = infinito) ed impostazione delle dimensioni (max 500x500 pixel) delle .gif animate da realizzare; 4) ''MakeAGif'' [https://makeagif.com], con il limite di 1024 kb per le immagini da utilizzare; 5) ''Gickr'' [http://www.gickr.com], con importazione delle immagini (max 10) da indirizzo web o dal proprio computer e praticamente le stesse impostazioni/caratteristiche di Picasion. [https://jjtiktok.com/id Video Downloader for Tiktokers] TUTTI I COLLEGAMENTI: # [http://www.softwaredidattico.org/libro/links_3_2_6_1/index.html PARTE 1] # [http://www.softwaredidattico.org/libro/links_3_2_6_2/index.html PARTE 2] '''Note''' [[Categoria:Software e didattica|Video e animazioni]] {{Avanzamento|100%|13 luglio 2018}} b8y0702yjfxl9dmz6lpqqwghac1a93b Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa 0 41565 501060 501032 2026-08-19T22:44:24Z ~2026-45474-98 54699 501060 wikitext text/x-wiki {{Disposizioni foniche di organi a canne}} Disposizioni foniche del [[w:Libero consorzio comunale di Siracusa|libero consorzio comunale di Siracusa]] raggruppate per comune: * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Siracusa|Siracusa]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Augusta|Augusta]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Avola|Avola]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Canicattini Bagni|Canicattini Bagni]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Carlentini|Carlentini]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Buccheri|Buccheri]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Buscemi|Buscemi]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Floridia|Floridia]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Francoforte|Francoforte]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Lentini|Lentini]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Melilli|Melilli]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Noto|Noto]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Pachino|Pachino]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Palazzolo Acreide|Palazzolo Acreide]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Rosolini|Rosolini]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Solarino|Solarino]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Sortino|Sortino]] {{Avanzamento|15%|20 novembre 2019}} [[Categoria:Disposizioni foniche di organi a canne]] ry2hx0qwzi9uakenwn67qystft6h5w3 Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Siracusa 0 44112 501058 501035 2026-08-19T22:20:41Z ~2026-45474-98 54699 501058 wikitext text/x-wiki {{Disposizioni foniche di organi a canne}} Disposizioni foniche del comune di [[w:Siracusa|Siracusa]] raggruppate per edificio. == Capoluogo == * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Siracusa/Siracusa - Cattedrale metropolitana della Natività di Maria Santissima|Cattedrale metropolitana della Natività di Maria Santissima]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Siracusa/Siracusa - Chiesa di San Filippo Apostolo|Chiesa di San Filippo Apostolo]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Siracusa/Siracusa - Chiesa di San Filippo Neri|Chiesa di San Filippo Neri]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Siracusa/Siracusa - Chiesa di San Giuseppe|Chiesa di San Giuseppe]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Siracusa/Siracusa - Chiesa di San Martino|Chiesa di San Martino]] {{Avanzamento|25%|22 ottobre 2019}} [[Categoria:Disposizioni foniche di organi a canne]] ji9mqonoduo7gotbte09qylps48ds4x Wikibooks:GUS2Wiki 4 51801 501043 500858 2026-08-19T19:54:21Z Alexis Jazz 37143 Updating gadget usage statistics from [[Special:GadgetUsage]] ([[phab:T121049]]) 501043 wikitext text/x-wiki {{#ifexist:Project:GUS2Wiki/top|{{/top}}|This page provides a historical record of [[Special:GadgetUsage]] through its page history. To get the data in CSV format, see wikitext. To customize this message or add categories, create [[/top]].}} I dati che seguono sono estratti da una copia ''cache'' del database, il cui ultimo aggiornamento risale al 2026-08-19T07:25:31Z. Un massimo di {{PLURAL:5000|un risultato è disponibile|5000 risultati è disponibile}} in cache. {| class="sortable wikitable" ! Accessorio !! data-sort-type="number" | Numero di utenti !! data-sort-type="number" | Utenti attivi |- |BordiArrotondati || 31 || 0 |- |CatWatch || 21 || 0 |- |Chat || 22 || 0 |- |EDTitle || 18 || 0 |- |HotCat || 51 || 3 |- |LinkComplete || 18 || 0 |- |MassDelete || 2 || 1 |- |NMS || 11 || 0 |- |Orologio || 36 || 0 |- |Popup || 24 || 3 |- |Purge || 50 || 3 |- |QuickEdit || 31 || 0 |- |Ricetta || data-sort-value="Infinity" | Predefinito || data-sort-value="Infinity" | Predefinito |- |Spostamento || 23 || 2 |- |Toolbar || 14 || 2 |- |Unwatch || 32 || 1 |- |UserEditCount || 37 || 1 |- |Wiked || 39 || 0 |- |canctxt || 10 || 1 |- |dictionaryLookupHover || 20 || 1 |- |lastedit || 41 || 0 |- |nav-aut || 22 || 0 |- |nav-blocklist || 24 || 1 |- |nav-bot || 12 || 0 |- |nav-canc || 25 || 1 |- |nav-cancimm || 9 || 0 |- |nav-css || 20 || 0 |- |nav-js || 17 || 0 |- |nav-log || 31 || 0 |- |nav-newpages || 33 || 0 |- |nav-prob || 23 || 1 |- |nav-rfa || 30 || 1 |- |nav-sandbox || 318 || 1 |- |nav-struadmin || 16 || 0 |- |nav-vand || 26 || 1 |- |section0 || 32 || 0 |- |stru-whois || 21 || 0 |- |strumentivari || 21 || 1 |- |tb-aiutare || 52 || 2 |- |tb-barr || 67 || 1 |- |tb-case || 75 || 1 |- |tb-controllare || 48 || 2 |- |tb-noinclude || 54 || 1 |- |tb-sott || 88 || 1 |} * [[Speciale:GadgetUsage]] * [[m:Meta:GUS2Wiki/Script|GUS2Wiki]] <!-- data in CSV format: BordiArrotondati,31,0 CatWatch,21,0 Chat,22,0 EDTitle,18,0 HotCat,51,3 LinkComplete,18,0 MassDelete,2,1 NMS,11,0 Orologio,36,0 Popup,24,3 Purge,50,3 QuickEdit,31,0 Ricetta,default,default Spostamento,23,2 Toolbar,14,2 Unwatch,32,1 UserEditCount,37,1 Wiked,39,0 canctxt,10,1 dictionaryLookupHover,20,1 lastedit,41,0 nav-aut,22,0 nav-blocklist,24,1 nav-bot,12,0 nav-canc,25,1 nav-cancimm,9,0 nav-css,20,0 nav-js,17,0 nav-log,31,0 nav-newpages,33,0 nav-prob,23,1 nav-rfa,30,1 nav-sandbox,318,1 nav-struadmin,16,0 nav-vand,26,1 section0,32,0 stru-whois,21,0 strumentivari,21,1 tb-aiutare,52,2 tb-barr,67,1 tb-case,75,1 tb-controllare,48,2 tb-noinclude,54,1 tb-sott,88,1 --> ptqi3hqoah2438u33zbp7fkm8dffa8k Software libero a scuola/Minetest/Luanti a scuola 0 60667 501039 500182 2026-08-19T15:40:19Z Mattruffoni 17392 aggiornato la m,opdalità per ottenere un file obj 501039 wikitext text/x-wiki {{Software libero a scuola}} Usare Luanti/Minetest per giocare a conoscere il territorio e, volendo, progettarne gli sviluppi futuri. == Il Progetto: La scuola come laboratorio di pianificazione territoriale == Questo manuale nasce con l'obiettivo di guidare docenti e studenti nell'utilizzo di '''Luanti''' (precedentemente noto come ''Minetest'') come strumento didattico, integrando la tecnologia, la geografia (GIS), la matematica e l'educazione civica. Il cuore del progetto si articola su tre pilastri fondamentali: * '''Esplorare e Osservare (La Georeferenziazione):''' Creare un mondo digitale che sia il facsimile esatto del proprio territorio reale. Attraverso l'importazione di dati geografici e altimetrici reali, gli studenti possono muoversi in scala 1:1 in un ambiente virtuale familiare, imparando a leggere la morfologia della propria terra da una prospettiva inedita e immersiva. * '''Progettare ed Eseguire (La Ricostruzione):''' Permettere agli studenti di ricostruire l'ambiente, i monumenti e i complessi urbani. Questo processo stimola lo sviluppo di competenze geometriche, di calcolo spaziale e di problem-solving strutturale, costringendo il ragazzo a passare dall'osservazione della realtà alla sua astrazione e successiva esecuzione tridimensionale a blocchi. * '''Partecipare (La Cittadinanza Attiva):''' Dare ai ragazzi la possibilità di utilizzare il server condiviso come un laboratorio democratico per la pianificazione urbana e infrastrutturale collettiva. Gli studenti non si limitano a replicare il presente o il passato, ma possono proporre modifiche, nuove infrastrutture e varianti urbanistiche, imparando il valore del dibattito, della negoziazione e della progettazione comunitaria del bene comune. Attraverso questo percorso, il mondo voxel di Luanti smette di essere un semplice videogioco e diventa un vero e proprio '''gemello digitale didattico''', un ponte tra la scuola e il territorio in grado di formare cittadini consapevoli e tecnicamente preparati. == Il Valore del Software Libero e l'Accessibilità == L'adozione di software libero come Luanti elimina alla radice l'ostacolo delle licenze commerciali e dei costi per le scuole e le famiglie. Questa libertà tecnologica si traduce in una straordinaria agilità operativa: permette di configurare, personalizzare e pubblicare online un server scolastico in modo immediato. Per gli studenti, l'accesso a questo "gemello digitale" del territorio diventa sicuro e inclusivo: chiunque, da qualsiasi dispositivo a casa o a scuola, può connettersi liberamente e partecipare al progetto collettivo, con l'unico requisito di inserire il proprio nome utente e password personalizzati. == Flusso di lavoro: Dati GIS, Modellazione 3D e Iniezione in Luanti == Questo capitolo documenta passo dopo passo la pipeline tecnologica utilizzata per trasformare i dati geografici e altimetrici reali della Val di Ledro in un mondo 3D interamente calpestabile all'interno del server Luanti (Minetest). === Fase 1: Acquisizione dei dati geografici e modellazione in Blender === ==== 1. Selezione dell'Area di Interesse (OSM) ==== Il progetto ha inizio con la delimitazione della zona geografica. Utilizzando il software di modellazione 3D '''Blender''' combinato con l'add-on '''Blender-GIS''', è stato possibile connettersi direttamente ai server cartografici globali. Tramite l'interfaccia di georeferenziazione, è stato ritagliato il perimetro esatto della Val di Ledro attingendo alla cartografia vettoriale di '''OpenStreetMap (OSM)'''. Questa operazione fissa le coordinate di base (Latitudine/Longitudine) nel sistema di riferimento del progetto. ==== 2. Generazione del Rilievo Altimetrico (SRTM) ==== Una volta ottenuta la mappa bidimensionale, si è passati alla terza dimensione applicando i dati altimetrici reali. Sfruttando la funzione di importazione DEM (Digital Elevation Model) di Blender-GIS, sono stati scaricati i dati '''SRTM (Shuttle Radar Topography Mission)''' forniti dalla NASA. Il plugin ha proiettato questi dati vettoriali sulla mesh piana di Blender, deformandola e generando un modello tridimensionale fedele del rilievo montuoso e della morfologia della valle. ==== 3. Download dei Volumi degli Edifici ==== Per integrare l'elemento antropico, è stato effettuato un download mirato direttamente dal portale ufficiale [https://www.openstreetmap.org openstreetmap.org]. È stato esportato un file con estensione <code>.osm</code>, contenente tutti i metadati e le impronte planimetriche degli edifici (i "volumi" e i poligoni delle case) registrati all'interno della medesima area geografica della valle. ==== 4. Posizionamento e Georeferenziazione delle Case ==== Il file <code>.osm</code> grezzo è stato importato all'interno della scena di Blender, sempre tramite l'ausilio di Blender-GIS. Il plugin, riconoscendo la corrispondenza delle coordinate geografiche condivise, ha posizionato automaticamente e matematicamente i volumi geometrici degli edifici sopra il rilievo 3D precedentemente generato, incollando le fondamenta delle case alle rispettive quote del terreno. Nell'importazione viene scelta l'opzione ''buildings''. ==== 5. Importazione del lago ==== Nello stesso modo, e con lo stesso file .osm, usato per importare gli edifici scegliendo l'opzione ''water'' è stato importato il lago di Ledro. Sul lago si è docvuto applicare un ''modifier'' che ha aggiunto una triangolazione della superficie. ==== 6. Esportazione della Mesh ==== Una volta preparato il file in vblender si è proceduto all'esportazione del modello in un formato di interscambio testuale standard. Il file risultante è stato salvato con il nome di <code>LedroValleCompleta.obj</code>, contenente: l'elenco puro dei vertici tridimensionali del terreno, gli edifici in 3d e la superficie del lago. Un altra informazione contenuta nei file .osm ad esempio è il nome delle vie e degli edifici, ed anche questo dato è interessante da importare nel mondo virtuale in mod da rendewre i luoghi più riconoscibili. === Fase 2: Parsing, Ottimizzazione e Struttura Server === === Il problema tecnologico === I metodi tradizionali di scrittura dei nodi in Luanti via API standard (come `minetest.set_node`) mostrano forti limiti quando si gestiscono milioni di coordinate geometriche: # '''Timeout UDP e Disconnessioni:''' L'elaborazione lineare di file massivi blocca il thread principale del server, causando il congelamento della rete e l'espulsione dei client. # '''Errore Map::getNodeMetadata (Block not found):''' In ambienti a mappa vuota (es. mapgen `singlenode`), il server fallisce l'accesso ai metadati di blocchi non ancora inizializzati sul database del mondo (`map.sqlite`), generando migliaia di warning e fallendo la scrittura. # '''Saturazione RAM in Blender:''' L'uso di modificatori come il ''Remesh'' su mesh territoriali molto estese (es. 20x12 km) satura la memoria volatile del sistema operativo, causando il crash del software di modellazione. === Architettura della Soluzione === La pipeline definitiva si divide in due fasi staccate: un'ottimizzazione matematica dei dati in locale tramite Python e un'iniezione asincrona a basso livello nel server Luanti tramite Lua. ==== Fase 1: Estrazione e Interpolazione dei Dati (Python) ==== Invece di sovraccaricare il motore di gioco o Blender, si utilizza uno script Python esterno sfruttando la libreria '''SciPy''' e l'algoritmo `NearestNDInterpolator` (o `LinearNDInterpolator`). Lo script esegue le seguenti operazioni: # Legge i vertici geometrici (`v X Y Z`) dal file `.obj` originale. # Rileva i confini geografici assoluti della mappa. # Inizializza un interpolatore spaziale e proietta i dati su una griglia fitta bidimensionale regolare (Heightmap) con un passo stabilito (es. ogni 2 metri). # Tappa matematicamente i "buchi di cielo" presenti nella mesh rada, assegnando a ogni coordinata vuota l'altezza corretta calcolata sui punti vicini. # Genera un file di testo ordinato (`ledro_terreno_dati.txt`) in formato `X,Y,Z`. ==== 7. Conversione e Densificazione dei Dati (Python e SciPy) ==== I file <code>.obj</code> nativi presentano una struttura a nuvola di punti (Point Cloud) rada e non ordinata. Con il supporto di '''Gemini''', sono stati sviluppati gli script Python per elaborare i dati: * <code>estrai_griglia.py</code>: Questo script utilizza la libreria scientifica '''SciPy''' (in particolare l'algoritmo <code>NearestNDInterpolator</code>) per analizzare i 66.481 vertici originali distribuiti su un'area di circa 20x12 km. Python proietta questi punti su una griglia fitta bidimensionale regolare (Heightmap) con un passo costante (es. ogni 2 metri), interpolando matematicamente le altezze nei punti vuoti per "tappare i buchi di cielo" e generando un file coordinato e continuo chiamato <code>ledro_terreno_dati.txt</code> in formato <code>X,Y,Z</code>.<syntaxhighlight lang="python"> import os import numpy as np from scipy.interpolate import NearestNDInterpolator FILE_OBJ = "LedroRilievo.obj" FILE_OUTPUT = "ledro_terreno_dati.txt" PASSO = 2 # Un punto ogni 2 metri print("1. Lettura di tutti i vertici dal file OBJ...") punti_validi = [] with open(FILE_OBJ, "r") as f: for line in f: if line.startswith("v "): parti = line.split() if len(parti) >= 4: try: punti_validi.append((float(parti[1]), float(parti[2]), float(parti[3]))) except ValueError: continue if not punti_validi: print("ERRORE: Nessun vertice trovato nel file OBJ!") exit() # Coordinate separate x_arr = np.array([p[0] for p in punti_validi]) y_arr = np.array([p[1] for p in punti_validi]) z_arr = np.array([p[2] for p in punti_validi]) min_x, max_x = int(np.min(x_arr)), int(np.max(x_arr)) min_z, max_z = int(np.min(z_arr)), int(np.max(z_arr)) print(f"Confini rilevati -> X: [{min_x} a {max_x}], Z: [{min_z} a {max_z}]") print("2. Inizializzazione interpolatore geometrico (SciPy)...") # Creiamo l'interpolatore basato sui punti noti dell'OBJ interp = NearestNDInterpolator(list(zip(x_arr, z_arr)), y_arr) print("3. Generazione griglia fitta continua e scrittura...") # Generiamo gli intervalli regolari basati sul PASSO scelto intervallo_x = np.arange(round(min_x / PASSO) * PASSO, round(max_x / PASSO) * PASSO + PASSO, PASSO) intervallo_z = np.arange(round(min_z / PASSO) * PASSO, round(max_z / PASSO) * PASSO + PASSO, PASSO) punti_totali_scritti = 0 with open(FILE_OUTPUT, "w") as out: for gx in intervallo_x: # Calcoliamo l'altezza per l'intera colonna Z in un colpo solo (velocissimo) gz_array = np.array(list(intervallo_z)) gx_array = np.full_like(gz_array, gx) # SciPy calcola le altezze interpolate istantaneamente per tutta la riga altezze_interpolate = interp(gx_array, gz_array) for i, gz in enumerate(intervallo_z): gy = round(altezze_interpolate[i]) out.write(f"{gx},{gy},{gz}\n") punti_totali_scritti += 1 print(f"Operazione completata! Generata griglia solida continua con {punti_totali_scritti} punti complessivi.") </syntaxhighlight> * <code>ledro_convertitore_case.py</code>: Estrae le posizioni degli edifici associandole ai rispettivi blocchi di costruzione, generando il file ordinato <code>ledro_case_dati.txt</code><syntaxhighlight lang="python"> import numpy as np import trimesh import os from math import ceil # ========================================== # CONFIGURAZIONE COSTANTI # ========================================== FILE_OBJ_TERRENO = "LedroRilievo.obj" FILE_OBJ_CASE = "LedroCase.obj" NOME_FILE_USCITA = "ledro_case_dati.txt" # Scala 1.0 per corrispondenza esatta con il terreno a passo 1 metro FAUTORE_SCALA = 1.0 START_Y = 30 def converti_case_streaming(terreno_input, case_input, file_output): if not os.path.exists(case_input) or not os.path.exists(terreno_input): print("Errore: Uno dei file OBJ non esiste nella cartella attuale!") return # 1. Calcolo del centro del terreno per l'allineamento perfetto degli assi print(f"Lettura terreno per allineamento assi: {terreno_input}...") scena_t = trimesh.load(terreno_input, force='mesh') mesh_t = trimesh.util.concatenate([g for g in scena_t.geometry.values()]) if isinstance(scena_t, trimesh.Scene) else scena_t bounds_t = mesh_t.bounds min_x_t, _, min_z_t = bounds_t[0] max_x_t, _, max_z_t = bounds_t[1] centro_x = int((max_x_t - min_x_t) / 2) centro_z = int((max_z_t - min_z_t) / 2) # 2. Caricamento e pulizia della mesh degli edifici print(f"Caricamento edifici da {case_input}...") scena_c = trimesh.load(case_input, force='mesh') if isinstance(scena_c, trimesh.Scene): mesh_unica_case = trimesh.util.concatenate([g for g in scena_c.geometry.values()]) else: mesh_unica_case = scena_c print("Pulizia della mesh e fusione dei vertici adiacenti...") # Valida e salda insieme i poligoni staccati della stessa struttura mesh_unica_case.process(validate=True) print("Separazione degli edifici in componenti connesse...") edifici_grezzi = mesh_unica_case.split(only_watertight=False) # Filtriamo le bricioline geometriche inferiori a 2mq edifici = [edf for edf in edifici_grezzi if edf.area > 2.0] print(f"Trovati {len(edifici)} edifici reali stabili. Generazione geometrie cave...") # Rimuoviamo il vecchio file se presente if os.path.exists(file_output): os.remove(file_output) # 3. Ciclo di generazione geometrica delle case cave (SOLO SOLIDI) edifici_scritti = 0 with open(file_output, "w") as f: for i, edf in enumerate(edifici): b = edf.bounds min_x, min_y, min_z = b[0] max_x, max_y, max_z = b[1] dim_x = int(ceil(max_x - min_x)) dim_y = int(ceil(max_y - min_y)) dim_z = int(ceil(max_z - min_z)) # FILTRO DI SICUREZZA ANTI-LOOP (ARTEFATTI GIS): # Se un "edificio" supera le dimensioni di un enorme isolato, è un errore di mesh dell'OBJ. # Lo saltiamo per evitare che i cicli for successivi congelino la CPU. if dim_x > 60 or dim_z > 60 or dim_y > 40: continue # APPLICAZIONE REGOLE PUNTO 4: Vincoli minimi (5x6x5) larghezza_x = max(5, dim_x) lunghezza_z = max(6, dim_z) altezza_y = max(5, dim_y) # Calcolo coordinate assolute centrate rispetto al terreno start_x = int(min_x - min_x_t - centro_x) start_z = int(min_z - min_z_t - centro_z) start_y = int(min_y + START_Y) edifici_scritti += 1 # Rendering dei soli nodi fisici perimetrali for dx in range(larghezza_x): for dz in range(lunghezza_z): for dy in range(altezza_y): abs_x = start_x + dx abs_z = start_z + dz abs_y = start_y + dy is_muro = (dx == 0 or dx == larghezza_x - 1 or dz == 0 or dz == lunghezza_z - 1) is_pavimento = (dy == 0) is_tetto = (dy == altezza_y - 1) if is_pavimento: blocco = "default:wood" elif is_tetto: blocco = "default:brick" elif is_muro: blocco = "default:stone" else: # Salta l'aria interna! Risparmia lo spazio su disco continue f.write(f"{abs_x},{abs_y},{abs_z},{blocco}\n") if (i + 1) % 100 == 0 or (i + 1) == len(edifici): print(f"Progressione: {i + 1}/{len(edifici)} nodi mesh analizzati... ({edifici_scritti} edifici reali scritti)") print(f"Fatto! File delle case salvato con successo in {file_output}. Scritti {edifici_scritti} edifici.") # ========================================== # PUNTO DI INGRESSO DELLO SCRIPT # ========================================== if __name__ == "__main__": converti_case_streaming(FILE_OBJ_TERRENO, FILE_OBJ_CASE, NOME_FILE_USCITA) </syntaxhighlight> ==== 8. Configurazione dell'Ambiente Virtuale Docker ==== Per ospitare l'infrastruttura di simulazione in modo isolato e replicabile, è stato configurato un container '''Docker''' gestito tramite '''Docker Compose'''. Sulla base di un file <code>docker-compose.yml</code> strutturato ad hoc, la cartella di lavoro del server Luanti/Minetest è stata mappata in locale sul PC dell'utente (tramite i Docker Volumes) per permettere la modifica in tempo reale dei file di gioco. All'interno della configurazione, il mondo è stato battezzato <code>ledro3d</code> e l'utente <code>mattruffoni</code> è stato designato come amministratore di sistema con massimi privilegi energetici.<syntaxhighlight lang="dockerfile"> services: luanti_engine: image: lscr.io/linuxserver/luanti:latest container_name: local_luanti_engine environment: - PUID=1000 - PGID=1000 - TZ=Europe/Rome # FORZATURA: Diciamo a Luanti esattamente quale file .conf leggere dentro il container - CLI_ARGS=--worldname ledro3d --config /config/.minetest/minetest.conf --terminal volumes: - ./server_data:/config/.minetest ports: - 30000:30000/udp restart: unless-stopped </syntaxhighlight> ==== 9. Accessibilità del Server di Gioco ==== Una volta avviato lo stack di Docker tramite terminale (<code>docker compose up -d</code>), il container ha esposto i servizi di rete dedicati. Il server Luanti/Minetest è diventato operativo e raggiungibile in locale dall'indirizzo di loopback '''<code>localhost:30000</code>''', pronto ad accettare le connessioni da parte del client di gioco per l'esplorazione virtuale. === Fase 3: Sviluppo della Mod e Generazione del Mondo === ====Creazione mod '''importatore'''==== Nella cartella ''.../minetest-server/server_data/worlds/ledro3d/worldmods/importatore'' si crea la mod importatore inserendoci il file init.lua, mod.conf e i due file di testo ledro_terreno_dati.txt e ledro_case_dati.txt creati in precedenza. ==== 10. Sviluppo della Mod Lua Asincrona "Importatore" ==== L'iniezione di milioni di nodi all'interno del database del mondo (<code>map.sqlite</code>) presenta forti criticità prestazionali (rischio di timeout UDP e crash per memoria satura). Per ovviare a questo problema, è stata sviluppata una mod personalizzata in linguaggio Lua denominata '''<code>importatore</code>'''. La mod implementa due soluzioni architetturali cruciali: # '''Il VoxelManip Engine (LVM):''' Invece di posizionare un singolo cubo alla volta, la mod alloca grandi porzioni di mappa direttamente nella memoria volatile del server, scrive i blocchi di erba superficiale (<code>default:dirt_with_grass</code>) e le fondamenta sottostanti (<code>default:stone</code>), e forza la scrittura in blocco sul database, azzerando i warning di blocchi non trovati. # '''Gestione tramite Co-routine Lua:''' La lettura dei file <code>.txt</code> è inserita in un ciclo asincrono controllato da co-routine. Tramite l'istruzione <code>coroutine.yield()</code>, la mod rilascia il controllo alla CPU del PC host ogni 100 nodi processati, permettendo al server di rimanere fluido, gestire i pacchetti di rete e consentire il movimento del giocatore durante la crescita progressiva della valle. ==== Fase 2: Iniezione Asincrona nella Mappa (Luanti Mod) ==== La mod Luanti (scritta in `init.lua`) riceve il file a griglia regolare e applica due strategie fondamentali per garantire stabilità e performance: * '''Uso del VoxelManip (LVM):''' Invece di scrivere un blocco alla volta, la mod alloca un'area di memoria temporanea (`minetest.get_voxel_manip()`), manipola l'array dei nodi inserendo la superficie erbosa (`default:dirt_with_grass`) e lo zoccolo di roccia sottostante (`default:stone`), e infine forza la scrittura dell'intero blocco direttamente sul database (`vm:write_to_map()`). Questo bypassa i controlli dei metadati azzerando il warning ''Block not found''. * '''Gestione Asincrona via Co-routine:''' Il ciclo di lettura del file viene inserito in una co-routine Lua (`coroutine.create`). Tramite l'istruzione `coroutine.yield()`, la mod rilascia il controllo alla CPU ogni 100 nodi processati, permettendo al server Luanti di gestire i pacchetti di rete, l'orario del mondo e il login dei giocatori senza lag. ==== Codice init.lua della mod importatore==== <syntaxhighlight lang="lua"> -- ======================================================== -- 1. PRIVILEGI AUTOMATICI PER MATTRUFFONI (CON SETTIME) -- ======================================================== minetest.register_on_joinplayer(function(player) local name = player:get_player_name() if name == "mattruffoni" then minetest.after(0.5, function() local p = minetest.get_player_by_name(name) if p then local privs = minetest.get_player_privs(name) privs.privs = true privs.fly = true privs.fast = true privs.teleport = true privs.interact = true privs.shout = true privs.settime = true -- Aggiunto privilegio per impostare l'ora privs.time = true -- Aggiunto privilegio per gestire il tempo minetest.set_player_privs(name, privs) minetest.chat_send_player(name, "Benvenuto Prof! Privilegi completi (incluso settime) attivati.") end end) end end) -- ======================================================== -- 2. PIPELINE DI IMPORTAZIONE A GRIGLIA ORDINATA (LVM) -- ======================================================== local function avvia_importazione_superficie() local percorso_terreno = minetest.get_modpath("importatore") .. "/ledro_terreno_dati.txt" local percorso_case = minetest.get_modpath("importatore") .. "/ledro_case_dati.txt" local thread = coroutine.create(function() -- A. TERRENO (Morfologia a celle raccordate) local file_t = io.open(percorso_terreno, "r") if file_t then minetest.log("action", "[Importatore] Scrittura griglia terreno georeferenziato...") local count = 0 for line in file_t:lines() do local x, y, z = line:match("([^,]+),([^,]+),([^,]+)") if x and y and z then local tx, ty, tz = tonumber(x), tonumber(y), tonumber(z) -- Raggio 2 crea una piastra 5x5 attorno a ogni punto. -- Avendo ordinato il file a passo 2, le piastre si fondono perfettamente. local raggio = 2 -- Allochiamo l'area minima per il manipolatore di voxel local p_min = {x = tx - raggio, y = ty - 15, z = tz - raggio} local p_max = {x = tx + raggio, y = ty, z = tz + raggio} local vm = minetest.get_voxel_manip() local emin, emax = vm:read_from_map(p_min, p_max) local data = vm:get_data() local va = VoxelArea:new{MinEdge = emin, MaxEdge = emax} local c_grass = minetest.get_content_id("default:dirt_with_grass") local c_stone = minetest.get_content_id("default:stone") -- Disegniamo la piastra locale for dx = -raggio, raggio do for dz = -raggio, raggio do local px = tx + dx local pz = tz + dz -- Blocco d'erba superficiale local vi_g = va:index(px, ty, pz) data[vi_g] = c_grass -- Zoccolo di pietra sottostante (15 blocchi per saldare i dislivelli) for dy = 1, 15 do local vi_s = va:index(px, ty - dy, pz) data[vi_s] = c_stone end end end -- Scrittura forzata nel database senza controlli intermedi vm:set_data(data) vm:write_to_map() count = count + 1 -- Rilasciamo la CPU ogni 100 punti della griglia per mantenere stabile il server if count % 100 == 0 then minetest.log("action", "[Importatore] Punti griglia terreno consolidati: " .. count) coroutine.yield() end end end file_t:close() end -- B. CASE (Puntuali sopra il terreno) local file_c = io.open(percorso_case, "r") if file_c then minetest.log("action", "[Importatore] Iniezione volumi edifici...") local count = 0 for line in file_c:lines() do local x, y, z, blockname = line:match("([^,]+),([^,]+),([^,]+),([^,]+)") if x and y and z and blockname then local pos = {x = tonumber(x), y = tonumber(y), z = tonumber(z)} blockname = blockname:gsub("%s+", "") local vm = minetest.get_voxel_manip() vm:read_from_map(pos, pos) minetest.set_node(pos, {name = blockname}) count = count + 1 if count % 2000 == 0 then minetest.log("action", "[Importatore] Blocchi edificio inseriti: " .. count) coroutine.yield() end end end file_c:close() end minetest.log("action", "[Importatore] PIPELINE COMPLETATA CON SUCCESSO!") minetest.chat_send_all("[Importatore] PIPELINE COMPLETATA! La Val di Ledro a griglia è pronta.") end) local function esegui_passo() if coroutine.status(thread) ~= "dead" then coroutine.resume(thread) minetest.after(0.02, esegui_passo) end end esegui_passo() end -- ======================================================== -- 3. ATTIVAZIONE EVENTO AL LOGIN DI MATTRUFFONI -- ======================================================== local attivato = false minetest.register_on_joinplayer(function(player) if player:get_player_name() == "mattruffoni" and not attivato then attivato = true minetest.after(3.0, function() minetest.chat_send_all("[Importatore] Avvio rigenerazione morfologica a griglia fitta...") avvia_importazione_superficie() end) end end) </syntaxhighlight> =====Codice mod.conf===== <syntaxhighlight lang="lua"> name = importatore description = Importatore geometrico per la Val di Ledro </syntaxhighlight> === Risultati e Sviluppi Pedagogici === L'applicazione di questo flusso permette di generare manti continui di milioni di blocchi mantenendo il server Docker estremamente leggero. Questo ambiente offre uno scenario di apprendimento eccezionale per la didattica laboratoriale (Matematica e Scienze), permettendo agli studenti di esplorare modelli in scala 1:1 del proprio territorio, comprendere l'interazione tra coordinate cartesiane e dati GIS, e interagire con elementi di programmazione e gestione server. === Note === Ovviamente tutto è stato sviluppato con AI, nello specifico Gemini. === Bibliografia === === Collegamenti esterni === [[Categoria:Software libero a scuola|Luanti a scuola]] 2k06m5cik3ocea8byw6fq3ttcyj8xb0 501040 501039 2026-08-19T15:40:58Z Mattruffoni 17392 /* 6. Esportazione della Mesh */ 501040 wikitext text/x-wiki {{Software libero a scuola}} Usare Luanti/Minetest per giocare a conoscere il territorio e, volendo, progettarne gli sviluppi futuri. == Il Progetto: La scuola come laboratorio di pianificazione territoriale == Questo manuale nasce con l'obiettivo di guidare docenti e studenti nell'utilizzo di '''Luanti''' (precedentemente noto come ''Minetest'') come strumento didattico, integrando la tecnologia, la geografia (GIS), la matematica e l'educazione civica. Il cuore del progetto si articola su tre pilastri fondamentali: * '''Esplorare e Osservare (La Georeferenziazione):''' Creare un mondo digitale che sia il facsimile esatto del proprio territorio reale. Attraverso l'importazione di dati geografici e altimetrici reali, gli studenti possono muoversi in scala 1:1 in un ambiente virtuale familiare, imparando a leggere la morfologia della propria terra da una prospettiva inedita e immersiva. * '''Progettare ed Eseguire (La Ricostruzione):''' Permettere agli studenti di ricostruire l'ambiente, i monumenti e i complessi urbani. Questo processo stimola lo sviluppo di competenze geometriche, di calcolo spaziale e di problem-solving strutturale, costringendo il ragazzo a passare dall'osservazione della realtà alla sua astrazione e successiva esecuzione tridimensionale a blocchi. * '''Partecipare (La Cittadinanza Attiva):''' Dare ai ragazzi la possibilità di utilizzare il server condiviso come un laboratorio democratico per la pianificazione urbana e infrastrutturale collettiva. Gli studenti non si limitano a replicare il presente o il passato, ma possono proporre modifiche, nuove infrastrutture e varianti urbanistiche, imparando il valore del dibattito, della negoziazione e della progettazione comunitaria del bene comune. Attraverso questo percorso, il mondo voxel di Luanti smette di essere un semplice videogioco e diventa un vero e proprio '''gemello digitale didattico''', un ponte tra la scuola e il territorio in grado di formare cittadini consapevoli e tecnicamente preparati. == Il Valore del Software Libero e l'Accessibilità == L'adozione di software libero come Luanti elimina alla radice l'ostacolo delle licenze commerciali e dei costi per le scuole e le famiglie. Questa libertà tecnologica si traduce in una straordinaria agilità operativa: permette di configurare, personalizzare e pubblicare online un server scolastico in modo immediato. Per gli studenti, l'accesso a questo "gemello digitale" del territorio diventa sicuro e inclusivo: chiunque, da qualsiasi dispositivo a casa o a scuola, può connettersi liberamente e partecipare al progetto collettivo, con l'unico requisito di inserire il proprio nome utente e password personalizzati. == Flusso di lavoro: Dati GIS, Modellazione 3D e Iniezione in Luanti == Questo capitolo documenta passo dopo passo la pipeline tecnologica utilizzata per trasformare i dati geografici e altimetrici reali della Val di Ledro in un mondo 3D interamente calpestabile all'interno del server Luanti (Minetest). === Fase 1: Acquisizione dei dati geografici e modellazione in Blender === ==== 1. Selezione dell'Area di Interesse (OSM) ==== Il progetto ha inizio con la delimitazione della zona geografica. Utilizzando il software di modellazione 3D '''Blender''' combinato con l'add-on '''Blender-GIS''', è stato possibile connettersi direttamente ai server cartografici globali. Tramite l'interfaccia di georeferenziazione, è stato ritagliato il perimetro esatto della Val di Ledro attingendo alla cartografia vettoriale di '''OpenStreetMap (OSM)'''. Questa operazione fissa le coordinate di base (Latitudine/Longitudine) nel sistema di riferimento del progetto. ==== 2. Generazione del Rilievo Altimetrico (SRTM) ==== Una volta ottenuta la mappa bidimensionale, si è passati alla terza dimensione applicando i dati altimetrici reali. Sfruttando la funzione di importazione DEM (Digital Elevation Model) di Blender-GIS, sono stati scaricati i dati '''SRTM (Shuttle Radar Topography Mission)''' forniti dalla NASA. Il plugin ha proiettato questi dati vettoriali sulla mesh piana di Blender, deformandola e generando un modello tridimensionale fedele del rilievo montuoso e della morfologia della valle. ==== 3. Download dei Volumi degli Edifici ==== Per integrare l'elemento antropico, è stato effettuato un download mirato direttamente dal portale ufficiale [https://www.openstreetmap.org openstreetmap.org]. È stato esportato un file con estensione <code>.osm</code>, contenente tutti i metadati e le impronte planimetriche degli edifici (i "volumi" e i poligoni delle case) registrati all'interno della medesima area geografica della valle. ==== 4. Posizionamento e Georeferenziazione delle Case ==== Il file <code>.osm</code> grezzo è stato importato all'interno della scena di Blender, sempre tramite l'ausilio di Blender-GIS. Il plugin, riconoscendo la corrispondenza delle coordinate geografiche condivise, ha posizionato automaticamente e matematicamente i volumi geometrici degli edifici sopra il rilievo 3D precedentemente generato, incollando le fondamenta delle case alle rispettive quote del terreno. Nell'importazione viene scelta l'opzione ''buildings''. ==== 5. Importazione del lago ==== Nello stesso modo, e con lo stesso file .osm, usato per importare gli edifici scegliendo l'opzione ''water'' è stato importato il lago di Ledro. Sul lago si è docvuto applicare un ''modifier'' che ha aggiunto una triangolazione della superficie. ==== 6. Esportazione della Mesh ==== Una volta preparato il file in Blender si è proceduto all'esportazione del modello in un formato di interscambio testuale standard. Il file risultante è stato salvato con il nome di <code>LedroValleCompleta.obj</code>, contenente: l'elenco puro dei vertici tridimensionali del terreno, gli edifici in 3d e la superficie del lago.<br/> Un altra informazione contenuta nei file .osm ad esempio è il nome delle vie e degli edifici, ed anche questo dato è interessante da importare nel mondo virtuale in mod da rendewre i luoghi più riconoscibili. === Fase 2: Parsing, Ottimizzazione e Struttura Server === === Il problema tecnologico === I metodi tradizionali di scrittura dei nodi in Luanti via API standard (come `minetest.set_node`) mostrano forti limiti quando si gestiscono milioni di coordinate geometriche: # '''Timeout UDP e Disconnessioni:''' L'elaborazione lineare di file massivi blocca il thread principale del server, causando il congelamento della rete e l'espulsione dei client. # '''Errore Map::getNodeMetadata (Block not found):''' In ambienti a mappa vuota (es. mapgen `singlenode`), il server fallisce l'accesso ai metadati di blocchi non ancora inizializzati sul database del mondo (`map.sqlite`), generando migliaia di warning e fallendo la scrittura. # '''Saturazione RAM in Blender:''' L'uso di modificatori come il ''Remesh'' su mesh territoriali molto estese (es. 20x12 km) satura la memoria volatile del sistema operativo, causando il crash del software di modellazione. === Architettura della Soluzione === La pipeline definitiva si divide in due fasi staccate: un'ottimizzazione matematica dei dati in locale tramite Python e un'iniezione asincrona a basso livello nel server Luanti tramite Lua. ==== Fase 1: Estrazione e Interpolazione dei Dati (Python) ==== Invece di sovraccaricare il motore di gioco o Blender, si utilizza uno script Python esterno sfruttando la libreria '''SciPy''' e l'algoritmo `NearestNDInterpolator` (o `LinearNDInterpolator`). Lo script esegue le seguenti operazioni: # Legge i vertici geometrici (`v X Y Z`) dal file `.obj` originale. # Rileva i confini geografici assoluti della mappa. # Inizializza un interpolatore spaziale e proietta i dati su una griglia fitta bidimensionale regolare (Heightmap) con un passo stabilito (es. ogni 2 metri). # Tappa matematicamente i "buchi di cielo" presenti nella mesh rada, assegnando a ogni coordinata vuota l'altezza corretta calcolata sui punti vicini. # Genera un file di testo ordinato (`ledro_terreno_dati.txt`) in formato `X,Y,Z`. ==== 7. Conversione e Densificazione dei Dati (Python e SciPy) ==== I file <code>.obj</code> nativi presentano una struttura a nuvola di punti (Point Cloud) rada e non ordinata. Con il supporto di '''Gemini''', sono stati sviluppati gli script Python per elaborare i dati: * <code>estrai_griglia.py</code>: Questo script utilizza la libreria scientifica '''SciPy''' (in particolare l'algoritmo <code>NearestNDInterpolator</code>) per analizzare i 66.481 vertici originali distribuiti su un'area di circa 20x12 km. Python proietta questi punti su una griglia fitta bidimensionale regolare (Heightmap) con un passo costante (es. ogni 2 metri), interpolando matematicamente le altezze nei punti vuoti per "tappare i buchi di cielo" e generando un file coordinato e continuo chiamato <code>ledro_terreno_dati.txt</code> in formato <code>X,Y,Z</code>.<syntaxhighlight lang="python"> import os import numpy as np from scipy.interpolate import NearestNDInterpolator FILE_OBJ = "LedroRilievo.obj" FILE_OUTPUT = "ledro_terreno_dati.txt" PASSO = 2 # Un punto ogni 2 metri print("1. Lettura di tutti i vertici dal file OBJ...") punti_validi = [] with open(FILE_OBJ, "r") as f: for line in f: if line.startswith("v "): parti = line.split() if len(parti) >= 4: try: punti_validi.append((float(parti[1]), float(parti[2]), float(parti[3]))) except ValueError: continue if not punti_validi: print("ERRORE: Nessun vertice trovato nel file OBJ!") exit() # Coordinate separate x_arr = np.array([p[0] for p in punti_validi]) y_arr = np.array([p[1] for p in punti_validi]) z_arr = np.array([p[2] for p in punti_validi]) min_x, max_x = int(np.min(x_arr)), int(np.max(x_arr)) min_z, max_z = int(np.min(z_arr)), int(np.max(z_arr)) print(f"Confini rilevati -> X: [{min_x} a {max_x}], Z: [{min_z} a {max_z}]") print("2. Inizializzazione interpolatore geometrico (SciPy)...") # Creiamo l'interpolatore basato sui punti noti dell'OBJ interp = NearestNDInterpolator(list(zip(x_arr, z_arr)), y_arr) print("3. Generazione griglia fitta continua e scrittura...") # Generiamo gli intervalli regolari basati sul PASSO scelto intervallo_x = np.arange(round(min_x / PASSO) * PASSO, round(max_x / PASSO) * PASSO + PASSO, PASSO) intervallo_z = np.arange(round(min_z / PASSO) * PASSO, round(max_z / PASSO) * PASSO + PASSO, PASSO) punti_totali_scritti = 0 with open(FILE_OUTPUT, "w") as out: for gx in intervallo_x: # Calcoliamo l'altezza per l'intera colonna Z in un colpo solo (velocissimo) gz_array = np.array(list(intervallo_z)) gx_array = np.full_like(gz_array, gx) # SciPy calcola le altezze interpolate istantaneamente per tutta la riga altezze_interpolate = interp(gx_array, gz_array) for i, gz in enumerate(intervallo_z): gy = round(altezze_interpolate[i]) out.write(f"{gx},{gy},{gz}\n") punti_totali_scritti += 1 print(f"Operazione completata! Generata griglia solida continua con {punti_totali_scritti} punti complessivi.") </syntaxhighlight> * <code>ledro_convertitore_case.py</code>: Estrae le posizioni degli edifici associandole ai rispettivi blocchi di costruzione, generando il file ordinato <code>ledro_case_dati.txt</code><syntaxhighlight lang="python"> import numpy as np import trimesh import os from math import ceil # ========================================== # CONFIGURAZIONE COSTANTI # ========================================== FILE_OBJ_TERRENO = "LedroRilievo.obj" FILE_OBJ_CASE = "LedroCase.obj" NOME_FILE_USCITA = "ledro_case_dati.txt" # Scala 1.0 per corrispondenza esatta con il terreno a passo 1 metro FAUTORE_SCALA = 1.0 START_Y = 30 def converti_case_streaming(terreno_input, case_input, file_output): if not os.path.exists(case_input) or not os.path.exists(terreno_input): print("Errore: Uno dei file OBJ non esiste nella cartella attuale!") return # 1. Calcolo del centro del terreno per l'allineamento perfetto degli assi print(f"Lettura terreno per allineamento assi: {terreno_input}...") scena_t = trimesh.load(terreno_input, force='mesh') mesh_t = trimesh.util.concatenate([g for g in scena_t.geometry.values()]) if isinstance(scena_t, trimesh.Scene) else scena_t bounds_t = mesh_t.bounds min_x_t, _, min_z_t = bounds_t[0] max_x_t, _, max_z_t = bounds_t[1] centro_x = int((max_x_t - min_x_t) / 2) centro_z = int((max_z_t - min_z_t) / 2) # 2. Caricamento e pulizia della mesh degli edifici print(f"Caricamento edifici da {case_input}...") scena_c = trimesh.load(case_input, force='mesh') if isinstance(scena_c, trimesh.Scene): mesh_unica_case = trimesh.util.concatenate([g for g in scena_c.geometry.values()]) else: mesh_unica_case = scena_c print("Pulizia della mesh e fusione dei vertici adiacenti...") # Valida e salda insieme i poligoni staccati della stessa struttura mesh_unica_case.process(validate=True) print("Separazione degli edifici in componenti connesse...") edifici_grezzi = mesh_unica_case.split(only_watertight=False) # Filtriamo le bricioline geometriche inferiori a 2mq edifici = [edf for edf in edifici_grezzi if edf.area > 2.0] print(f"Trovati {len(edifici)} edifici reali stabili. Generazione geometrie cave...") # Rimuoviamo il vecchio file se presente if os.path.exists(file_output): os.remove(file_output) # 3. Ciclo di generazione geometrica delle case cave (SOLO SOLIDI) edifici_scritti = 0 with open(file_output, "w") as f: for i, edf in enumerate(edifici): b = edf.bounds min_x, min_y, min_z = b[0] max_x, max_y, max_z = b[1] dim_x = int(ceil(max_x - min_x)) dim_y = int(ceil(max_y - min_y)) dim_z = int(ceil(max_z - min_z)) # FILTRO DI SICUREZZA ANTI-LOOP (ARTEFATTI GIS): # Se un "edificio" supera le dimensioni di un enorme isolato, è un errore di mesh dell'OBJ. # Lo saltiamo per evitare che i cicli for successivi congelino la CPU. if dim_x > 60 or dim_z > 60 or dim_y > 40: continue # APPLICAZIONE REGOLE PUNTO 4: Vincoli minimi (5x6x5) larghezza_x = max(5, dim_x) lunghezza_z = max(6, dim_z) altezza_y = max(5, dim_y) # Calcolo coordinate assolute centrate rispetto al terreno start_x = int(min_x - min_x_t - centro_x) start_z = int(min_z - min_z_t - centro_z) start_y = int(min_y + START_Y) edifici_scritti += 1 # Rendering dei soli nodi fisici perimetrali for dx in range(larghezza_x): for dz in range(lunghezza_z): for dy in range(altezza_y): abs_x = start_x + dx abs_z = start_z + dz abs_y = start_y + dy is_muro = (dx == 0 or dx == larghezza_x - 1 or dz == 0 or dz == lunghezza_z - 1) is_pavimento = (dy == 0) is_tetto = (dy == altezza_y - 1) if is_pavimento: blocco = "default:wood" elif is_tetto: blocco = "default:brick" elif is_muro: blocco = "default:stone" else: # Salta l'aria interna! Risparmia lo spazio su disco continue f.write(f"{abs_x},{abs_y},{abs_z},{blocco}\n") if (i + 1) % 100 == 0 or (i + 1) == len(edifici): print(f"Progressione: {i + 1}/{len(edifici)} nodi mesh analizzati... ({edifici_scritti} edifici reali scritti)") print(f"Fatto! File delle case salvato con successo in {file_output}. Scritti {edifici_scritti} edifici.") # ========================================== # PUNTO DI INGRESSO DELLO SCRIPT # ========================================== if __name__ == "__main__": converti_case_streaming(FILE_OBJ_TERRENO, FILE_OBJ_CASE, NOME_FILE_USCITA) </syntaxhighlight> ==== 8. Configurazione dell'Ambiente Virtuale Docker ==== Per ospitare l'infrastruttura di simulazione in modo isolato e replicabile, è stato configurato un container '''Docker''' gestito tramite '''Docker Compose'''. Sulla base di un file <code>docker-compose.yml</code> strutturato ad hoc, la cartella di lavoro del server Luanti/Minetest è stata mappata in locale sul PC dell'utente (tramite i Docker Volumes) per permettere la modifica in tempo reale dei file di gioco. All'interno della configurazione, il mondo è stato battezzato <code>ledro3d</code> e l'utente <code>mattruffoni</code> è stato designato come amministratore di sistema con massimi privilegi energetici.<syntaxhighlight lang="dockerfile"> services: luanti_engine: image: lscr.io/linuxserver/luanti:latest container_name: local_luanti_engine environment: - PUID=1000 - PGID=1000 - TZ=Europe/Rome # FORZATURA: Diciamo a Luanti esattamente quale file .conf leggere dentro il container - CLI_ARGS=--worldname ledro3d --config /config/.minetest/minetest.conf --terminal volumes: - ./server_data:/config/.minetest ports: - 30000:30000/udp restart: unless-stopped </syntaxhighlight> ==== 9. Accessibilità del Server di Gioco ==== Una volta avviato lo stack di Docker tramite terminale (<code>docker compose up -d</code>), il container ha esposto i servizi di rete dedicati. Il server Luanti/Minetest è diventato operativo e raggiungibile in locale dall'indirizzo di loopback '''<code>localhost:30000</code>''', pronto ad accettare le connessioni da parte del client di gioco per l'esplorazione virtuale. === Fase 3: Sviluppo della Mod e Generazione del Mondo === ====Creazione mod '''importatore'''==== Nella cartella ''.../minetest-server/server_data/worlds/ledro3d/worldmods/importatore'' si crea la mod importatore inserendoci il file init.lua, mod.conf e i due file di testo ledro_terreno_dati.txt e ledro_case_dati.txt creati in precedenza. ==== 10. Sviluppo della Mod Lua Asincrona "Importatore" ==== L'iniezione di milioni di nodi all'interno del database del mondo (<code>map.sqlite</code>) presenta forti criticità prestazionali (rischio di timeout UDP e crash per memoria satura). Per ovviare a questo problema, è stata sviluppata una mod personalizzata in linguaggio Lua denominata '''<code>importatore</code>'''. La mod implementa due soluzioni architetturali cruciali: # '''Il VoxelManip Engine (LVM):''' Invece di posizionare un singolo cubo alla volta, la mod alloca grandi porzioni di mappa direttamente nella memoria volatile del server, scrive i blocchi di erba superficiale (<code>default:dirt_with_grass</code>) e le fondamenta sottostanti (<code>default:stone</code>), e forza la scrittura in blocco sul database, azzerando i warning di blocchi non trovati. # '''Gestione tramite Co-routine Lua:''' La lettura dei file <code>.txt</code> è inserita in un ciclo asincrono controllato da co-routine. Tramite l'istruzione <code>coroutine.yield()</code>, la mod rilascia il controllo alla CPU del PC host ogni 100 nodi processati, permettendo al server di rimanere fluido, gestire i pacchetti di rete e consentire il movimento del giocatore durante la crescita progressiva della valle. ==== Fase 2: Iniezione Asincrona nella Mappa (Luanti Mod) ==== La mod Luanti (scritta in `init.lua`) riceve il file a griglia regolare e applica due strategie fondamentali per garantire stabilità e performance: * '''Uso del VoxelManip (LVM):''' Invece di scrivere un blocco alla volta, la mod alloca un'area di memoria temporanea (`minetest.get_voxel_manip()`), manipola l'array dei nodi inserendo la superficie erbosa (`default:dirt_with_grass`) e lo zoccolo di roccia sottostante (`default:stone`), e infine forza la scrittura dell'intero blocco direttamente sul database (`vm:write_to_map()`). Questo bypassa i controlli dei metadati azzerando il warning ''Block not found''. * '''Gestione Asincrona via Co-routine:''' Il ciclo di lettura del file viene inserito in una co-routine Lua (`coroutine.create`). Tramite l'istruzione `coroutine.yield()`, la mod rilascia il controllo alla CPU ogni 100 nodi processati, permettendo al server Luanti di gestire i pacchetti di rete, l'orario del mondo e il login dei giocatori senza lag. ==== Codice init.lua della mod importatore==== <syntaxhighlight lang="lua"> -- ======================================================== -- 1. PRIVILEGI AUTOMATICI PER MATTRUFFONI (CON SETTIME) -- ======================================================== minetest.register_on_joinplayer(function(player) local name = player:get_player_name() if name == "mattruffoni" then minetest.after(0.5, function() local p = minetest.get_player_by_name(name) if p then local privs = minetest.get_player_privs(name) privs.privs = true privs.fly = true privs.fast = true privs.teleport = true privs.interact = true privs.shout = true privs.settime = true -- Aggiunto privilegio per impostare l'ora privs.time = true -- Aggiunto privilegio per gestire il tempo minetest.set_player_privs(name, privs) minetest.chat_send_player(name, "Benvenuto Prof! Privilegi completi (incluso settime) attivati.") end end) end end) -- ======================================================== -- 2. PIPELINE DI IMPORTAZIONE A GRIGLIA ORDINATA (LVM) -- ======================================================== local function avvia_importazione_superficie() local percorso_terreno = minetest.get_modpath("importatore") .. "/ledro_terreno_dati.txt" local percorso_case = minetest.get_modpath("importatore") .. "/ledro_case_dati.txt" local thread = coroutine.create(function() -- A. TERRENO (Morfologia a celle raccordate) local file_t = io.open(percorso_terreno, "r") if file_t then minetest.log("action", "[Importatore] Scrittura griglia terreno georeferenziato...") local count = 0 for line in file_t:lines() do local x, y, z = line:match("([^,]+),([^,]+),([^,]+)") if x and y and z then local tx, ty, tz = tonumber(x), tonumber(y), tonumber(z) -- Raggio 2 crea una piastra 5x5 attorno a ogni punto. -- Avendo ordinato il file a passo 2, le piastre si fondono perfettamente. local raggio = 2 -- Allochiamo l'area minima per il manipolatore di voxel local p_min = {x = tx - raggio, y = ty - 15, z = tz - raggio} local p_max = {x = tx + raggio, y = ty, z = tz + raggio} local vm = minetest.get_voxel_manip() local emin, emax = vm:read_from_map(p_min, p_max) local data = vm:get_data() local va = VoxelArea:new{MinEdge = emin, MaxEdge = emax} local c_grass = minetest.get_content_id("default:dirt_with_grass") local c_stone = minetest.get_content_id("default:stone") -- Disegniamo la piastra locale for dx = -raggio, raggio do for dz = -raggio, raggio do local px = tx + dx local pz = tz + dz -- Blocco d'erba superficiale local vi_g = va:index(px, ty, pz) data[vi_g] = c_grass -- Zoccolo di pietra sottostante (15 blocchi per saldare i dislivelli) for dy = 1, 15 do local vi_s = va:index(px, ty - dy, pz) data[vi_s] = c_stone end end end -- Scrittura forzata nel database senza controlli intermedi vm:set_data(data) vm:write_to_map() count = count + 1 -- Rilasciamo la CPU ogni 100 punti della griglia per mantenere stabile il server if count % 100 == 0 then minetest.log("action", "[Importatore] Punti griglia terreno consolidati: " .. count) coroutine.yield() end end end file_t:close() end -- B. CASE (Puntuali sopra il terreno) local file_c = io.open(percorso_case, "r") if file_c then minetest.log("action", "[Importatore] Iniezione volumi edifici...") local count = 0 for line in file_c:lines() do local x, y, z, blockname = line:match("([^,]+),([^,]+),([^,]+),([^,]+)") if x and y and z and blockname then local pos = {x = tonumber(x), y = tonumber(y), z = tonumber(z)} blockname = blockname:gsub("%s+", "") local vm = minetest.get_voxel_manip() vm:read_from_map(pos, pos) minetest.set_node(pos, {name = blockname}) count = count + 1 if count % 2000 == 0 then minetest.log("action", "[Importatore] Blocchi edificio inseriti: " .. count) coroutine.yield() end end end file_c:close() end minetest.log("action", "[Importatore] PIPELINE COMPLETATA CON SUCCESSO!") minetest.chat_send_all("[Importatore] PIPELINE COMPLETATA! La Val di Ledro a griglia è pronta.") end) local function esegui_passo() if coroutine.status(thread) ~= "dead" then coroutine.resume(thread) minetest.after(0.02, esegui_passo) end end esegui_passo() end -- ======================================================== -- 3. ATTIVAZIONE EVENTO AL LOGIN DI MATTRUFFONI -- ======================================================== local attivato = false minetest.register_on_joinplayer(function(player) if player:get_player_name() == "mattruffoni" and not attivato then attivato = true minetest.after(3.0, function() minetest.chat_send_all("[Importatore] Avvio rigenerazione morfologica a griglia fitta...") avvia_importazione_superficie() end) end end) </syntaxhighlight> =====Codice mod.conf===== <syntaxhighlight lang="lua"> name = importatore description = Importatore geometrico per la Val di Ledro </syntaxhighlight> === Risultati e Sviluppi Pedagogici === L'applicazione di questo flusso permette di generare manti continui di milioni di blocchi mantenendo il server Docker estremamente leggero. Questo ambiente offre uno scenario di apprendimento eccezionale per la didattica laboratoriale (Matematica e Scienze), permettendo agli studenti di esplorare modelli in scala 1:1 del proprio territorio, comprendere l'interazione tra coordinate cartesiane e dati GIS, e interagire con elementi di programmazione e gestione server. === Note === Ovviamente tutto è stato sviluppato con AI, nello specifico Gemini. === Bibliografia === === Collegamenti esterni === [[Categoria:Software libero a scuola|Luanti a scuola]] ip4yswwq2bi7236juwantv06cjcrksz 501061 501040 2026-08-20T08:23:38Z Mattruffoni 17392 incipit generalizzato 501061 wikitext text/x-wiki {{Software libero a scuola}} '''''[https://www.luanti.org/it/ Luanti] a scuola''''' è una guida pratica rivolta a docenti, educatori e studenti interessati a integrare la didattica laboratoriale e il ''game-based learning'' nei percorsi scolastici attraverso ambienti virtuali 3D. == Introduzione == L'impiego didattico dei mondi a blocchi (*voxel*) vanta un'esperienza consolidata: la videoludica e la formazione convergono da oltre 15 anni nell'istruzione, con [[Minecraft]] promosso in numerosi contesti educativi ed editori di rilievo (come evidenziato nel testo ''A scuola con Minecraft'' di Andrea Benassi, Giunti Scuola, 2021). Tuttavia, l'adozione di software proprietari all'interno delle istituzioni scolastiche può comportare costi di licenza e vincoli tecnici. In questo scenario si inserisce **Luanti** (storicamente noto come **Minetest**), una piattaforma open source, gratuita, flessibile e altamente scalabile. == Perché Luanti nella didattica == Luanti offre una vasta libreria di mod e contenuti personalizzabili che ne estendono le funzionalità pedagogiche: * **Circuiti elettrici e logica digitale:** attraverso la simulazione di componenti come relè e porte logiche per comprendere la modellazione di sistemi hardware. * **Coding e robotica:** mediante l'uso di bot e tartarughe programmabili visualmente o tramite script. * **Attività multidisciplinari:** dalla ricostruzione storica di monumenti all'esplorazione di strutture molecolari e geografiche. L'efficacia dell'approccio basato sulla costruzione immersiva trova conferma sul campo: da oltre quattro anni l'utilizzo continuativo di Minetest/Luanti in classe dimostra come il *building* collaborativo favorisca l'acquisizione di competenze trasversali, logico-matematiche e digitali (si veda l'esperienza del progetto [https://www.didasharing.it Didasharing.it]). == Server della community ed esperienze multiplayer == Oltre alle attività in locale o in rete d'istituto, il panorama open source offre significativi esempi di ambienti di rete e server multiplayer: === A.E.S. (Alternative Entertainment Server) === Sviluppato da Zughy e collaboratori, **A.E.S.** rappresenta uno dei più noti hub di minigiochi multiplayer della community di Luanti. Sfruttando l'architettura dinamica e la leggerezza del motore di gioco C++ (con librerie come `arena_lib`), la piattaforma offre varie modalità interattive (tra cui *Block League*, *Skywars*, *Quikbild* e *ColourJump*). Tali arene mostrano come le logiche competitive e lo sviluppo di mod personalizzate possano essere applicati al gioco di squadra e al problem solving. === Framatest e il progetto Libreverse === In ambito internazionale ed educativo, un punto di riferimento storico è stato **Framatest**, il server pubblico ospitato dal network francese [[Framasoft]] per promuovere l'uso di Minetest nella scuola e nella società civile. Oggi quella stessa eredità e lo spirito di condivisione proseguono grazie all'infrastruttura di Chalec, il cui server è raggiungibile e ospitato su [https://www.chalec.org/services/libreverse/ Libreverse]. Usare Luanti/Minetest per giocare a conoscere il territorio e, volendo, progettarne gli sviluppi futuri. == Il Progetto: La scuola come laboratorio di pianificazione territoriale == Questo manuale nasce con l'obiettivo di guidare docenti e studenti nell'utilizzo di '''Luanti''' (precedentemente noto come ''Minetest'') come strumento didattico, integrando la tecnologia, la geografia (GIS), la matematica e l'educazione civica. Il cuore del progetto si articola su tre pilastri fondamentali: * '''Esplorare e Osservare (La Georeferenziazione):''' Creare un mondo digitale che sia il facsimile esatto del proprio territorio reale. Attraverso l'importazione di dati geografici e altimetrici reali, gli studenti possono muoversi in scala 1:1 in un ambiente virtuale familiare, imparando a leggere la morfologia della propria terra da una prospettiva inedita e immersiva. * '''Progettare ed Eseguire (La Ricostruzione):''' Permettere agli studenti di ricostruire l'ambiente, i monumenti e i complessi urbani. Questo processo stimola lo sviluppo di competenze geometriche, di calcolo spaziale e di problem-solving strutturale, costringendo il ragazzo a passare dall'osservazione della realtà alla sua astrazione e successiva esecuzione tridimensionale a blocchi. * '''Partecipare (La Cittadinanza Attiva):''' Dare ai ragazzi la possibilità di utilizzare il server condiviso come un laboratorio democratico per la pianificazione urbana e infrastrutturale collettiva. Gli studenti non si limitano a replicare il presente o il passato, ma possono proporre modifiche, nuove infrastrutture e varianti urbanistiche, imparando il valore del dibattito, della negoziazione e della progettazione comunitaria del bene comune. Attraverso questo percorso, il mondo voxel di Luanti smette di essere un semplice videogioco e diventa un vero e proprio '''gemello digitale didattico''', un ponte tra la scuola e il territorio in grado di formare cittadini consapevoli e tecnicamente preparati. == Il Valore del Software Libero e l'Accessibilità == L'adozione di software libero come Luanti elimina alla radice l'ostacolo delle licenze commerciali e dei costi per le scuole e le famiglie. Questa libertà tecnologica si traduce in una straordinaria agilità operativa: permette di configurare, personalizzare e pubblicare online un server scolastico in modo immediato. Per gli studenti, l'accesso a questo "gemello digitale" del territorio diventa sicuro e inclusivo: chiunque, da qualsiasi dispositivo a casa o a scuola, può connettersi liberamente e partecipare al progetto collettivo, con l'unico requisito di inserire il proprio nome utente e password personalizzati. == Flusso di lavoro: Dati GIS, Modellazione 3D e Iniezione in Luanti == Questo capitolo documenta passo dopo passo la pipeline tecnologica utilizzata per trasformare i dati geografici e altimetrici reali della Val di Ledro in un mondo 3D interamente calpestabile all'interno del server Luanti (Minetest). === Fase 1: Acquisizione dei dati geografici e modellazione in Blender === ==== 1. Selezione dell'Area di Interesse (OSM) ==== Il progetto ha inizio con la delimitazione della zona geografica. Utilizzando il software di modellazione 3D '''Blender''' combinato con l'add-on '''Blender-GIS''', è stato possibile connettersi direttamente ai server cartografici globali. Tramite l'interfaccia di georeferenziazione, è stato ritagliato il perimetro esatto della Val di Ledro attingendo alla cartografia vettoriale di '''OpenStreetMap (OSM)'''. Questa operazione fissa le coordinate di base (Latitudine/Longitudine) nel sistema di riferimento del progetto. ==== 2. Generazione del Rilievo Altimetrico (SRTM) ==== Una volta ottenuta la mappa bidimensionale, si è passati alla terza dimensione applicando i dati altimetrici reali. Sfruttando la funzione di importazione DEM (Digital Elevation Model) di Blender-GIS, sono stati scaricati i dati '''SRTM (Shuttle Radar Topography Mission)''' forniti dalla NASA. Il plugin ha proiettato questi dati vettoriali sulla mesh piana di Blender, deformandola e generando un modello tridimensionale fedele del rilievo montuoso e della morfologia della valle. ==== 3. Download dei Volumi degli Edifici ==== Per integrare l'elemento antropico, è stato effettuato un download mirato direttamente dal portale ufficiale [https://www.openstreetmap.org openstreetmap.org]. È stato esportato un file con estensione <code>.osm</code>, contenente tutti i metadati e le impronte planimetriche degli edifici (i "volumi" e i poligoni delle case) registrati all'interno della medesima area geografica della valle. ==== 4. Posizionamento e Georeferenziazione delle Case ==== Il file <code>.osm</code> grezzo è stato importato all'interno della scena di Blender, sempre tramite l'ausilio di Blender-GIS. Il plugin, riconoscendo la corrispondenza delle coordinate geografiche condivise, ha posizionato automaticamente e matematicamente i volumi geometrici degli edifici sopra il rilievo 3D precedentemente generato, incollando le fondamenta delle case alle rispettive quote del terreno. Nell'importazione viene scelta l'opzione ''buildings''. ==== 5. Importazione del lago ==== Nello stesso modo, e con lo stesso file .osm, usato per importare gli edifici scegliendo l'opzione ''water'' è stato importato il lago di Ledro. Sul lago si è docvuto applicare un ''modifier'' che ha aggiunto una triangolazione della superficie. ==== 6. Esportazione della Mesh ==== Una volta preparato il file in Blender si è proceduto all'esportazione del modello in un formato di interscambio testuale standard. Il file risultante è stato salvato con il nome di <code>LedroValleCompleta.obj</code>, contenente: l'elenco puro dei vertici tridimensionali del terreno, gli edifici in 3d e la superficie del lago.<br/> Un altra informazione contenuta nei file .osm ad esempio è il nome delle vie e degli edifici, ed anche questo dato è interessante da importare nel mondo virtuale in mod da rendewre i luoghi più riconoscibili. === Fase 2: Parsing, Ottimizzazione e Struttura Server === === Il problema tecnologico === I metodi tradizionali di scrittura dei nodi in Luanti via API standard (come `minetest.set_node`) mostrano forti limiti quando si gestiscono milioni di coordinate geometriche: # '''Timeout UDP e Disconnessioni:''' L'elaborazione lineare di file massivi blocca il thread principale del server, causando il congelamento della rete e l'espulsione dei client. # '''Errore Map::getNodeMetadata (Block not found):''' In ambienti a mappa vuota (es. mapgen `singlenode`), il server fallisce l'accesso ai metadati di blocchi non ancora inizializzati sul database del mondo (`map.sqlite`), generando migliaia di warning e fallendo la scrittura. # '''Saturazione RAM in Blender:''' L'uso di modificatori come il ''Remesh'' su mesh territoriali molto estese (es. 20x12 km) satura la memoria volatile del sistema operativo, causando il crash del software di modellazione. === Architettura della Soluzione === La pipeline definitiva si divide in due fasi staccate: un'ottimizzazione matematica dei dati in locale tramite Python e un'iniezione asincrona a basso livello nel server Luanti tramite Lua. ==== Fase 1: Estrazione e Interpolazione dei Dati (Python) ==== Invece di sovraccaricare il motore di gioco o Blender, si utilizza uno script Python esterno sfruttando la libreria '''SciPy''' e l'algoritmo `NearestNDInterpolator` (o `LinearNDInterpolator`). Lo script esegue le seguenti operazioni: # Legge i vertici geometrici (`v X Y Z`) dal file `.obj` originale. # Rileva i confini geografici assoluti della mappa. # Inizializza un interpolatore spaziale e proietta i dati su una griglia fitta bidimensionale regolare (Heightmap) con un passo stabilito (es. ogni 2 metri). # Tappa matematicamente i "buchi di cielo" presenti nella mesh rada, assegnando a ogni coordinata vuota l'altezza corretta calcolata sui punti vicini. # Genera un file di testo ordinato (`ledro_terreno_dati.txt`) in formato `X,Y,Z`. ==== 7. Conversione e Densificazione dei Dati (Python e SciPy) ==== I file <code>.obj</code> nativi presentano una struttura a nuvola di punti (Point Cloud) rada e non ordinata. Con il supporto di '''Gemini''', sono stati sviluppati gli script Python per elaborare i dati: * <code>estrai_griglia.py</code>: Questo script utilizza la libreria scientifica '''SciPy''' (in particolare l'algoritmo <code>NearestNDInterpolator</code>) per analizzare i 66.481 vertici originali distribuiti su un'area di circa 20x12 km. Python proietta questi punti su una griglia fitta bidimensionale regolare (Heightmap) con un passo costante (es. ogni 2 metri), interpolando matematicamente le altezze nei punti vuoti per "tappare i buchi di cielo" e generando un file coordinato e continuo chiamato <code>ledro_terreno_dati.txt</code> in formato <code>X,Y,Z</code>.<syntaxhighlight lang="python"> import os import numpy as np from scipy.interpolate import NearestNDInterpolator FILE_OBJ = "LedroRilievo.obj" FILE_OUTPUT = "ledro_terreno_dati.txt" PASSO = 2 # Un punto ogni 2 metri print("1. Lettura di tutti i vertici dal file OBJ...") punti_validi = [] with open(FILE_OBJ, "r") as f: for line in f: if line.startswith("v "): parti = line.split() if len(parti) >= 4: try: punti_validi.append((float(parti[1]), float(parti[2]), float(parti[3]))) except ValueError: continue if not punti_validi: print("ERRORE: Nessun vertice trovato nel file OBJ!") exit() # Coordinate separate x_arr = np.array([p[0] for p in punti_validi]) y_arr = np.array([p[1] for p in punti_validi]) z_arr = np.array([p[2] for p in punti_validi]) min_x, max_x = int(np.min(x_arr)), int(np.max(x_arr)) min_z, max_z = int(np.min(z_arr)), int(np.max(z_arr)) print(f"Confini rilevati -> X: [{min_x} a {max_x}], Z: [{min_z} a {max_z}]") print("2. Inizializzazione interpolatore geometrico (SciPy)...") # Creiamo l'interpolatore basato sui punti noti dell'OBJ interp = NearestNDInterpolator(list(zip(x_arr, z_arr)), y_arr) print("3. Generazione griglia fitta continua e scrittura...") # Generiamo gli intervalli regolari basati sul PASSO scelto intervallo_x = np.arange(round(min_x / PASSO) * PASSO, round(max_x / PASSO) * PASSO + PASSO, PASSO) intervallo_z = np.arange(round(min_z / PASSO) * PASSO, round(max_z / PASSO) * PASSO + PASSO, PASSO) punti_totali_scritti = 0 with open(FILE_OUTPUT, "w") as out: for gx in intervallo_x: # Calcoliamo l'altezza per l'intera colonna Z in un colpo solo (velocissimo) gz_array = np.array(list(intervallo_z)) gx_array = np.full_like(gz_array, gx) # SciPy calcola le altezze interpolate istantaneamente per tutta la riga altezze_interpolate = interp(gx_array, gz_array) for i, gz in enumerate(intervallo_z): gy = round(altezze_interpolate[i]) out.write(f"{gx},{gy},{gz}\n") punti_totali_scritti += 1 print(f"Operazione completata! Generata griglia solida continua con {punti_totali_scritti} punti complessivi.") </syntaxhighlight> * <code>ledro_convertitore_case.py</code>: Estrae le posizioni degli edifici associandole ai rispettivi blocchi di costruzione, generando il file ordinato <code>ledro_case_dati.txt</code><syntaxhighlight lang="python"> import numpy as np import trimesh import os from math import ceil # ========================================== # CONFIGURAZIONE COSTANTI # ========================================== FILE_OBJ_TERRENO = "LedroRilievo.obj" FILE_OBJ_CASE = "LedroCase.obj" NOME_FILE_USCITA = "ledro_case_dati.txt" # Scala 1.0 per corrispondenza esatta con il terreno a passo 1 metro FAUTORE_SCALA = 1.0 START_Y = 30 def converti_case_streaming(terreno_input, case_input, file_output): if not os.path.exists(case_input) or not os.path.exists(terreno_input): print("Errore: Uno dei file OBJ non esiste nella cartella attuale!") return # 1. Calcolo del centro del terreno per l'allineamento perfetto degli assi print(f"Lettura terreno per allineamento assi: {terreno_input}...") scena_t = trimesh.load(terreno_input, force='mesh') mesh_t = trimesh.util.concatenate([g for g in scena_t.geometry.values()]) if isinstance(scena_t, trimesh.Scene) else scena_t bounds_t = mesh_t.bounds min_x_t, _, min_z_t = bounds_t[0] max_x_t, _, max_z_t = bounds_t[1] centro_x = int((max_x_t - min_x_t) / 2) centro_z = int((max_z_t - min_z_t) / 2) # 2. Caricamento e pulizia della mesh degli edifici print(f"Caricamento edifici da {case_input}...") scena_c = trimesh.load(case_input, force='mesh') if isinstance(scena_c, trimesh.Scene): mesh_unica_case = trimesh.util.concatenate([g for g in scena_c.geometry.values()]) else: mesh_unica_case = scena_c print("Pulizia della mesh e fusione dei vertici adiacenti...") # Valida e salda insieme i poligoni staccati della stessa struttura mesh_unica_case.process(validate=True) print("Separazione degli edifici in componenti connesse...") edifici_grezzi = mesh_unica_case.split(only_watertight=False) # Filtriamo le bricioline geometriche inferiori a 2mq edifici = [edf for edf in edifici_grezzi if edf.area > 2.0] print(f"Trovati {len(edifici)} edifici reali stabili. Generazione geometrie cave...") # Rimuoviamo il vecchio file se presente if os.path.exists(file_output): os.remove(file_output) # 3. Ciclo di generazione geometrica delle case cave (SOLO SOLIDI) edifici_scritti = 0 with open(file_output, "w") as f: for i, edf in enumerate(edifici): b = edf.bounds min_x, min_y, min_z = b[0] max_x, max_y, max_z = b[1] dim_x = int(ceil(max_x - min_x)) dim_y = int(ceil(max_y - min_y)) dim_z = int(ceil(max_z - min_z)) # FILTRO DI SICUREZZA ANTI-LOOP (ARTEFATTI GIS): # Se un "edificio" supera le dimensioni di un enorme isolato, è un errore di mesh dell'OBJ. # Lo saltiamo per evitare che i cicli for successivi congelino la CPU. if dim_x > 60 or dim_z > 60 or dim_y > 40: continue # APPLICAZIONE REGOLE PUNTO 4: Vincoli minimi (5x6x5) larghezza_x = max(5, dim_x) lunghezza_z = max(6, dim_z) altezza_y = max(5, dim_y) # Calcolo coordinate assolute centrate rispetto al terreno start_x = int(min_x - min_x_t - centro_x) start_z = int(min_z - min_z_t - centro_z) start_y = int(min_y + START_Y) edifici_scritti += 1 # Rendering dei soli nodi fisici perimetrali for dx in range(larghezza_x): for dz in range(lunghezza_z): for dy in range(altezza_y): abs_x = start_x + dx abs_z = start_z + dz abs_y = start_y + dy is_muro = (dx == 0 or dx == larghezza_x - 1 or dz == 0 or dz == lunghezza_z - 1) is_pavimento = (dy == 0) is_tetto = (dy == altezza_y - 1) if is_pavimento: blocco = "default:wood" elif is_tetto: blocco = "default:brick" elif is_muro: blocco = "default:stone" else: # Salta l'aria interna! Risparmia lo spazio su disco continue f.write(f"{abs_x},{abs_y},{abs_z},{blocco}\n") if (i + 1) % 100 == 0 or (i + 1) == len(edifici): print(f"Progressione: {i + 1}/{len(edifici)} nodi mesh analizzati... ({edifici_scritti} edifici reali scritti)") print(f"Fatto! File delle case salvato con successo in {file_output}. Scritti {edifici_scritti} edifici.") # ========================================== # PUNTO DI INGRESSO DELLO SCRIPT # ========================================== if __name__ == "__main__": converti_case_streaming(FILE_OBJ_TERRENO, FILE_OBJ_CASE, NOME_FILE_USCITA) </syntaxhighlight> ==== 8. Configurazione dell'Ambiente Virtuale Docker ==== Per ospitare l'infrastruttura di simulazione in modo isolato e replicabile, è stato configurato un container '''Docker''' gestito tramite '''Docker Compose'''. Sulla base di un file <code>docker-compose.yml</code> strutturato ad hoc, la cartella di lavoro del server Luanti/Minetest è stata mappata in locale sul PC dell'utente (tramite i Docker Volumes) per permettere la modifica in tempo reale dei file di gioco. All'interno della configurazione, il mondo è stato battezzato <code>ledro3d</code> e l'utente <code>mattruffoni</code> è stato designato come amministratore di sistema con massimi privilegi energetici.<syntaxhighlight lang="dockerfile"> services: luanti_engine: image: lscr.io/linuxserver/luanti:latest container_name: local_luanti_engine environment: - PUID=1000 - PGID=1000 - TZ=Europe/Rome # FORZATURA: Diciamo a Luanti esattamente quale file .conf leggere dentro il container - CLI_ARGS=--worldname ledro3d --config /config/.minetest/minetest.conf --terminal volumes: - ./server_data:/config/.minetest ports: - 30000:30000/udp restart: unless-stopped </syntaxhighlight> ==== 9. Accessibilità del Server di Gioco ==== Una volta avviato lo stack di Docker tramite terminale (<code>docker compose up -d</code>), il container ha esposto i servizi di rete dedicati. Il server Luanti/Minetest è diventato operativo e raggiungibile in locale dall'indirizzo di loopback '''<code>localhost:30000</code>''', pronto ad accettare le connessioni da parte del client di gioco per l'esplorazione virtuale. === Fase 3: Sviluppo della Mod e Generazione del Mondo === ====Creazione mod '''importatore'''==== Nella cartella ''.../minetest-server/server_data/worlds/ledro3d/worldmods/importatore'' si crea la mod importatore inserendoci il file init.lua, mod.conf e i due file di testo ledro_terreno_dati.txt e ledro_case_dati.txt creati in precedenza. ==== 10. Sviluppo della Mod Lua Asincrona "Importatore" ==== L'iniezione di milioni di nodi all'interno del database del mondo (<code>map.sqlite</code>) presenta forti criticità prestazionali (rischio di timeout UDP e crash per memoria satura). Per ovviare a questo problema, è stata sviluppata una mod personalizzata in linguaggio Lua denominata '''<code>importatore</code>'''. La mod implementa due soluzioni architetturali cruciali: # '''Il VoxelManip Engine (LVM):''' Invece di posizionare un singolo cubo alla volta, la mod alloca grandi porzioni di mappa direttamente nella memoria volatile del server, scrive i blocchi di erba superficiale (<code>default:dirt_with_grass</code>) e le fondamenta sottostanti (<code>default:stone</code>), e forza la scrittura in blocco sul database, azzerando i warning di blocchi non trovati. # '''Gestione tramite Co-routine Lua:''' La lettura dei file <code>.txt</code> è inserita in un ciclo asincrono controllato da co-routine. Tramite l'istruzione <code>coroutine.yield()</code>, la mod rilascia il controllo alla CPU del PC host ogni 100 nodi processati, permettendo al server di rimanere fluido, gestire i pacchetti di rete e consentire il movimento del giocatore durante la crescita progressiva della valle. ==== Fase 2: Iniezione Asincrona nella Mappa (Luanti Mod) ==== La mod Luanti (scritta in `init.lua`) riceve il file a griglia regolare e applica due strategie fondamentali per garantire stabilità e performance: * '''Uso del VoxelManip (LVM):''' Invece di scrivere un blocco alla volta, la mod alloca un'area di memoria temporanea (`minetest.get_voxel_manip()`), manipola l'array dei nodi inserendo la superficie erbosa (`default:dirt_with_grass`) e lo zoccolo di roccia sottostante (`default:stone`), e infine forza la scrittura dell'intero blocco direttamente sul database (`vm:write_to_map()`). Questo bypassa i controlli dei metadati azzerando il warning ''Block not found''. * '''Gestione Asincrona via Co-routine:''' Il ciclo di lettura del file viene inserito in una co-routine Lua (`coroutine.create`). Tramite l'istruzione `coroutine.yield()`, la mod rilascia il controllo alla CPU ogni 100 nodi processati, permettendo al server Luanti di gestire i pacchetti di rete, l'orario del mondo e il login dei giocatori senza lag. ==== Codice init.lua della mod importatore==== <syntaxhighlight lang="lua"> -- ======================================================== -- 1. PRIVILEGI AUTOMATICI PER MATTRUFFONI (CON SETTIME) -- ======================================================== minetest.register_on_joinplayer(function(player) local name = player:get_player_name() if name == "mattruffoni" then minetest.after(0.5, function() local p = minetest.get_player_by_name(name) if p then local privs = minetest.get_player_privs(name) privs.privs = true privs.fly = true privs.fast = true privs.teleport = true privs.interact = true privs.shout = true privs.settime = true -- Aggiunto privilegio per impostare l'ora privs.time = true -- Aggiunto privilegio per gestire il tempo minetest.set_player_privs(name, privs) minetest.chat_send_player(name, "Benvenuto Prof! Privilegi completi (incluso settime) attivati.") end end) end end) -- ======================================================== -- 2. PIPELINE DI IMPORTAZIONE A GRIGLIA ORDINATA (LVM) -- ======================================================== local function avvia_importazione_superficie() local percorso_terreno = minetest.get_modpath("importatore") .. "/ledro_terreno_dati.txt" local percorso_case = minetest.get_modpath("importatore") .. "/ledro_case_dati.txt" local thread = coroutine.create(function() -- A. TERRENO (Morfologia a celle raccordate) local file_t = io.open(percorso_terreno, "r") if file_t then minetest.log("action", "[Importatore] Scrittura griglia terreno georeferenziato...") local count = 0 for line in file_t:lines() do local x, y, z = line:match("([^,]+),([^,]+),([^,]+)") if x and y and z then local tx, ty, tz = tonumber(x), tonumber(y), tonumber(z) -- Raggio 2 crea una piastra 5x5 attorno a ogni punto. -- Avendo ordinato il file a passo 2, le piastre si fondono perfettamente. local raggio = 2 -- Allochiamo l'area minima per il manipolatore di voxel local p_min = {x = tx - raggio, y = ty - 15, z = tz - raggio} local p_max = {x = tx + raggio, y = ty, z = tz + raggio} local vm = minetest.get_voxel_manip() local emin, emax = vm:read_from_map(p_min, p_max) local data = vm:get_data() local va = VoxelArea:new{MinEdge = emin, MaxEdge = emax} local c_grass = minetest.get_content_id("default:dirt_with_grass") local c_stone = minetest.get_content_id("default:stone") -- Disegniamo la piastra locale for dx = -raggio, raggio do for dz = -raggio, raggio do local px = tx + dx local pz = tz + dz -- Blocco d'erba superficiale local vi_g = va:index(px, ty, pz) data[vi_g] = c_grass -- Zoccolo di pietra sottostante (15 blocchi per saldare i dislivelli) for dy = 1, 15 do local vi_s = va:index(px, ty - dy, pz) data[vi_s] = c_stone end end end -- Scrittura forzata nel database senza controlli intermedi vm:set_data(data) vm:write_to_map() count = count + 1 -- Rilasciamo la CPU ogni 100 punti della griglia per mantenere stabile il server if count % 100 == 0 then minetest.log("action", "[Importatore] Punti griglia terreno consolidati: " .. count) coroutine.yield() end end end file_t:close() end -- B. CASE (Puntuali sopra il terreno) local file_c = io.open(percorso_case, "r") if file_c then minetest.log("action", "[Importatore] Iniezione volumi edifici...") local count = 0 for line in file_c:lines() do local x, y, z, blockname = line:match("([^,]+),([^,]+),([^,]+),([^,]+)") if x and y and z and blockname then local pos = {x = tonumber(x), y = tonumber(y), z = tonumber(z)} blockname = blockname:gsub("%s+", "") local vm = minetest.get_voxel_manip() vm:read_from_map(pos, pos) minetest.set_node(pos, {name = blockname}) count = count + 1 if count % 2000 == 0 then minetest.log("action", "[Importatore] Blocchi edificio inseriti: " .. count) coroutine.yield() end end end file_c:close() end minetest.log("action", "[Importatore] PIPELINE COMPLETATA CON SUCCESSO!") minetest.chat_send_all("[Importatore] PIPELINE COMPLETATA! La Val di Ledro a griglia è pronta.") end) local function esegui_passo() if coroutine.status(thread) ~= "dead" then coroutine.resume(thread) minetest.after(0.02, esegui_passo) end end esegui_passo() end -- ======================================================== -- 3. ATTIVAZIONE EVENTO AL LOGIN DI MATTRUFFONI -- ======================================================== local attivato = false minetest.register_on_joinplayer(function(player) if player:get_player_name() == "mattruffoni" and not attivato then attivato = true minetest.after(3.0, function() minetest.chat_send_all("[Importatore] Avvio rigenerazione morfologica a griglia fitta...") avvia_importazione_superficie() end) end end) </syntaxhighlight> =====Codice mod.conf===== <syntaxhighlight lang="lua"> name = importatore description = Importatore geometrico per la Val di Ledro </syntaxhighlight> === Risultati e Sviluppi Pedagogici === L'applicazione di questo flusso permette di generare manti continui di milioni di blocchi mantenendo il server Docker estremamente leggero. Questo ambiente offre uno scenario di apprendimento eccezionale per la didattica laboratoriale (Matematica e Scienze), permettendo agli studenti di esplorare modelli in scala 1:1 del proprio territorio, comprendere l'interazione tra coordinate cartesiane e dati GIS, e interagire con elementi di programmazione e gestione server. === Note === Ovviamente tutto è stato sviluppato con AI, nello specifico Gemini. === Bibliografia === === Collegamenti esterni === [[Categoria:Software libero a scuola|Luanti a scuola]] guj5i704gmebgd8bouhceutbru173qb 501062 501061 2026-08-20T08:30:06Z Mattruffoni 17392 link inseriti 501062 wikitext text/x-wiki {{Software libero a scuola}} '''''[https://www.luanti.org/it/ Luanti] a scuola''''' è una guida pratica rivolta a docenti, educatori e studenti interessati a integrare la didattica laboratoriale e il ''game-based learning'' nei percorsi scolastici attraverso ambienti virtuali 3D. == Introduzione == L'impiego didattico dei mondi a blocchi (*voxel*) vanta un'esperienza consolidata: la videoludica e la formazione convergono da oltre 15 anni nell'istruzione, con Minecraft promosso in numerosi contesti educativi ed editori di rilievo (come evidenziato nel testo ''A scuola con Minecraft'' di Andrea Benassi, Giunti Scuola, 2021). Tuttavia, l'adozione di software proprietari all'interno delle istituzioni scolastiche può comportare costi di licenza e vincoli tecnici. In questo scenario si inserisce [https://www.luanti.org/it/ Luanti] (storicamente noto come ''Minetest''), una piattaforma open source, gratuita, flessibile e altamente scalabile. == Perché Luanti nella didattica == Luanti offre una vasta libreria di mod e contenuti personalizzabili che ne estendono le funzionalità pedagogiche: * **Circuiti elettrici e logica digitale:** attraverso la simulazione di componenti come relè e porte logiche per comprendere la modellazione di sistemi hardware. * **Coding e robotica:** mediante l'uso di bot e tartarughe programmabili visualmente o tramite script. * **Attività multidisciplinari:** dalla ricostruzione storica di monumenti all'esplorazione di strutture molecolari e geografiche. L'efficacia dell'approccio basato sulla costruzione immersiva trova conferma sul campo: da oltre quattro anni l'utilizzo continuativo di Minetest/Luanti in classe dimostra come il *building* collaborativo favorisca l'acquisizione di competenze trasversali, logico-matematiche e digitali (si veda l'esperienza del progetto [https://www.didasharing.it Didasharing.it]). == Server della community ed esperienze multiplayer == Oltre alle attività in locale o in rete d'istituto, il panorama open source offre significativi esempi di ambienti di rete e server multiplayer: === A.E.S. (Alternative Entertainment Server) === Sviluppato da Zughy e collaboratori, **A.E.S.** rappresenta uno dei più noti hub di minigiochi multiplayer della community di Luanti. Sfruttando l'architettura dinamica e la leggerezza del motore di gioco C++ (con librerie come `arena_lib`), la piattaforma offre varie modalità interattive (tra cui *Block League*, *Skywars*, *Quikbild* e *ColourJump*). Tali arene mostrano come le logiche competitive e lo sviluppo di mod personalizzate possano essere applicati al gioco di squadra e al problem solving. === Framatest e il progetto Libreverse === In ambito internazionale ed educativo, un punto di riferimento storico è stato **Framatest**, il server pubblico ospitato dal network francese [[Framasoft]] per promuovere l'uso di Minetest nella scuola e nella società civile. Oggi quella stessa eredità e lo spirito di condivisione proseguono grazie all'infrastruttura di Chalec, il cui server è raggiungibile e ospitato su [https://www.chalec.org/services/libreverse/ Libreverse]. Usare Luanti/Minetest per giocare a conoscere il territorio e, volendo, progettarne gli sviluppi futuri. == Il Progetto: La scuola come laboratorio di pianificazione territoriale == Questo manuale nasce con l'obiettivo di guidare docenti e studenti nell'utilizzo di '''Luanti''' (precedentemente noto come ''Minetest'') come strumento didattico, integrando la tecnologia, la geografia (GIS), la matematica e l'educazione civica. Il cuore del progetto si articola su tre pilastri fondamentali: * '''Esplorare e Osservare (La Georeferenziazione):''' Creare un mondo digitale che sia il facsimile esatto del proprio territorio reale. Attraverso l'importazione di dati geografici e altimetrici reali, gli studenti possono muoversi in scala 1:1 in un ambiente virtuale familiare, imparando a leggere la morfologia della propria terra da una prospettiva inedita e immersiva. * '''Progettare ed Eseguire (La Ricostruzione):''' Permettere agli studenti di ricostruire l'ambiente, i monumenti e i complessi urbani. Questo processo stimola lo sviluppo di competenze geometriche, di calcolo spaziale e di problem-solving strutturale, costringendo il ragazzo a passare dall'osservazione della realtà alla sua astrazione e successiva esecuzione tridimensionale a blocchi. * '''Partecipare (La Cittadinanza Attiva):''' Dare ai ragazzi la possibilità di utilizzare il server condiviso come un laboratorio democratico per la pianificazione urbana e infrastrutturale collettiva. Gli studenti non si limitano a replicare il presente o il passato, ma possono proporre modifiche, nuove infrastrutture e varianti urbanistiche, imparando il valore del dibattito, della negoziazione e della progettazione comunitaria del bene comune. Attraverso questo percorso, il mondo voxel di Luanti smette di essere un semplice videogioco e diventa un vero e proprio '''gemello digitale didattico''', un ponte tra la scuola e il territorio in grado di formare cittadini consapevoli e tecnicamente preparati. == Il Valore del Software Libero e l'Accessibilità == L'adozione di software libero come Luanti elimina alla radice l'ostacolo delle licenze commerciali e dei costi per le scuole e le famiglie. Questa libertà tecnologica si traduce in una straordinaria agilità operativa: permette di configurare, personalizzare e pubblicare online un server scolastico in modo immediato. Per gli studenti, l'accesso a questo "gemello digitale" del territorio diventa sicuro e inclusivo: chiunque, da qualsiasi dispositivo a casa o a scuola, può connettersi liberamente e partecipare al progetto collettivo, con l'unico requisito di inserire il proprio nome utente e password personalizzati. == Flusso di lavoro: Dati GIS, Modellazione 3D e Iniezione in Luanti == Questo capitolo documenta passo dopo passo la pipeline tecnologica utilizzata per trasformare i dati geografici e altimetrici reali della Val di Ledro in un mondo 3D interamente calpestabile all'interno del server Luanti (Minetest). === Fase 1: Acquisizione dei dati geografici e modellazione in Blender === ==== 1. Selezione dell'Area di Interesse (OSM) ==== Il progetto ha inizio con la delimitazione della zona geografica. Utilizzando il software di modellazione 3D '''Blender''' combinato con l'add-on '''Blender-GIS''', è stato possibile connettersi direttamente ai server cartografici globali. Tramite l'interfaccia di georeferenziazione, è stato ritagliato il perimetro esatto della Val di Ledro attingendo alla cartografia vettoriale di '''OpenStreetMap (OSM)'''. Questa operazione fissa le coordinate di base (Latitudine/Longitudine) nel sistema di riferimento del progetto. ==== 2. Generazione del Rilievo Altimetrico (SRTM) ==== Una volta ottenuta la mappa bidimensionale, si è passati alla terza dimensione applicando i dati altimetrici reali. Sfruttando la funzione di importazione DEM (Digital Elevation Model) di Blender-GIS, sono stati scaricati i dati '''SRTM (Shuttle Radar Topography Mission)''' forniti dalla NASA. Il plugin ha proiettato questi dati vettoriali sulla mesh piana di Blender, deformandola e generando un modello tridimensionale fedele del rilievo montuoso e della morfologia della valle. ==== 3. Download dei Volumi degli Edifici ==== Per integrare l'elemento antropico, è stato effettuato un download mirato direttamente dal portale ufficiale [https://www.openstreetmap.org openstreetmap.org]. È stato esportato un file con estensione <code>.osm</code>, contenente tutti i metadati e le impronte planimetriche degli edifici (i "volumi" e i poligoni delle case) registrati all'interno della medesima area geografica della valle. ==== 4. Posizionamento e Georeferenziazione delle Case ==== Il file <code>.osm</code> grezzo è stato importato all'interno della scena di Blender, sempre tramite l'ausilio di Blender-GIS. Il plugin, riconoscendo la corrispondenza delle coordinate geografiche condivise, ha posizionato automaticamente e matematicamente i volumi geometrici degli edifici sopra il rilievo 3D precedentemente generato, incollando le fondamenta delle case alle rispettive quote del terreno. Nell'importazione viene scelta l'opzione ''buildings''. ==== 5. Importazione del lago ==== Nello stesso modo, e con lo stesso file .osm, usato per importare gli edifici scegliendo l'opzione ''water'' è stato importato il lago di Ledro. Sul lago si è docvuto applicare un ''modifier'' che ha aggiunto una triangolazione della superficie. ==== 6. Esportazione della Mesh ==== Una volta preparato il file in Blender si è proceduto all'esportazione del modello in un formato di interscambio testuale standard. Il file risultante è stato salvato con il nome di <code>LedroValleCompleta.obj</code>, contenente: l'elenco puro dei vertici tridimensionali del terreno, gli edifici in 3d e la superficie del lago.<br/> Un altra informazione contenuta nei file .osm ad esempio è il nome delle vie e degli edifici, ed anche questo dato è interessante da importare nel mondo virtuale in mod da rendewre i luoghi più riconoscibili. === Fase 2: Parsing, Ottimizzazione e Struttura Server === === Il problema tecnologico === I metodi tradizionali di scrittura dei nodi in Luanti via API standard (come `minetest.set_node`) mostrano forti limiti quando si gestiscono milioni di coordinate geometriche: # '''Timeout UDP e Disconnessioni:''' L'elaborazione lineare di file massivi blocca il thread principale del server, causando il congelamento della rete e l'espulsione dei client. # '''Errore Map::getNodeMetadata (Block not found):''' In ambienti a mappa vuota (es. mapgen `singlenode`), il server fallisce l'accesso ai metadati di blocchi non ancora inizializzati sul database del mondo (`map.sqlite`), generando migliaia di warning e fallendo la scrittura. # '''Saturazione RAM in Blender:''' L'uso di modificatori come il ''Remesh'' su mesh territoriali molto estese (es. 20x12 km) satura la memoria volatile del sistema operativo, causando il crash del software di modellazione. === Architettura della Soluzione === La pipeline definitiva si divide in due fasi staccate: un'ottimizzazione matematica dei dati in locale tramite Python e un'iniezione asincrona a basso livello nel server Luanti tramite Lua. ==== Fase 1: Estrazione e Interpolazione dei Dati (Python) ==== Invece di sovraccaricare il motore di gioco o Blender, si utilizza uno script Python esterno sfruttando la libreria '''SciPy''' e l'algoritmo `NearestNDInterpolator` (o `LinearNDInterpolator`). Lo script esegue le seguenti operazioni: # Legge i vertici geometrici (`v X Y Z`) dal file `.obj` originale. # Rileva i confini geografici assoluti della mappa. # Inizializza un interpolatore spaziale e proietta i dati su una griglia fitta bidimensionale regolare (Heightmap) con un passo stabilito (es. ogni 2 metri). # Tappa matematicamente i "buchi di cielo" presenti nella mesh rada, assegnando a ogni coordinata vuota l'altezza corretta calcolata sui punti vicini. # Genera un file di testo ordinato (`ledro_terreno_dati.txt`) in formato `X,Y,Z`. ==== 7. Conversione e Densificazione dei Dati (Python e SciPy) ==== I file <code>.obj</code> nativi presentano una struttura a nuvola di punti (Point Cloud) rada e non ordinata. Con il supporto di '''Gemini''', sono stati sviluppati gli script Python per elaborare i dati: * <code>estrai_griglia.py</code>: Questo script utilizza la libreria scientifica '''SciPy''' (in particolare l'algoritmo <code>NearestNDInterpolator</code>) per analizzare i 66.481 vertici originali distribuiti su un'area di circa 20x12 km. Python proietta questi punti su una griglia fitta bidimensionale regolare (Heightmap) con un passo costante (es. ogni 2 metri), interpolando matematicamente le altezze nei punti vuoti per "tappare i buchi di cielo" e generando un file coordinato e continuo chiamato <code>ledro_terreno_dati.txt</code> in formato <code>X,Y,Z</code>.<syntaxhighlight lang="python"> import os import numpy as np from scipy.interpolate import NearestNDInterpolator FILE_OBJ = "LedroRilievo.obj" FILE_OUTPUT = "ledro_terreno_dati.txt" PASSO = 2 # Un punto ogni 2 metri print("1. Lettura di tutti i vertici dal file OBJ...") punti_validi = [] with open(FILE_OBJ, "r") as f: for line in f: if line.startswith("v "): parti = line.split() if len(parti) >= 4: try: punti_validi.append((float(parti[1]), float(parti[2]), float(parti[3]))) except ValueError: continue if not punti_validi: print("ERRORE: Nessun vertice trovato nel file OBJ!") exit() # Coordinate separate x_arr = np.array([p[0] for p in punti_validi]) y_arr = np.array([p[1] for p in punti_validi]) z_arr = np.array([p[2] for p in punti_validi]) min_x, max_x = int(np.min(x_arr)), int(np.max(x_arr)) min_z, max_z = int(np.min(z_arr)), int(np.max(z_arr)) print(f"Confini rilevati -> X: [{min_x} a {max_x}], Z: [{min_z} a {max_z}]") print("2. Inizializzazione interpolatore geometrico (SciPy)...") # Creiamo l'interpolatore basato sui punti noti dell'OBJ interp = NearestNDInterpolator(list(zip(x_arr, z_arr)), y_arr) print("3. Generazione griglia fitta continua e scrittura...") # Generiamo gli intervalli regolari basati sul PASSO scelto intervallo_x = np.arange(round(min_x / PASSO) * PASSO, round(max_x / PASSO) * PASSO + PASSO, PASSO) intervallo_z = np.arange(round(min_z / PASSO) * PASSO, round(max_z / PASSO) * PASSO + PASSO, PASSO) punti_totali_scritti = 0 with open(FILE_OUTPUT, "w") as out: for gx in intervallo_x: # Calcoliamo l'altezza per l'intera colonna Z in un colpo solo (velocissimo) gz_array = np.array(list(intervallo_z)) gx_array = np.full_like(gz_array, gx) # SciPy calcola le altezze interpolate istantaneamente per tutta la riga altezze_interpolate = interp(gx_array, gz_array) for i, gz in enumerate(intervallo_z): gy = round(altezze_interpolate[i]) out.write(f"{gx},{gy},{gz}\n") punti_totali_scritti += 1 print(f"Operazione completata! Generata griglia solida continua con {punti_totali_scritti} punti complessivi.") </syntaxhighlight> * <code>ledro_convertitore_case.py</code>: Estrae le posizioni degli edifici associandole ai rispettivi blocchi di costruzione, generando il file ordinato <code>ledro_case_dati.txt</code><syntaxhighlight lang="python"> import numpy as np import trimesh import os from math import ceil # ========================================== # CONFIGURAZIONE COSTANTI # ========================================== FILE_OBJ_TERRENO = "LedroRilievo.obj" FILE_OBJ_CASE = "LedroCase.obj" NOME_FILE_USCITA = "ledro_case_dati.txt" # Scala 1.0 per corrispondenza esatta con il terreno a passo 1 metro FAUTORE_SCALA = 1.0 START_Y = 30 def converti_case_streaming(terreno_input, case_input, file_output): if not os.path.exists(case_input) or not os.path.exists(terreno_input): print("Errore: Uno dei file OBJ non esiste nella cartella attuale!") return # 1. Calcolo del centro del terreno per l'allineamento perfetto degli assi print(f"Lettura terreno per allineamento assi: {terreno_input}...") scena_t = trimesh.load(terreno_input, force='mesh') mesh_t = trimesh.util.concatenate([g for g in scena_t.geometry.values()]) if isinstance(scena_t, trimesh.Scene) else scena_t bounds_t = mesh_t.bounds min_x_t, _, min_z_t = bounds_t[0] max_x_t, _, max_z_t = bounds_t[1] centro_x = int((max_x_t - min_x_t) / 2) centro_z = int((max_z_t - min_z_t) / 2) # 2. Caricamento e pulizia della mesh degli edifici print(f"Caricamento edifici da {case_input}...") scena_c = trimesh.load(case_input, force='mesh') if isinstance(scena_c, trimesh.Scene): mesh_unica_case = trimesh.util.concatenate([g for g in scena_c.geometry.values()]) else: mesh_unica_case = scena_c print("Pulizia della mesh e fusione dei vertici adiacenti...") # Valida e salda insieme i poligoni staccati della stessa struttura mesh_unica_case.process(validate=True) print("Separazione degli edifici in componenti connesse...") edifici_grezzi = mesh_unica_case.split(only_watertight=False) # Filtriamo le bricioline geometriche inferiori a 2mq edifici = [edf for edf in edifici_grezzi if edf.area > 2.0] print(f"Trovati {len(edifici)} edifici reali stabili. Generazione geometrie cave...") # Rimuoviamo il vecchio file se presente if os.path.exists(file_output): os.remove(file_output) # 3. Ciclo di generazione geometrica delle case cave (SOLO SOLIDI) edifici_scritti = 0 with open(file_output, "w") as f: for i, edf in enumerate(edifici): b = edf.bounds min_x, min_y, min_z = b[0] max_x, max_y, max_z = b[1] dim_x = int(ceil(max_x - min_x)) dim_y = int(ceil(max_y - min_y)) dim_z = int(ceil(max_z - min_z)) # FILTRO DI SICUREZZA ANTI-LOOP (ARTEFATTI GIS): # Se un "edificio" supera le dimensioni di un enorme isolato, è un errore di mesh dell'OBJ. # Lo saltiamo per evitare che i cicli for successivi congelino la CPU. if dim_x > 60 or dim_z > 60 or dim_y > 40: continue # APPLICAZIONE REGOLE PUNTO 4: Vincoli minimi (5x6x5) larghezza_x = max(5, dim_x) lunghezza_z = max(6, dim_z) altezza_y = max(5, dim_y) # Calcolo coordinate assolute centrate rispetto al terreno start_x = int(min_x - min_x_t - centro_x) start_z = int(min_z - min_z_t - centro_z) start_y = int(min_y + START_Y) edifici_scritti += 1 # Rendering dei soli nodi fisici perimetrali for dx in range(larghezza_x): for dz in range(lunghezza_z): for dy in range(altezza_y): abs_x = start_x + dx abs_z = start_z + dz abs_y = start_y + dy is_muro = (dx == 0 or dx == larghezza_x - 1 or dz == 0 or dz == lunghezza_z - 1) is_pavimento = (dy == 0) is_tetto = (dy == altezza_y - 1) if is_pavimento: blocco = "default:wood" elif is_tetto: blocco = "default:brick" elif is_muro: blocco = "default:stone" else: # Salta l'aria interna! Risparmia lo spazio su disco continue f.write(f"{abs_x},{abs_y},{abs_z},{blocco}\n") if (i + 1) % 100 == 0 or (i + 1) == len(edifici): print(f"Progressione: {i + 1}/{len(edifici)} nodi mesh analizzati... ({edifici_scritti} edifici reali scritti)") print(f"Fatto! File delle case salvato con successo in {file_output}. Scritti {edifici_scritti} edifici.") # ========================================== # PUNTO DI INGRESSO DELLO SCRIPT # ========================================== if __name__ == "__main__": converti_case_streaming(FILE_OBJ_TERRENO, FILE_OBJ_CASE, NOME_FILE_USCITA) </syntaxhighlight> ==== 8. Configurazione dell'Ambiente Virtuale Docker ==== Per ospitare l'infrastruttura di simulazione in modo isolato e replicabile, è stato configurato un container '''Docker''' gestito tramite '''Docker Compose'''. Sulla base di un file <code>docker-compose.yml</code> strutturato ad hoc, la cartella di lavoro del server Luanti/Minetest è stata mappata in locale sul PC dell'utente (tramite i Docker Volumes) per permettere la modifica in tempo reale dei file di gioco. All'interno della configurazione, il mondo è stato battezzato <code>ledro3d</code> e l'utente <code>mattruffoni</code> è stato designato come amministratore di sistema con massimi privilegi energetici.<syntaxhighlight lang="dockerfile"> services: luanti_engine: image: lscr.io/linuxserver/luanti:latest container_name: local_luanti_engine environment: - PUID=1000 - PGID=1000 - TZ=Europe/Rome # FORZATURA: Diciamo a Luanti esattamente quale file .conf leggere dentro il container - CLI_ARGS=--worldname ledro3d --config /config/.minetest/minetest.conf --terminal volumes: - ./server_data:/config/.minetest ports: - 30000:30000/udp restart: unless-stopped </syntaxhighlight> ==== 9. Accessibilità del Server di Gioco ==== Una volta avviato lo stack di Docker tramite terminale (<code>docker compose up -d</code>), il container ha esposto i servizi di rete dedicati. Il server Luanti/Minetest è diventato operativo e raggiungibile in locale dall'indirizzo di loopback '''<code>localhost:30000</code>''', pronto ad accettare le connessioni da parte del client di gioco per l'esplorazione virtuale. === Fase 3: Sviluppo della Mod e Generazione del Mondo === ====Creazione mod '''importatore'''==== Nella cartella ''.../minetest-server/server_data/worlds/ledro3d/worldmods/importatore'' si crea la mod importatore inserendoci il file init.lua, mod.conf e i due file di testo ledro_terreno_dati.txt e ledro_case_dati.txt creati in precedenza. ==== 10. Sviluppo della Mod Lua Asincrona "Importatore" ==== L'iniezione di milioni di nodi all'interno del database del mondo (<code>map.sqlite</code>) presenta forti criticità prestazionali (rischio di timeout UDP e crash per memoria satura). Per ovviare a questo problema, è stata sviluppata una mod personalizzata in linguaggio Lua denominata '''<code>importatore</code>'''. La mod implementa due soluzioni architetturali cruciali: # '''Il VoxelManip Engine (LVM):''' Invece di posizionare un singolo cubo alla volta, la mod alloca grandi porzioni di mappa direttamente nella memoria volatile del server, scrive i blocchi di erba superficiale (<code>default:dirt_with_grass</code>) e le fondamenta sottostanti (<code>default:stone</code>), e forza la scrittura in blocco sul database, azzerando i warning di blocchi non trovati. # '''Gestione tramite Co-routine Lua:''' La lettura dei file <code>.txt</code> è inserita in un ciclo asincrono controllato da co-routine. Tramite l'istruzione <code>coroutine.yield()</code>, la mod rilascia il controllo alla CPU del PC host ogni 100 nodi processati, permettendo al server di rimanere fluido, gestire i pacchetti di rete e consentire il movimento del giocatore durante la crescita progressiva della valle. ==== Fase 2: Iniezione Asincrona nella Mappa (Luanti Mod) ==== La mod Luanti (scritta in `init.lua`) riceve il file a griglia regolare e applica due strategie fondamentali per garantire stabilità e performance: * '''Uso del VoxelManip (LVM):''' Invece di scrivere un blocco alla volta, la mod alloca un'area di memoria temporanea (`minetest.get_voxel_manip()`), manipola l'array dei nodi inserendo la superficie erbosa (`default:dirt_with_grass`) e lo zoccolo di roccia sottostante (`default:stone`), e infine forza la scrittura dell'intero blocco direttamente sul database (`vm:write_to_map()`). Questo bypassa i controlli dei metadati azzerando il warning ''Block not found''. * '''Gestione Asincrona via Co-routine:''' Il ciclo di lettura del file viene inserito in una co-routine Lua (`coroutine.create`). Tramite l'istruzione `coroutine.yield()`, la mod rilascia il controllo alla CPU ogni 100 nodi processati, permettendo al server Luanti di gestire i pacchetti di rete, l'orario del mondo e il login dei giocatori senza lag. ==== Codice init.lua della mod importatore==== <syntaxhighlight lang="lua"> -- ======================================================== -- 1. PRIVILEGI AUTOMATICI PER MATTRUFFONI (CON SETTIME) -- ======================================================== minetest.register_on_joinplayer(function(player) local name = player:get_player_name() if name == "mattruffoni" then minetest.after(0.5, function() local p = minetest.get_player_by_name(name) if p then local privs = minetest.get_player_privs(name) privs.privs = true privs.fly = true privs.fast = true privs.teleport = true privs.interact = true privs.shout = true privs.settime = true -- Aggiunto privilegio per impostare l'ora privs.time = true -- Aggiunto privilegio per gestire il tempo minetest.set_player_privs(name, privs) minetest.chat_send_player(name, "Benvenuto Prof! Privilegi completi (incluso settime) attivati.") end end) end end) -- ======================================================== -- 2. PIPELINE DI IMPORTAZIONE A GRIGLIA ORDINATA (LVM) -- ======================================================== local function avvia_importazione_superficie() local percorso_terreno = minetest.get_modpath("importatore") .. "/ledro_terreno_dati.txt" local percorso_case = minetest.get_modpath("importatore") .. "/ledro_case_dati.txt" local thread = coroutine.create(function() -- A. TERRENO (Morfologia a celle raccordate) local file_t = io.open(percorso_terreno, "r") if file_t then minetest.log("action", "[Importatore] Scrittura griglia terreno georeferenziato...") local count = 0 for line in file_t:lines() do local x, y, z = line:match("([^,]+),([^,]+),([^,]+)") if x and y and z then local tx, ty, tz = tonumber(x), tonumber(y), tonumber(z) -- Raggio 2 crea una piastra 5x5 attorno a ogni punto. -- Avendo ordinato il file a passo 2, le piastre si fondono perfettamente. local raggio = 2 -- Allochiamo l'area minima per il manipolatore di voxel local p_min = {x = tx - raggio, y = ty - 15, z = tz - raggio} local p_max = {x = tx + raggio, y = ty, z = tz + raggio} local vm = minetest.get_voxel_manip() local emin, emax = vm:read_from_map(p_min, p_max) local data = vm:get_data() local va = VoxelArea:new{MinEdge = emin, MaxEdge = emax} local c_grass = minetest.get_content_id("default:dirt_with_grass") local c_stone = minetest.get_content_id("default:stone") -- Disegniamo la piastra locale for dx = -raggio, raggio do for dz = -raggio, raggio do local px = tx + dx local pz = tz + dz -- Blocco d'erba superficiale local vi_g = va:index(px, ty, pz) data[vi_g] = c_grass -- Zoccolo di pietra sottostante (15 blocchi per saldare i dislivelli) for dy = 1, 15 do local vi_s = va:index(px, ty - dy, pz) data[vi_s] = c_stone end end end -- Scrittura forzata nel database senza controlli intermedi vm:set_data(data) vm:write_to_map() count = count + 1 -- Rilasciamo la CPU ogni 100 punti della griglia per mantenere stabile il server if count % 100 == 0 then minetest.log("action", "[Importatore] Punti griglia terreno consolidati: " .. count) coroutine.yield() end end end file_t:close() end -- B. CASE (Puntuali sopra il terreno) local file_c = io.open(percorso_case, "r") if file_c then minetest.log("action", "[Importatore] Iniezione volumi edifici...") local count = 0 for line in file_c:lines() do local x, y, z, blockname = line:match("([^,]+),([^,]+),([^,]+),([^,]+)") if x and y and z and blockname then local pos = {x = tonumber(x), y = tonumber(y), z = tonumber(z)} blockname = blockname:gsub("%s+", "") local vm = minetest.get_voxel_manip() vm:read_from_map(pos, pos) minetest.set_node(pos, {name = blockname}) count = count + 1 if count % 2000 == 0 then minetest.log("action", "[Importatore] Blocchi edificio inseriti: " .. count) coroutine.yield() end end end file_c:close() end minetest.log("action", "[Importatore] PIPELINE COMPLETATA CON SUCCESSO!") minetest.chat_send_all("[Importatore] PIPELINE COMPLETATA! La Val di Ledro a griglia è pronta.") end) local function esegui_passo() if coroutine.status(thread) ~= "dead" then coroutine.resume(thread) minetest.after(0.02, esegui_passo) end end esegui_passo() end -- ======================================================== -- 3. ATTIVAZIONE EVENTO AL LOGIN DI MATTRUFFONI -- ======================================================== local attivato = false minetest.register_on_joinplayer(function(player) if player:get_player_name() == "mattruffoni" and not attivato then attivato = true minetest.after(3.0, function() minetest.chat_send_all("[Importatore] Avvio rigenerazione morfologica a griglia fitta...") avvia_importazione_superficie() end) end end) </syntaxhighlight> =====Codice mod.conf===== <syntaxhighlight lang="lua"> name = importatore description = Importatore geometrico per la Val di Ledro </syntaxhighlight> === Risultati e Sviluppi Pedagogici === L'applicazione di questo flusso permette di generare manti continui di milioni di blocchi mantenendo il server Docker estremamente leggero. Questo ambiente offre uno scenario di apprendimento eccezionale per la didattica laboratoriale (Matematica e Scienze), permettendo agli studenti di esplorare modelli in scala 1:1 del proprio territorio, comprendere l'interazione tra coordinate cartesiane e dati GIS, e interagire con elementi di programmazione e gestione server. === Note === Ovviamente tutto è stato sviluppato con AI, nello specifico Gemini. === Bibliografia === === Collegamenti esterni === [[Categoria:Software libero a scuola|Luanti a scuola]] 91waoqxzrq5kyi9cer4zsn6k21d29do 501063 501062 2026-08-20T08:30:47Z Mattruffoni 17392 /* Perché Luanti nella didattica */ 501063 wikitext text/x-wiki {{Software libero a scuola}} '''''[https://www.luanti.org/it/ Luanti] a scuola''''' è una guida pratica rivolta a docenti, educatori e studenti interessati a integrare la didattica laboratoriale e il ''game-based learning'' nei percorsi scolastici attraverso ambienti virtuali 3D. == Introduzione == L'impiego didattico dei mondi a blocchi (*voxel*) vanta un'esperienza consolidata: la videoludica e la formazione convergono da oltre 15 anni nell'istruzione, con Minecraft promosso in numerosi contesti educativi ed editori di rilievo (come evidenziato nel testo ''A scuola con Minecraft'' di Andrea Benassi, Giunti Scuola, 2021). Tuttavia, l'adozione di software proprietari all'interno delle istituzioni scolastiche può comportare costi di licenza e vincoli tecnici. In questo scenario si inserisce [https://www.luanti.org/it/ Luanti] (storicamente noto come ''Minetest''), una piattaforma open source, gratuita, flessibile e altamente scalabile. == Perché Luanti nella didattica == Luanti offre una vasta libreria di mod e contenuti personalizzabili che ne estendono le funzionalità pedagogiche: * '''Circuiti elettrici e logica digitale:''' attraverso la simulazione di componenti come relè e porte logiche per comprendere la modellazione di sistemi hardware. * '''Coding e robotica:''' mediante l'uso di bot e tartarughe programmabili visualmente o tramite script. * '''Attività multidisciplinari:''' dalla ricostruzione storica di monumenti all'esplorazione di strutture molecolari e geografiche. L'efficacia dell'approccio basato sulla costruzione immersiva trova conferma sul campo: da oltre quattro anni l'utilizzo continuativo di Minetest/Luanti in classe dimostra come il *building* collaborativo favorisca l'acquisizione di competenze trasversali, logico-matematiche e digitali (si veda l'esperienza del progetto [https://www.didasharing.it Didasharing.it]). == Server della community ed esperienze multiplayer == Oltre alle attività in locale o in rete d'istituto, il panorama open source offre significativi esempi di ambienti di rete e server multiplayer: === A.E.S. (Alternative Entertainment Server) === Sviluppato da Zughy e collaboratori, **A.E.S.** rappresenta uno dei più noti hub di minigiochi multiplayer della community di Luanti. Sfruttando l'architettura dinamica e la leggerezza del motore di gioco C++ (con librerie come `arena_lib`), la piattaforma offre varie modalità interattive (tra cui *Block League*, *Skywars*, *Quikbild* e *ColourJump*). Tali arene mostrano come le logiche competitive e lo sviluppo di mod personalizzate possano essere applicati al gioco di squadra e al problem solving. === Framatest e il progetto Libreverse === In ambito internazionale ed educativo, un punto di riferimento storico è stato **Framatest**, il server pubblico ospitato dal network francese [[Framasoft]] per promuovere l'uso di Minetest nella scuola e nella società civile. Oggi quella stessa eredità e lo spirito di condivisione proseguono grazie all'infrastruttura di Chalec, il cui server è raggiungibile e ospitato su [https://www.chalec.org/services/libreverse/ Libreverse]. Usare Luanti/Minetest per giocare a conoscere il territorio e, volendo, progettarne gli sviluppi futuri. == Il Progetto: La scuola come laboratorio di pianificazione territoriale == Questo manuale nasce con l'obiettivo di guidare docenti e studenti nell'utilizzo di '''Luanti''' (precedentemente noto come ''Minetest'') come strumento didattico, integrando la tecnologia, la geografia (GIS), la matematica e l'educazione civica. Il cuore del progetto si articola su tre pilastri fondamentali: * '''Esplorare e Osservare (La Georeferenziazione):''' Creare un mondo digitale che sia il facsimile esatto del proprio territorio reale. Attraverso l'importazione di dati geografici e altimetrici reali, gli studenti possono muoversi in scala 1:1 in un ambiente virtuale familiare, imparando a leggere la morfologia della propria terra da una prospettiva inedita e immersiva. * '''Progettare ed Eseguire (La Ricostruzione):''' Permettere agli studenti di ricostruire l'ambiente, i monumenti e i complessi urbani. Questo processo stimola lo sviluppo di competenze geometriche, di calcolo spaziale e di problem-solving strutturale, costringendo il ragazzo a passare dall'osservazione della realtà alla sua astrazione e successiva esecuzione tridimensionale a blocchi. * '''Partecipare (La Cittadinanza Attiva):''' Dare ai ragazzi la possibilità di utilizzare il server condiviso come un laboratorio democratico per la pianificazione urbana e infrastrutturale collettiva. Gli studenti non si limitano a replicare il presente o il passato, ma possono proporre modifiche, nuove infrastrutture e varianti urbanistiche, imparando il valore del dibattito, della negoziazione e della progettazione comunitaria del bene comune. Attraverso questo percorso, il mondo voxel di Luanti smette di essere un semplice videogioco e diventa un vero e proprio '''gemello digitale didattico''', un ponte tra la scuola e il territorio in grado di formare cittadini consapevoli e tecnicamente preparati. == Il Valore del Software Libero e l'Accessibilità == L'adozione di software libero come Luanti elimina alla radice l'ostacolo delle licenze commerciali e dei costi per le scuole e le famiglie. Questa libertà tecnologica si traduce in una straordinaria agilità operativa: permette di configurare, personalizzare e pubblicare online un server scolastico in modo immediato. Per gli studenti, l'accesso a questo "gemello digitale" del territorio diventa sicuro e inclusivo: chiunque, da qualsiasi dispositivo a casa o a scuola, può connettersi liberamente e partecipare al progetto collettivo, con l'unico requisito di inserire il proprio nome utente e password personalizzati. == Flusso di lavoro: Dati GIS, Modellazione 3D e Iniezione in Luanti == Questo capitolo documenta passo dopo passo la pipeline tecnologica utilizzata per trasformare i dati geografici e altimetrici reali della Val di Ledro in un mondo 3D interamente calpestabile all'interno del server Luanti (Minetest). === Fase 1: Acquisizione dei dati geografici e modellazione in Blender === ==== 1. Selezione dell'Area di Interesse (OSM) ==== Il progetto ha inizio con la delimitazione della zona geografica. Utilizzando il software di modellazione 3D '''Blender''' combinato con l'add-on '''Blender-GIS''', è stato possibile connettersi direttamente ai server cartografici globali. Tramite l'interfaccia di georeferenziazione, è stato ritagliato il perimetro esatto della Val di Ledro attingendo alla cartografia vettoriale di '''OpenStreetMap (OSM)'''. Questa operazione fissa le coordinate di base (Latitudine/Longitudine) nel sistema di riferimento del progetto. ==== 2. Generazione del Rilievo Altimetrico (SRTM) ==== Una volta ottenuta la mappa bidimensionale, si è passati alla terza dimensione applicando i dati altimetrici reali. Sfruttando la funzione di importazione DEM (Digital Elevation Model) di Blender-GIS, sono stati scaricati i dati '''SRTM (Shuttle Radar Topography Mission)''' forniti dalla NASA. Il plugin ha proiettato questi dati vettoriali sulla mesh piana di Blender, deformandola e generando un modello tridimensionale fedele del rilievo montuoso e della morfologia della valle. ==== 3. Download dei Volumi degli Edifici ==== Per integrare l'elemento antropico, è stato effettuato un download mirato direttamente dal portale ufficiale [https://www.openstreetmap.org openstreetmap.org]. È stato esportato un file con estensione <code>.osm</code>, contenente tutti i metadati e le impronte planimetriche degli edifici (i "volumi" e i poligoni delle case) registrati all'interno della medesima area geografica della valle. ==== 4. Posizionamento e Georeferenziazione delle Case ==== Il file <code>.osm</code> grezzo è stato importato all'interno della scena di Blender, sempre tramite l'ausilio di Blender-GIS. Il plugin, riconoscendo la corrispondenza delle coordinate geografiche condivise, ha posizionato automaticamente e matematicamente i volumi geometrici degli edifici sopra il rilievo 3D precedentemente generato, incollando le fondamenta delle case alle rispettive quote del terreno. Nell'importazione viene scelta l'opzione ''buildings''. ==== 5. Importazione del lago ==== Nello stesso modo, e con lo stesso file .osm, usato per importare gli edifici scegliendo l'opzione ''water'' è stato importato il lago di Ledro. Sul lago si è docvuto applicare un ''modifier'' che ha aggiunto una triangolazione della superficie. ==== 6. Esportazione della Mesh ==== Una volta preparato il file in Blender si è proceduto all'esportazione del modello in un formato di interscambio testuale standard. Il file risultante è stato salvato con il nome di <code>LedroValleCompleta.obj</code>, contenente: l'elenco puro dei vertici tridimensionali del terreno, gli edifici in 3d e la superficie del lago.<br/> Un altra informazione contenuta nei file .osm ad esempio è il nome delle vie e degli edifici, ed anche questo dato è interessante da importare nel mondo virtuale in mod da rendewre i luoghi più riconoscibili. === Fase 2: Parsing, Ottimizzazione e Struttura Server === === Il problema tecnologico === I metodi tradizionali di scrittura dei nodi in Luanti via API standard (come `minetest.set_node`) mostrano forti limiti quando si gestiscono milioni di coordinate geometriche: # '''Timeout UDP e Disconnessioni:''' L'elaborazione lineare di file massivi blocca il thread principale del server, causando il congelamento della rete e l'espulsione dei client. # '''Errore Map::getNodeMetadata (Block not found):''' In ambienti a mappa vuota (es. mapgen `singlenode`), il server fallisce l'accesso ai metadati di blocchi non ancora inizializzati sul database del mondo (`map.sqlite`), generando migliaia di warning e fallendo la scrittura. # '''Saturazione RAM in Blender:''' L'uso di modificatori come il ''Remesh'' su mesh territoriali molto estese (es. 20x12 km) satura la memoria volatile del sistema operativo, causando il crash del software di modellazione. === Architettura della Soluzione === La pipeline definitiva si divide in due fasi staccate: un'ottimizzazione matematica dei dati in locale tramite Python e un'iniezione asincrona a basso livello nel server Luanti tramite Lua. ==== Fase 1: Estrazione e Interpolazione dei Dati (Python) ==== Invece di sovraccaricare il motore di gioco o Blender, si utilizza uno script Python esterno sfruttando la libreria '''SciPy''' e l'algoritmo `NearestNDInterpolator` (o `LinearNDInterpolator`). Lo script esegue le seguenti operazioni: # Legge i vertici geometrici (`v X Y Z`) dal file `.obj` originale. # Rileva i confini geografici assoluti della mappa. # Inizializza un interpolatore spaziale e proietta i dati su una griglia fitta bidimensionale regolare (Heightmap) con un passo stabilito (es. ogni 2 metri). # Tappa matematicamente i "buchi di cielo" presenti nella mesh rada, assegnando a ogni coordinata vuota l'altezza corretta calcolata sui punti vicini. # Genera un file di testo ordinato (`ledro_terreno_dati.txt`) in formato `X,Y,Z`. ==== 7. Conversione e Densificazione dei Dati (Python e SciPy) ==== I file <code>.obj</code> nativi presentano una struttura a nuvola di punti (Point Cloud) rada e non ordinata. Con il supporto di '''Gemini''', sono stati sviluppati gli script Python per elaborare i dati: * <code>estrai_griglia.py</code>: Questo script utilizza la libreria scientifica '''SciPy''' (in particolare l'algoritmo <code>NearestNDInterpolator</code>) per analizzare i 66.481 vertici originali distribuiti su un'area di circa 20x12 km. Python proietta questi punti su una griglia fitta bidimensionale regolare (Heightmap) con un passo costante (es. ogni 2 metri), interpolando matematicamente le altezze nei punti vuoti per "tappare i buchi di cielo" e generando un file coordinato e continuo chiamato <code>ledro_terreno_dati.txt</code> in formato <code>X,Y,Z</code>.<syntaxhighlight lang="python"> import os import numpy as np from scipy.interpolate import NearestNDInterpolator FILE_OBJ = "LedroRilievo.obj" FILE_OUTPUT = "ledro_terreno_dati.txt" PASSO = 2 # Un punto ogni 2 metri print("1. Lettura di tutti i vertici dal file OBJ...") punti_validi = [] with open(FILE_OBJ, "r") as f: for line in f: if line.startswith("v "): parti = line.split() if len(parti) >= 4: try: punti_validi.append((float(parti[1]), float(parti[2]), float(parti[3]))) except ValueError: continue if not punti_validi: print("ERRORE: Nessun vertice trovato nel file OBJ!") exit() # Coordinate separate x_arr = np.array([p[0] for p in punti_validi]) y_arr = np.array([p[1] for p in punti_validi]) z_arr = np.array([p[2] for p in punti_validi]) min_x, max_x = int(np.min(x_arr)), int(np.max(x_arr)) min_z, max_z = int(np.min(z_arr)), int(np.max(z_arr)) print(f"Confini rilevati -> X: [{min_x} a {max_x}], Z: [{min_z} a {max_z}]") print("2. Inizializzazione interpolatore geometrico (SciPy)...") # Creiamo l'interpolatore basato sui punti noti dell'OBJ interp = NearestNDInterpolator(list(zip(x_arr, z_arr)), y_arr) print("3. Generazione griglia fitta continua e scrittura...") # Generiamo gli intervalli regolari basati sul PASSO scelto intervallo_x = np.arange(round(min_x / PASSO) * PASSO, round(max_x / PASSO) * PASSO + PASSO, PASSO) intervallo_z = np.arange(round(min_z / PASSO) * PASSO, round(max_z / PASSO) * PASSO + PASSO, PASSO) punti_totali_scritti = 0 with open(FILE_OUTPUT, "w") as out: for gx in intervallo_x: # Calcoliamo l'altezza per l'intera colonna Z in un colpo solo (velocissimo) gz_array = np.array(list(intervallo_z)) gx_array = np.full_like(gz_array, gx) # SciPy calcola le altezze interpolate istantaneamente per tutta la riga altezze_interpolate = interp(gx_array, gz_array) for i, gz in enumerate(intervallo_z): gy = round(altezze_interpolate[i]) out.write(f"{gx},{gy},{gz}\n") punti_totali_scritti += 1 print(f"Operazione completata! Generata griglia solida continua con {punti_totali_scritti} punti complessivi.") </syntaxhighlight> * <code>ledro_convertitore_case.py</code>: Estrae le posizioni degli edifici associandole ai rispettivi blocchi di costruzione, generando il file ordinato <code>ledro_case_dati.txt</code><syntaxhighlight lang="python"> import numpy as np import trimesh import os from math import ceil # ========================================== # CONFIGURAZIONE COSTANTI # ========================================== FILE_OBJ_TERRENO = "LedroRilievo.obj" FILE_OBJ_CASE = "LedroCase.obj" NOME_FILE_USCITA = "ledro_case_dati.txt" # Scala 1.0 per corrispondenza esatta con il terreno a passo 1 metro FAUTORE_SCALA = 1.0 START_Y = 30 def converti_case_streaming(terreno_input, case_input, file_output): if not os.path.exists(case_input) or not os.path.exists(terreno_input): print("Errore: Uno dei file OBJ non esiste nella cartella attuale!") return # 1. Calcolo del centro del terreno per l'allineamento perfetto degli assi print(f"Lettura terreno per allineamento assi: {terreno_input}...") scena_t = trimesh.load(terreno_input, force='mesh') mesh_t = trimesh.util.concatenate([g for g in scena_t.geometry.values()]) if isinstance(scena_t, trimesh.Scene) else scena_t bounds_t = mesh_t.bounds min_x_t, _, min_z_t = bounds_t[0] max_x_t, _, max_z_t = bounds_t[1] centro_x = int((max_x_t - min_x_t) / 2) centro_z = int((max_z_t - min_z_t) / 2) # 2. Caricamento e pulizia della mesh degli edifici print(f"Caricamento edifici da {case_input}...") scena_c = trimesh.load(case_input, force='mesh') if isinstance(scena_c, trimesh.Scene): mesh_unica_case = trimesh.util.concatenate([g for g in scena_c.geometry.values()]) else: mesh_unica_case = scena_c print("Pulizia della mesh e fusione dei vertici adiacenti...") # Valida e salda insieme i poligoni staccati della stessa struttura mesh_unica_case.process(validate=True) print("Separazione degli edifici in componenti connesse...") edifici_grezzi = mesh_unica_case.split(only_watertight=False) # Filtriamo le bricioline geometriche inferiori a 2mq edifici = [edf for edf in edifici_grezzi if edf.area > 2.0] print(f"Trovati {len(edifici)} edifici reali stabili. Generazione geometrie cave...") # Rimuoviamo il vecchio file se presente if os.path.exists(file_output): os.remove(file_output) # 3. Ciclo di generazione geometrica delle case cave (SOLO SOLIDI) edifici_scritti = 0 with open(file_output, "w") as f: for i, edf in enumerate(edifici): b = edf.bounds min_x, min_y, min_z = b[0] max_x, max_y, max_z = b[1] dim_x = int(ceil(max_x - min_x)) dim_y = int(ceil(max_y - min_y)) dim_z = int(ceil(max_z - min_z)) # FILTRO DI SICUREZZA ANTI-LOOP (ARTEFATTI GIS): # Se un "edificio" supera le dimensioni di un enorme isolato, è un errore di mesh dell'OBJ. # Lo saltiamo per evitare che i cicli for successivi congelino la CPU. if dim_x > 60 or dim_z > 60 or dim_y > 40: continue # APPLICAZIONE REGOLE PUNTO 4: Vincoli minimi (5x6x5) larghezza_x = max(5, dim_x) lunghezza_z = max(6, dim_z) altezza_y = max(5, dim_y) # Calcolo coordinate assolute centrate rispetto al terreno start_x = int(min_x - min_x_t - centro_x) start_z = int(min_z - min_z_t - centro_z) start_y = int(min_y + START_Y) edifici_scritti += 1 # Rendering dei soli nodi fisici perimetrali for dx in range(larghezza_x): for dz in range(lunghezza_z): for dy in range(altezza_y): abs_x = start_x + dx abs_z = start_z + dz abs_y = start_y + dy is_muro = (dx == 0 or dx == larghezza_x - 1 or dz == 0 or dz == lunghezza_z - 1) is_pavimento = (dy == 0) is_tetto = (dy == altezza_y - 1) if is_pavimento: blocco = "default:wood" elif is_tetto: blocco = "default:brick" elif is_muro: blocco = "default:stone" else: # Salta l'aria interna! Risparmia lo spazio su disco continue f.write(f"{abs_x},{abs_y},{abs_z},{blocco}\n") if (i + 1) % 100 == 0 or (i + 1) == len(edifici): print(f"Progressione: {i + 1}/{len(edifici)} nodi mesh analizzati... ({edifici_scritti} edifici reali scritti)") print(f"Fatto! File delle case salvato con successo in {file_output}. Scritti {edifici_scritti} edifici.") # ========================================== # PUNTO DI INGRESSO DELLO SCRIPT # ========================================== if __name__ == "__main__": converti_case_streaming(FILE_OBJ_TERRENO, FILE_OBJ_CASE, NOME_FILE_USCITA) </syntaxhighlight> ==== 8. Configurazione dell'Ambiente Virtuale Docker ==== Per ospitare l'infrastruttura di simulazione in modo isolato e replicabile, è stato configurato un container '''Docker''' gestito tramite '''Docker Compose'''. Sulla base di un file <code>docker-compose.yml</code> strutturato ad hoc, la cartella di lavoro del server Luanti/Minetest è stata mappata in locale sul PC dell'utente (tramite i Docker Volumes) per permettere la modifica in tempo reale dei file di gioco. All'interno della configurazione, il mondo è stato battezzato <code>ledro3d</code> e l'utente <code>mattruffoni</code> è stato designato come amministratore di sistema con massimi privilegi energetici.<syntaxhighlight lang="dockerfile"> services: luanti_engine: image: lscr.io/linuxserver/luanti:latest container_name: local_luanti_engine environment: - PUID=1000 - PGID=1000 - TZ=Europe/Rome # FORZATURA: Diciamo a Luanti esattamente quale file .conf leggere dentro il container - CLI_ARGS=--worldname ledro3d --config /config/.minetest/minetest.conf --terminal volumes: - ./server_data:/config/.minetest ports: - 30000:30000/udp restart: unless-stopped </syntaxhighlight> ==== 9. Accessibilità del Server di Gioco ==== Una volta avviato lo stack di Docker tramite terminale (<code>docker compose up -d</code>), il container ha esposto i servizi di rete dedicati. Il server Luanti/Minetest è diventato operativo e raggiungibile in locale dall'indirizzo di loopback '''<code>localhost:30000</code>''', pronto ad accettare le connessioni da parte del client di gioco per l'esplorazione virtuale. === Fase 3: Sviluppo della Mod e Generazione del Mondo === ====Creazione mod '''importatore'''==== Nella cartella ''.../minetest-server/server_data/worlds/ledro3d/worldmods/importatore'' si crea la mod importatore inserendoci il file init.lua, mod.conf e i due file di testo ledro_terreno_dati.txt e ledro_case_dati.txt creati in precedenza. ==== 10. Sviluppo della Mod Lua Asincrona "Importatore" ==== L'iniezione di milioni di nodi all'interno del database del mondo (<code>map.sqlite</code>) presenta forti criticità prestazionali (rischio di timeout UDP e crash per memoria satura). Per ovviare a questo problema, è stata sviluppata una mod personalizzata in linguaggio Lua denominata '''<code>importatore</code>'''. La mod implementa due soluzioni architetturali cruciali: # '''Il VoxelManip Engine (LVM):''' Invece di posizionare un singolo cubo alla volta, la mod alloca grandi porzioni di mappa direttamente nella memoria volatile del server, scrive i blocchi di erba superficiale (<code>default:dirt_with_grass</code>) e le fondamenta sottostanti (<code>default:stone</code>), e forza la scrittura in blocco sul database, azzerando i warning di blocchi non trovati. # '''Gestione tramite Co-routine Lua:''' La lettura dei file <code>.txt</code> è inserita in un ciclo asincrono controllato da co-routine. Tramite l'istruzione <code>coroutine.yield()</code>, la mod rilascia il controllo alla CPU del PC host ogni 100 nodi processati, permettendo al server di rimanere fluido, gestire i pacchetti di rete e consentire il movimento del giocatore durante la crescita progressiva della valle. ==== Fase 2: Iniezione Asincrona nella Mappa (Luanti Mod) ==== La mod Luanti (scritta in `init.lua`) riceve il file a griglia regolare e applica due strategie fondamentali per garantire stabilità e performance: * '''Uso del VoxelManip (LVM):''' Invece di scrivere un blocco alla volta, la mod alloca un'area di memoria temporanea (`minetest.get_voxel_manip()`), manipola l'array dei nodi inserendo la superficie erbosa (`default:dirt_with_grass`) e lo zoccolo di roccia sottostante (`default:stone`), e infine forza la scrittura dell'intero blocco direttamente sul database (`vm:write_to_map()`). Questo bypassa i controlli dei metadati azzerando il warning ''Block not found''. * '''Gestione Asincrona via Co-routine:''' Il ciclo di lettura del file viene inserito in una co-routine Lua (`coroutine.create`). Tramite l'istruzione `coroutine.yield()`, la mod rilascia il controllo alla CPU ogni 100 nodi processati, permettendo al server Luanti di gestire i pacchetti di rete, l'orario del mondo e il login dei giocatori senza lag. ==== Codice init.lua della mod importatore==== <syntaxhighlight lang="lua"> -- ======================================================== -- 1. PRIVILEGI AUTOMATICI PER MATTRUFFONI (CON SETTIME) -- ======================================================== minetest.register_on_joinplayer(function(player) local name = player:get_player_name() if name == "mattruffoni" then minetest.after(0.5, function() local p = minetest.get_player_by_name(name) if p then local privs = minetest.get_player_privs(name) privs.privs = true privs.fly = true privs.fast = true privs.teleport = true privs.interact = true privs.shout = true privs.settime = true -- Aggiunto privilegio per impostare l'ora privs.time = true -- Aggiunto privilegio per gestire il tempo minetest.set_player_privs(name, privs) minetest.chat_send_player(name, "Benvenuto Prof! Privilegi completi (incluso settime) attivati.") end end) end end) -- ======================================================== -- 2. PIPELINE DI IMPORTAZIONE A GRIGLIA ORDINATA (LVM) -- ======================================================== local function avvia_importazione_superficie() local percorso_terreno = minetest.get_modpath("importatore") .. "/ledro_terreno_dati.txt" local percorso_case = minetest.get_modpath("importatore") .. "/ledro_case_dati.txt" local thread = coroutine.create(function() -- A. TERRENO (Morfologia a celle raccordate) local file_t = io.open(percorso_terreno, "r") if file_t then minetest.log("action", "[Importatore] Scrittura griglia terreno georeferenziato...") local count = 0 for line in file_t:lines() do local x, y, z = line:match("([^,]+),([^,]+),([^,]+)") if x and y and z then local tx, ty, tz = tonumber(x), tonumber(y), tonumber(z) -- Raggio 2 crea una piastra 5x5 attorno a ogni punto. -- Avendo ordinato il file a passo 2, le piastre si fondono perfettamente. local raggio = 2 -- Allochiamo l'area minima per il manipolatore di voxel local p_min = {x = tx - raggio, y = ty - 15, z = tz - raggio} local p_max = {x = tx + raggio, y = ty, z = tz + raggio} local vm = minetest.get_voxel_manip() local emin, emax = vm:read_from_map(p_min, p_max) local data = vm:get_data() local va = VoxelArea:new{MinEdge = emin, MaxEdge = emax} local c_grass = minetest.get_content_id("default:dirt_with_grass") local c_stone = minetest.get_content_id("default:stone") -- Disegniamo la piastra locale for dx = -raggio, raggio do for dz = -raggio, raggio do local px = tx + dx local pz = tz + dz -- Blocco d'erba superficiale local vi_g = va:index(px, ty, pz) data[vi_g] = c_grass -- Zoccolo di pietra sottostante (15 blocchi per saldare i dislivelli) for dy = 1, 15 do local vi_s = va:index(px, ty - dy, pz) data[vi_s] = c_stone end end end -- Scrittura forzata nel database senza controlli intermedi vm:set_data(data) vm:write_to_map() count = count + 1 -- Rilasciamo la CPU ogni 100 punti della griglia per mantenere stabile il server if count % 100 == 0 then minetest.log("action", "[Importatore] Punti griglia terreno consolidati: " .. count) coroutine.yield() end end end file_t:close() end -- B. CASE (Puntuali sopra il terreno) local file_c = io.open(percorso_case, "r") if file_c then minetest.log("action", "[Importatore] Iniezione volumi edifici...") local count = 0 for line in file_c:lines() do local x, y, z, blockname = line:match("([^,]+),([^,]+),([^,]+),([^,]+)") if x and y and z and blockname then local pos = {x = tonumber(x), y = tonumber(y), z = tonumber(z)} blockname = blockname:gsub("%s+", "") local vm = minetest.get_voxel_manip() vm:read_from_map(pos, pos) minetest.set_node(pos, {name = blockname}) count = count + 1 if count % 2000 == 0 then minetest.log("action", "[Importatore] Blocchi edificio inseriti: " .. count) coroutine.yield() end end end file_c:close() end minetest.log("action", "[Importatore] PIPELINE COMPLETATA CON SUCCESSO!") minetest.chat_send_all("[Importatore] PIPELINE COMPLETATA! La Val di Ledro a griglia è pronta.") end) local function esegui_passo() if coroutine.status(thread) ~= "dead" then coroutine.resume(thread) minetest.after(0.02, esegui_passo) end end esegui_passo() end -- ======================================================== -- 3. ATTIVAZIONE EVENTO AL LOGIN DI MATTRUFFONI -- ======================================================== local attivato = false minetest.register_on_joinplayer(function(player) if player:get_player_name() == "mattruffoni" and not attivato then attivato = true minetest.after(3.0, function() minetest.chat_send_all("[Importatore] Avvio rigenerazione morfologica a griglia fitta...") avvia_importazione_superficie() end) end end) </syntaxhighlight> =====Codice mod.conf===== <syntaxhighlight lang="lua"> name = importatore description = Importatore geometrico per la Val di Ledro </syntaxhighlight> === Risultati e Sviluppi Pedagogici === L'applicazione di questo flusso permette di generare manti continui di milioni di blocchi mantenendo il server Docker estremamente leggero. Questo ambiente offre uno scenario di apprendimento eccezionale per la didattica laboratoriale (Matematica e Scienze), permettendo agli studenti di esplorare modelli in scala 1:1 del proprio territorio, comprendere l'interazione tra coordinate cartesiane e dati GIS, e interagire con elementi di programmazione e gestione server. === Note === Ovviamente tutto è stato sviluppato con AI, nello specifico Gemini. === Bibliografia === === Collegamenti esterni === [[Categoria:Software libero a scuola|Luanti a scuola]] 150cot3vvbt5ig6527c2dubm7sntv3f Disposizioni foniche di organi a canne/Italia/Abruzzo/Provincia di Chieti/Vasto/Vasto - Chiesa di San Francesco di Paola 0 60960 501042 501038 2026-08-19T19:27:23Z VoceUmana7 51633 501042 wikitext text/x-wiki {{disposizioni foniche di organi a canne}} * '''Costruttore:''' Fratelli Ciavarelli * '''Anno:''' prima metà del sec. XIX * '''Restauri/modifiche:''' anonimo (manutenzione, 1885), R. Palma (installazione dell'elettroventilatore, sec. XX) * '''Registri:''' 7 * '''Canne:''' ca. 330 * '''Trasmissione:''' meccanica * '''Consolle:''' a finestra * '''Tastiere:''' 1 di 50 note con la prima ottava scavezza (''Do<sup>1</sup>''-''Fa<sup>5</sup>'') * '''Pedaliera:''' scavezza a leggio di 9 note (''Do<sup>1</sup>''-''Do<sup>2</sup>'') costantemente unita alla tastiera *'''Accessori:''' Tiratutti a pomello * '''Collocazione:''' a pavimento nel presbiterio {| border="0" cellspacing="0" cellpadding="20" style="border-collapse:collapse;" | style="vertical-align:top" | {| border="0" | colspan=2 | '''Colonna di sinistra - ''Ripieno''''' ---- |- |Principale |- |Ottava |- |Decima quinta |- |Decima nona |- |Vigesima seconda |- |} | style="vertical-align:top" | {| border="0" | colspan=2 | '''Colonna di destra - ''Concerto''''' ---- |- |Flauto in VIII |- |Voce umana<ref>dal ''Do<sup>3</sup>''</ref> |- |} |} == Note == <references/> {{Avanzamento|100%|18 agosto 2026}} [[Categoria:Disposizioni foniche di organi a canne]] qfjlalxb1dtngbczs431d49zaeucbbc Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Buscemi 0 60963 501044 501022 2026-08-19T21:47:54Z ~2026-45474-98 54699 501044 wikitext text/x-wiki {{Disposizioni foniche di organi a canne}} Disposizioni foniche del comune di [[w:Buscemi|Buscemi]] raggruppate per edificio. * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Buscemi/Buscemi - Chiesa di Sant'Antonio|Chiesa di Sant'Antonio]] ewwzc4qphtcvy7obgtxcce5dskyar9z 501046 501044 2026-08-19T21:58:00Z ~2026-45474-98 54699 501046 wikitext text/x-wiki {{Disposizioni foniche di organi a canne}} Disposizioni foniche del comune di [[w:Buscemi|Buscemi]] raggruppate per edificio. * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Buscemi/Buscemi - Chiesa di Sant'Antonio|Chiesa di Sant'Antonio]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Buscemi/Buscemi - Chiesa Madre - Natività di Maria Santissima|Chiesa Madre - Natività di Maria Santissima]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Buscemi/Buscemi - Chiesa di San Sebastiano|Chiesa di San Sebastiano]] djom83t9bpwzf50u33z0yc7hopclzt3 Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Buscemi/Buscemi - Chiesa di Sant'Antonio 0 60964 501049 501026 2026-08-19T22:00:56Z ~2026-45474-98 54699 501049 wikitext text/x-wiki {{disposizioni foniche di organi a canne}} * '''Costruttore:''' Donato del Piano * '''Anno:''' * '''Restauri:''' * '''Registri:''' 11 * '''Canne:''' * '''Trasmissione:''' meccanica * '''Consolle:''' a finestra * '''Tastiere:''' 1 di 45 tasti (''Do<sup>1</sup>''-''Do<sup>5</sup>''), con prima ottava corta * '''Pedaliera:''' di 12 note ((''Do<sup>1</sup>''-''Si<sup>1</sup>'')) * '''Collocazione:''' * '''Accessori:''' * '''Note:''' {| border="0" cellspacing="0" cellpadding="20" style="border-collapse:collapse;" | style="vertical-align:top" | | style="vertical-align:top" | {| border="0" | colspan=2 | |- |Principale I |- |Principale II |- |Ottava |- |Decimaquinta |- |Decimanona |- |Vigesimaseconda |- |Vigesimasesta |- |Vigesimanona |- | |- | |- | |- |} | style="vertical-align:top" | {| border="0" | colspan=2 | |- |Voce Umana |- |Flauto in ottava |- |Flauto in XII |- |} |} eoxgolm7lbtqgz4wim2a2nv4h1nhtvq Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Canicattini Bagni/Canicattini Bagni- Chiesa Madre 0 60970 501045 2026-08-19T21:50:48Z ~2026-45474-98 54699 Nuova pagina: {{disposizioni foniche di organi a canne}} * '''Costruttore:''' * '''Anno:''' * '''Restauri:''' * '''Registri:''' * '''Canne:''' * '''Trasmissione:''' * '''Consolle:''' * '''Tastiere:''' 1 di 45 tasti (''Do<sup>1</sup>''-''Do<sup>5</sup>''), con prima ottava corta * '''Pedaliera:''' di 12 note ((''Do<sup>1</sup>''-''Si<sup>1</sup>'')) * '''Collocazione:''' navata centrale destra nell'intercolunnio * '''Accessori:''' * '''Note:''' 501045 wikitext text/x-wiki {{disposizioni foniche di organi a canne}} * '''Costruttore:''' * '''Anno:''' * '''Restauri:''' * '''Registri:''' * '''Canne:''' * '''Trasmissione:''' * '''Consolle:''' * '''Tastiere:''' 1 di 45 tasti (''Do<sup>1</sup>''-''Do<sup>5</sup>''), con prima ottava corta * '''Pedaliera:''' di 12 note ((''Do<sup>1</sup>''-''Si<sup>1</sup>'')) * '''Collocazione:''' navata centrale destra nell'intercolunnio * '''Accessori:''' * '''Note:''' cknfhafghzvlhkgy5gq9e5odx3mll30 501050 501045 2026-08-19T22:01:52Z ~2026-45474-98 54699 501050 wikitext text/x-wiki {{disposizioni foniche di organi a canne}} * '''Costruttore:''' * '''Anno:''' * '''Restauri:''' * '''Registri:''' * '''Canne:''' * '''Trasmissione:''' * '''Consolle:''' * '''Tastiere:''' 1 di 45 tasti (''Do<sup>1</sup>''-''Do<sup>5</sup>''), con prima ottava corta * '''Pedaliera:''' di 12 note ((''Do<sup>1</sup>''-''Si<sup>1</sup>'')) * '''Collocazione:''' navata centrale nell'intercolunnio destro * '''Accessori:''' * '''Note:''' rkttzeu0tyhz09oimsa4v2uluva8pl3 Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Buscemi/Buscemi - Chiesa Madre - Natività di Maria Santissima 0 60971 501047 2026-08-19T21:59:22Z ~2026-45474-98 54699 Nuova pagina: {{disposizioni foniche di organi a canne}} * '''Costruttore:''' Donato del Piano * '''Anno:''' * '''Restauri:''' * '''Registri:''' * '''Canne:''' * '''Trasmissione:''' * '''Consolle:''' * '''Tastiere:''' 1 di 45 tasti (''Do<sup>1</sup>''-''Do<sup>5</sup>''), con prima ottava corta * '''Pedaliera:''' di 12 note ((''Do<sup>1</sup>''-''Si<sup>1</sup>'')) * '''Collocazione:''' in cantoria in controfacciata * '''Accessori:''' * '''Note:''' 501047 wikitext text/x-wiki {{disposizioni foniche di organi a canne}} * '''Costruttore:''' Donato del Piano * '''Anno:''' * '''Restauri:''' * '''Registri:''' * '''Canne:''' * '''Trasmissione:''' * '''Consolle:''' * '''Tastiere:''' 1 di 45 tasti (''Do<sup>1</sup>''-''Do<sup>5</sup>''), con prima ottava corta * '''Pedaliera:''' di 12 note ((''Do<sup>1</sup>''-''Si<sup>1</sup>'')) * '''Collocazione:''' in cantoria in controfacciata * '''Accessori:''' * '''Note:''' g9av4x9j1xbloydqm5w5ixpnvtcggec 501048 501047 2026-08-19T22:00:02Z ~2026-45474-98 54699 501048 wikitext text/x-wiki {{disposizioni foniche di organi a canne}} * '''Costruttore:''' Donato del Piano * '''Anno:''' * '''Restauri:''' * '''Registri:''' * '''Canne:''' * '''Trasmissione:''' * '''Consolle:''' * '''Tastiere:''' 1 di 45 tasti (''Do<sup>1</sup>''-''Do<sup>5</sup>''), con prima ottava corta * '''Pedaliera:''' di 12 note ((''Do<sup>1</sup>''-''Si<sup>1</sup>'')) * '''Collocazione:''' in cantoria in controfacciata * '''Accessori:''' * '''Note:''' attualmente in fase di restauro 0sri1kw8ieac79i0mt7nk6wl0j94ux8 Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Melilli 0 60972 501051 2026-08-19T22:04:49Z ~2026-45474-98 54699 Nuova pagina: * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Melilli/Melilli- Basilica di San Sebastiano|Basilica di San Sebastiano]] 501051 wikitext text/x-wiki * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Melilli/Melilli- Basilica di San Sebastiano|Basilica di San Sebastiano]] blky3adwch3kuh95dv81l8twcddg7vv 501052 501051 2026-08-19T22:05:59Z ~2026-45474-98 54699 501052 wikitext text/x-wiki {{Disposizioni foniche di organi a canne}} Disposizioni foniche del comune di [[w:Melilli|Melilli]] raggruppate per edificio. * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Melilli/Melilli- Basilica di San Sebastiano|Basilica di San Sebastiano]] 35eewpgeqafoqruot4br5qkercnzzge Software libero a scuola/Pdf/PDFedit 0 60973 501053 2026-08-19T22:06:27Z ~2026-45514-04 54704 I found this useful pdf tool with 106 free tools 501053 wikitext text/x-wiki [https://allpdflove.com/en/ AllPDFLove] is an online PDF platform designed to make everyday document tasks faster and easier. Its collection of tools helps users '''convert, merge, split, compress, edit, and manage PDF files''' directly from a web browser without complicated software. Whether you need to turn a PDF into an editable document, reduce file size, extract pages, or work with different document formats, AllPDFLove brings essential PDF utilities together in one convenient place. The tools are built for simple, practical workflows, making them suitable for students, professionals, businesses, and anyone who regularly works with digital documents. 7zgy68m19a9gj48tib65lach3fewh1z Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Floridia 0 60974 501056 2026-08-19T22:13:49Z ~2026-45474-98 54699 Nuova pagina: {{Disposizioni foniche di organi a canne}} Disposizioni foniche del comune di [[w:Floridia|Floridia]] raggruppate per edificio. * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Floridia/Floridia- Chiesa Madre|Chiesa Madre]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Floridia/Floridia- Chiesa della Madonna del Carmine|Chiesa della Madonna del Carmine]] * Disposizioni foniche d... 501056 wikitext text/x-wiki {{Disposizioni foniche di organi a canne}} Disposizioni foniche del comune di [[w:Floridia|Floridia]] raggruppate per edificio. * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Floridia/Floridia- Chiesa Madre|Chiesa Madre]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Floridia/Floridia- Chiesa della Madonna del Carmine|Chiesa della Madonna del Carmine]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Floridia/Floridia- Chiesa di Sant'Anna|Chiesa di Sant'Anna]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Floridia/Floridia- Chiesa di Sant'Antonio|Chiesa di Sant'Antonio]] * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Floridia/Floridia- Chiesa di San Francesco D'Assisi|Chiesa di San Francesco D'Assisi]] gw6j1v5it88zs6b2ceh5rb0mbsktmci Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Sortino 0 60975 501057 2026-08-19T22:18:35Z ~2026-45474-98 54699 Nuova pagina: {{Disposizioni foniche di organi a canne}} Disposizioni foniche del comune di [[w:Sortino|Sortino]] raggruppate per edificio. * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Sortino/Sortino- Chiesa Madre di San Giovanni Apostolo ed Evangelista|Chiesa Madre di San Giovanni Apostolo ed Evangelista]] 501057 wikitext text/x-wiki {{Disposizioni foniche di organi a canne}} Disposizioni foniche del comune di [[w:Sortino|Sortino]] raggruppate per edificio. * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Sortino/Sortino- Chiesa Madre di San Giovanni Apostolo ed Evangelista|Chiesa Madre di San Giovanni Apostolo ed Evangelista]] 9sim6554li9rkspcka42thz8peutbcs Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Pachino 0 60976 501059 2026-08-19T22:23:34Z ~2026-45474-98 54699 Nuova pagina: {{Disposizioni foniche di organi a canne}} Disposizioni foniche del comune di [[w:Pachino|Pachino]] raggruppate per edificio. * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Pachino/Pachino- Chiesa Madre del Santissimo Crocifisso|Chiesa Madre del Santissimo Crocifisso]] 501059 wikitext text/x-wiki {{Disposizioni foniche di organi a canne}} Disposizioni foniche del comune di [[w:Pachino|Pachino]] raggruppate per edificio. * [[Disposizioni foniche di organi a canne/Italia/Sicilia/Libero consorzio comunale di Siracusa/Pachino/Pachino- Chiesa Madre del Santissimo Crocifisso|Chiesa Madre del Santissimo Crocifisso]] ebt412k0p4ox52r40p8srt0mx8iyowe