[Projekt] Polyblock-Editor

Hier könnt ihr euch selbst, eure Homepage, euren Entwicklerstammtisch, Termine oder eure Projekte vorstellen.
Forumsregeln
Bitte Präfixe benutzen. Das Präfix "[Projekt]" bewirkt die Aufnahme von Bildern aus den Beiträgen des Themenerstellers in den Showroom. Alle Bilder aus dem Thema Showroom erscheinen ebenfalls im Showroom auf der Frontpage. Es werden nur Bilder berücksichtigt, die entweder mit dem attachement- oder dem img-BBCode im Beitrag angezeigt werden.

Die Bildersammelfunktion muss manuell ausgeführt werden, die URL dazu und weitere Details zum Showroom sind hier zu finden.

This forum is primarily intended for German-language video game developers. Please don't post promotional information targeted at end users.
Antworten
joeydee
Establishment
Beiträge: 1039
Registriert: 23.04.2003, 15:29
Kontaktdaten:

[Projekt] Polyblock-Editor

Beitrag von joeydee »

Kleines Side-Projekt, das ich mal einigermaßen fertig gemacht habe.

Ursprungsgedanke war, Polygone per Maus in 2D bearbeiten zu können. Dann irgendwie tesselieren, und einfache World-Y-Extrusion per Parameter dazu (Bodenhöhe, Blockhöhe), und schon kann man einfache 3D-Umgebungen für Prototyping basteln. Ein bischen wie Doom1-Levelgeometrie, mehr oder weniger.

Beim "irgendwie tesselieren" kam ich zwischenzeitlich darauf, dass es ja sowieso sehr einfache Polys bleiben, und es wohl reichen dürfte, den Startpunkt für einen Fan manuell festlegen zu können.
poly3.jpg
Dadurch kann man, wie im Bild zu sehen, einfache konkave Polygone ohne viel Tamtam dahinter tesselieren. Ich rendere die Polys transparent und mit Dreieckslinien bei selektiertem Polygon, d.h. man sieht sofort wo was nicht passt und kann andere Startpunkte ausprobieren.

Beispielszenen, im Download mit dabei:
poly01.jpg
poly02.jpg
Bedienung:
In 3D kann man nur betrachten. Kein Dolly, sondern WASD2X + Maus.
Im 2D-Canvas:
- MMB + Mousewheel: Pan und Zoom.
- Linien/Punkte/Polygone anfassen, verschieben, löschen. Wenn man ein kleines Poly verschieben möchte, aber erwischt immer nur Punkte oder Linien: ranzoomen.
- STRG+Klick für neue Punkte. Wenn ein Poly markiert ist, wird dort ein neuer Punkt eingefügt. Ansonsten ein neues Poly begonnen. Polyorder wird automatisch korrigiert, da muss man nichts beachten.
- Wenn man mal an ein Poly nicht mehr ran kommt: das darüberliegende markieren und "send to back".
- Selektiertes Polygon: ALT+verschieben=Duplizieren; R=Rotate (90°), M=Mirror.
- Doppelklick auf einen Punkt: von diesem aus neu tesselieren.
Man kann nur im Raster und Ganzzahlen arbeiten.
Höhe wird vom letzten markierten Block beibehalten, Boden wird je nach Mausposition beim Erstellen ermittelt, aber nicht beim Verschieben geändert.

Was NICHT geht:
Undo, zerschneiden, frei drehen, Rampen bauen, gruppieren, Multiselektion, texturieren, einfärben, Warnungen wenn man nicht gespeichert hat bei clear/load/quit, usw.
Es ist halt wirklich nur für schnelle kleine Protoszenen gedacht, wenn man mal schnell was bauen, aber keinen ausgewachsenen 3D-Editor bedienen möchte. Daher habe ich manche Features, welche die Bedienung komplexer machen würden, erstmal weggelassen. Aber ein paar Sachen kommen sicher mit der Zeit dazu.

Exportformate:
- Das native Format ist binär. Doku lohnt sichjetzt nicht, weil:
- txt ist im Prinzip dasselbe, nur lesbar und selbsterklärend. Für eigene Anwendungen.
- tris ist nur Geometrie als rohe Dreiecksliste, unique Vertices, keine Indices.
- obj ist ebenfalls im Textformart, mit indizierten Vertices, zum Weiterarbeiten in 3D-Software. Ob konkave Polygone richtig tesseliert werden, hängt dann vom Programm ab. In Blender hatten erste Versuche geklappt, in Cura ebenfalls.
Ich möchte nicht ausschließen, dass ich bei dem ein oder anderen Export noch einen Fehler drin habe, ist alles nicht auf Herz und Nieren geprüft.

Es gibt ein paar experimentelle Features, z.B. wenn man bei type "trigger" oder "path" eintippt, werden diese anders dargstellt. Ist mal gedacht als kleiner Levelbuilder, wo man dann die Polyblöcke als einfache Collider weiterbenutzen, aber am Ende andere Geometrie hinterlegen kann.

