2014-12-24 15 views
5

Avviso: anche se il mio esempio proviene da OpenGL, questa non è una domanda OpenGL, ma una domanda generale D.Tipo di estrazione e offset dal campo struct nel modello

Sfondo: Nel mio progetto di gioco, ho una classe di shader per facilitare l'interfacciamento al codice GLSL. uniformi ambiente di lavoro ben:

uniform(string name, float value) --> glUniform1f(...) 
uniform(string name, mat4 m) --> glUniformMatrix4fv(...) 
etc. etc. 

Cioè, si sceglie la funzione destra a seconda del tipo di parametro, e così quando modifico il mio codice, si passa automaticamente a utilizzare la funzione corretta (supponendo che non ho tipo conflitti tra D e GLSL).

I miei problemi stanno implementando un meccanismo un po 'simile per legare gli attributi. Ho VERTICE struttura:

struct VERTEX { ...; vec3 pos; ... } 

per l'attributo vincolante, oltre a conoscere il tipo di campo, ho bisogno l'offset, ma non ho bisogno dei valori. Sono riuscito a scrivere implementazione clumpsy, dove chiamata appare come:

vbo.attrib!(typeof(mesh.VERTEX.pos))("vert_pos", mesh.VERTEX.pos.offsetof); 

E VBO.attrib è implementata in questo modo:

void attrib(T: vec2)(string name, ulong offset) { /* 2 floats from offset */ } 
void attrib(T: vec3)(string name, ulong offset) { /* 3 floats from offset */ } 

Domanda: C'è un modo per rendere questo più semplice ed elegante ? In genere, non mi piace duplicare il campo quando si chiama, ovvero estrarre prima il tipo per scegliere la corretta funzione di attributo di attributo, quindi inviare separatamente l'offset. Mi piacerebbe l'aspetto chiamata di funzione o meno così:

vbo.attrib("vert_pos", mesh.VERTEX.pos); 

... E il modello per estrarre sia il tipo e l'offset dall'argomento. Ho letto le guide dei modelli D e le esercitazioni, ma non ho ancora capito come implementare modelli del genere. È possibile e come?

Precisazione: Ho la sensazione che io sono già vicino, solo che non hanno abbastanza immaginazione (e la conoscenza da modelli D e mixins) per attuare la prima fase:

XXX(name, field) 
--> some unknown magic 
--> vbo.attrib!(typeof(field))(name,field.offsetof) 
--> void attrib(T: vec2)(string name, ulong offset) { /* arguments for GL call */ } 

EDIT: Con mixins, sono riuscito a far sembrare questo:

template attrib(string name, string field) 
    { 
     const char[] attrib = 
      "vbo.attrib!" ~ 
      "(typeof(" ~ field ~ "))" ~ 
      "(\"" ~ name ~ "\", " ~ field ~ ".offsetof);"; 
    } 

    mixin(attrib!("vert_pos", "mesh.VERTEX.pos")); 
    mixin(attrib!("vert_uv", "mesh.VERTEX.uv")); 

per essere onesti, (chiamata) sembra ancora più complesso da usare rispetto al mio attuale, quindi tengo la mia corrente e cerco una soluzione dall'aspetto più gradevole.

+0

Potrebbe essere sufficiente passare il nome come argomento modello, quindi utilizzare mixin o __traits (getMember) per ottenere l'offset e il tipo da esso e inoltrarlo alla chiamata della funzione di attributo. –

+0

Oppure un argomento alias: 'void attrib (campo alias) (nome stringa) {alias T = typeof (campo); auto offset = field.offsetof;/* resto del codice * /} 'Ma non sono sicuro che l'offsetof funzionerà effettivamente su un alias del genere. –

+0

blargh l'opzione alias ti permette di ottenere i dati, ma in realtà non chiama la funzione, si lamenta di aver bisogno di 'this'. :( –

risposta

5

siete davvero molto vicini alla soluzione. Questo funziona con DMD testa git:

import std.stdio; 

struct vec2 { 
    float a, b; 
} 

struct vec3 { 
    float a, b, c; 
} 

struct VERTEX { 
    vec3 pos; 
    vec2 uv; 
} 

void attrib(T: vec2) (string name, ulong offset) { 
    writefln("vec2: name=%s; ofs=%s", name, offset); 
} 

void attrib(T: vec3) (string name, ulong offset) { 
    writefln("vec3: name=%s; ofs=%s", name, offset); 
} 


static void attrib(string name, alias field)() { 
    attrib!(typeof(field))(name, field.offsetof); 
} 


void main() { 
    attrib!("vert_pos", VERTEX.pos); // outputs "vec3: name=vert_pos; ofs=0" 
    attrib!("vert_uv", VERTEX.uv); // outputs: "vec2: name=vert_uv; ofs=12" 
} 

purtroppo non ho 2.066 rilascio ufficiale per verificare se funziona con esso. questo sarà non funziona con 2.065 di sicuro, quindi sei fuori di fortuna con GDC (come ancora utilizzando 2.065).

il trucco è in static, che significa "questo modello non ha bisogno di alcun contesto".

p.s. appena controllato, e sì, funziona con 2.066 rilascio.

+1

Grazie mille! Sapevo che è possibile: D – MaKo

Problemi correlati