Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion examples/jsm/transpiler/AST.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export class Program extends ASTNode {

export class VariableDeclaration extends ASTNode {

constructor( type, name, value = null, next = null, immutable = false ) {
constructor( type, name, value = null, next = null, immutable = false, isUserDefinedStructType = false ) {

super();

Expand All @@ -136,6 +136,8 @@ export class VariableDeclaration extends ASTNode {

this.immutable = immutable;

this.isUserDefinedStructType = isUserDefinedStructType;

this.isVariableDeclaration = true;

this.initialize();
Expand Down Expand Up @@ -629,3 +631,32 @@ export class SwitchCase extends ASTNode {
}

}

// helper class for StructDefinition
export class StructMember {

constructor( type, name ) {

this.type = type;
this.name = name;
this.isStructMember = true;

}

}

export class StructDefinition extends ASTNode {

constructor( name, members = [] ) {

super();

this.name = name;
this.members = members;
this.isStructDefinition = true;

this.initialize();

}

}
59 changes: 54 additions & 5 deletions examples/jsm/transpiler/GLSLDecoder.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Program, FunctionDeclaration, Switch, For, AccessorElements, Ternary, Varying, DynamicElement, StaticElement, FunctionParameter, Unary, Conditional, VariableDeclaration, Operator, Number, String, FunctionCall, Return, Accessor, Uniform, Discard, SwitchCase, Continue, Break, While, Comment } from './AST.js';
import { Program, FunctionDeclaration, Switch, For, AccessorElements, Ternary, Varying, DynamicElement, StaticElement, FunctionParameter, Unary, Conditional, VariableDeclaration, Operator, Number, String, FunctionCall, Return, Accessor, Uniform, Discard, SwitchCase, Continue, Break, While, Comment, StructMember, StructDefinition } from './AST.js';

import { isType } from './TranspilerUtils.js';
import { isBuiltinType } from './TranspilerUtils.js';

const unaryOperators = [
'+', '-', '~', '!', '++', '--'
Expand Down Expand Up @@ -255,6 +255,7 @@ class GLSLDecoder {
this.index = 0;
this.tokenizer = null;
this.keywords = [];
this.userDefinedStructTypes = new Set();

this.addPolyfill( 'gl_FragCoord', 'vec3 gl_FragCoord = vec3( screenCoordinate.x, screenCoordinate.y.oneMinus(), screenCoordinate.z );' );

Expand Down Expand Up @@ -708,6 +709,7 @@ class GLSLDecoder {
if ( immutable ) index ++;

type = type || tokens[ index ++ ].str;
const isUserDefinedStructType = this.userDefinedStructTypes.has(type);
const name = tokens[ index ++ ].str;

const token = tokens[ index ];
Expand Down Expand Up @@ -738,7 +740,7 @@ class GLSLDecoder {

}

const variable = new VariableDeclaration( type, name, init, next, immutable );
const variable = new VariableDeclaration( type, name, init, next, immutable, isUserDefinedStructType );

return variable;

Expand Down Expand Up @@ -780,6 +782,48 @@ class GLSLDecoder {

}

parseStructDefinition() {

const tokens = this.readTokensUntil( ';' );

const structName = tokens[ 1 ].str;
this.userDefinedStructTypes.add(structName);

if (tokens[ 2 ].str !== '{' ) {

throw new Error( 'Expected \'{\' after struct name ' );

}

const structMembers = [];
for ( let i = 3; i < tokens.length - 2; i += 3 ) {

const typeToken = tokens[ i ];
const nameToken = tokens[ i + 1 ];

if (typeToken.type != 'literal' || nameToken.type != 'literal') {
throw new Error( 'Invalid struct declaration' );
}

if (tokens[ i + 2 ].str !== ';' ) {
throw new Error( 'Missing \';\' after struct member name' );
}

const member = new StructMember(typeToken.str, nameToken.str);
structMembers.push(member);

}

if (tokens[ tokens.length - 2 ].str !== '}' ) {

throw new Error( 'Missing closing \'}\' for struct ' + structName );

}

return new StructDefinition(structName, structMembers);

}

parseReturn() {

this.readToken(); // skip 'return'
Expand Down Expand Up @@ -827,7 +871,8 @@ class GLSLDecoder {

let initialization;

if ( initializationTokens[ 0 ] && isType( initializationTokens[ 0 ].str ) ) {
const firstToken = initializationTokens[ 0 ];
if ( firstToken && ( isBuiltinType( firstToken.str ) || this.userDefinedStructTypes.has( firstToken.str ) ) ) {

initialization = this.parseVariablesFromToken( initializationTokens );

Expand Down Expand Up @@ -1079,7 +1124,11 @@ class GLSLDecoder {

statement = this.parseVarying();

} else if ( isType( token.str ) ) {
} else if ( token.str === 'struct' ) {

statement = this.parseStructDefinition();

} else if ( isBuiltinType( token.str ) || this.userDefinedStructTypes.has( token.str ) ) {

if ( this.getToken( 2 ).str === '(' ) {

Expand Down
41 changes: 39 additions & 2 deletions examples/jsm/transpiler/TSLEncoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,10 @@ class TSLEncoder {

code = this.emitVarying( node );

} else if ( node.isStructDefinition ) {

code = this.emitStructDefinition( node );

} else if ( node.isTernary ) {

code = this.emitTernary( node );
Expand Down Expand Up @@ -669,9 +673,17 @@ ${ this.tab }} )`;

} else {

varStr += ` = property( '${ type }' )`;
if ( node.isUserDefinedStructType ) {

varStr += ` = ${type}()`;

} else {

varStr += ` = property( '${ type }' )`;

this.addImport( 'property' );
this.addImport( 'property' );

}

}

Expand Down Expand Up @@ -702,6 +714,31 @@ ${ this.tab }} )`;

}

emitStructDefinition( node ) {

const { name, members } = node;

this.addImport( 'struct' );

let structString = `const ${ name } = struct({\n\n`;

for ( let i = 0; i < members.length; i += 1 ) {

const member = members[i];

structString += `${this.tab}\t${member.name}: '${member.type}'`;

const delimiter = (i != members.length - 1) ? ',\n' : '\n';
structString += delimiter;

}

structString += `\n${this.tab}}, \'${name}\' )`;

return structString;

}

emitOverloadingFunction( nodes ) {

const { name } = nodes[ 0 ];
Expand Down
4 changes: 2 additions & 2 deletions examples/jsm/transpiler/TranspilerUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ export function isPrimitive( value ) {

}

export function isType( str ) {
export function isBuiltinType( str ) {

return /void|bool|float|u?int|mat[234]|mat[234]x[234]|(u|i|b)?vec[234]/.test( str );
return /^(void|bool|float|u?int|mat[234]|mat[234]x[234]|(u|i|b)?vec[234])$/.test( str );

}

Expand Down