Ich dachte ich werfs einfach mal im aktuellen Zustand in die Runde:
Polyblocks01.zip
(4.12 MiB) 21-mal heruntergeladen
Mirror
Establishment
Beiträge: 248
Registriert: 25.08.2019, 05:00
Alter Benutzername: gdsWizard
Kontaktdaten:

Re: [Projekt] Polyblock-Editor

Beitrag von Mirror »

Ich finde das sieht schon ziemlich gut aus. Ein brauchbarer Editor, auch wenn noch ein paar Features, wie sie selber bemerkten, noch fehlen. Ich hoffe ich kriege mit meinem Editor auch mal sowas hin.
Hat den StormWizard 1.0 und 2.0 verbrochen. http://www.mirrorcad.com
joeydee
Establishment
Beiträge: 1039
Registriert: 23.04.2003, 15:29
Kontaktdaten:

Re: [Projekt] Polyblock-Editor

Beitrag von joeydee »

thx :)
Kleiner Bug: Wenn man gerade eine Line oder Punkt selektiert hatte, dann auf den Hintergrund klickt (ohne STRG) um die Auswahl aufzuheben, dann ein neues Poly mit STRG beginnen möchte, geht das nicht. Abhilfe: Ein ganzes Poly selektieren, dann aufden Hintergrund klicken.
State-Hölle, es gibt bei sowas mehr Zustände auf die man unterschiedlich reagieren muss als man dem Ganzen ansieht.
joeydee
Establishment
Beiträge: 1039
Registriert: 23.04.2003, 15:29
Kontaktdaten:

Re: [Projekt] Polyblock-Editor

Beitrag von joeydee »

Ich werfe auch noch ein paar (Pseudo)Codesnippets und weitere Infos in die Runde, die hilfreich sein könnten wenn man das für eigene Projekte ausprobieren möchte.

Datentyp für einen Block:

Code: Alles auswählen

    
    class PolyBlock
        public string name = "";
        public string type = "";
        public float bottom = 0;
        public float height = 1;
        public List<Vector2> verts = new List<Vector2>();

Textformat im Vergleich dazu:

Code: Alles auswählen

//POLYBLOCK SCENE
numBlocks 2

//POLYBLOCK
name 
type 
bottom  000
height  003
numVerts 9
 010  020    009  026    001  026   -004  020
-004  012    008  007    017  008    018  012
 024  020

//POLYBLOCK
name bla
type blub
bottom  000
height  007
numVerts 7
-001  007   -015  024   -009  010   -017 -011
-001  001    011 -007    018  003

//EOF
Das native Binärformat ist nicht wesentlich anders, allerdings Float-basiert. Außerdem: Die vec2 werden als 4 floats x,y,0,1 geschrieben, aber nur die ersten beiden Komponenten sind in dieser Version relevant. (WriteVec() == 4x writeFloat())

Code: Alles auswählen

            
            stream.writeString(name);
            stream.writeString(type);
            stream.writeFloat(bottom);
            stream.writeFloat(height);
            stream.writeInt(verts.Count);
            foreach (var vert in verts) stream.writeVec(new Vector4(vert.X, vert.Y, 0, 1));
Triangulate, zum Rendern.
Ist extruded auf false, wird nur das Polygon zurückgegeben. Ansonsten der Block mit Seitenwänden, Boden und Deckel.
X,Y wird zu X,-Z, da bei mir +X=rechts, +Y=oben, +Z=vorn in 3D.

Code: Alles auswählen

        public List<Vector3> triangulate(bool extruded)
        {
            List<Vector3> tris = new List<Vector3>();
            int n = verts.Count;
            float bt = extruded ? bottom : 0;
            Vector3 v0 = new Vector3(verts[0].X, bt, -verts[0].Y);
            Vector3 vh = new Vector3(0, extruded?height:0, 0);

            //surfaces
            for (int i = 2; i < n; i++)
            {
                Vector3 v1 = new Vector3(verts[i - 1].X, bt, -verts[i - 1].Y);
                Vector3 v2 = new Vector3(verts[i].X, bt, -verts[i].Y);
                //bottom
                if (extruded)
                {
                    tris.Add(v0);
                    tris.Add(v2);
                    tris.Add(v1);
                }
                //top
                tris.Add(v0 + vh);
                tris.Add(v1 + vh);
                tris.Add(v2 + vh);
            }

            //sides
            if (extruded)
            {
                for (int i = 0; i < n; i++)
                {
                    Vector3 v1 = new Vector3(verts[i].X, bt, -verts[i].Y);
                    Vector3 v2 = new Vector3(verts[(i + 1) % n].X, bt, -verts[(i + 1) % n].Y);
                    tris.Add(v1);
                    tris.Add(v2);
                    tris.Add(v2 + vh);
                    tris.Add(v2 + vh);
                    tris.Add(v1 + vh);
                    tris.Add(v1);
                }
            }
            return tris;
        }
Demnächst kommen noch Snippets zu:
- 2D-Picking (point inside poly?)
- 3D-Kollisionserkennung (Kugel vs. Block)
- Response (Kontaktnormale)
Antworten