mirror of https://github.com/buggins/dlangui.git
fbx import, initial version
This commit is contained in:
parent
35ee4fbb99
commit
22f9b7a8c7
|
@ -284,6 +284,7 @@
|
||||||
<Compile Include="src\dlangui\graphics\scene\camera.d" />
|
<Compile Include="src\dlangui\graphics\scene\camera.d" />
|
||||||
<Compile Include="src\dlangui\graphics\scene\drawableobject.d" />
|
<Compile Include="src\dlangui\graphics\scene\drawableobject.d" />
|
||||||
<Compile Include="src\dlangui\graphics\scene\effect.d" />
|
<Compile Include="src\dlangui\graphics\scene\effect.d" />
|
||||||
|
<Compile Include="src\dlangui\graphics\scene\fbximport.d" />
|
||||||
<Compile Include="src\dlangui\graphics\scene\light.d" />
|
<Compile Include="src\dlangui\graphics\scene\light.d" />
|
||||||
<Compile Include="src\dlangui\graphics\scene\material.d" />
|
<Compile Include="src\dlangui\graphics\scene\material.d" />
|
||||||
<Compile Include="src\dlangui\graphics\scene\mesh.d" />
|
<Compile Include="src\dlangui\graphics\scene\mesh.d" />
|
||||||
|
|
|
@ -143,6 +143,7 @@
|
||||||
<Compile Include="src\dlangui\graphics\scene\camera.d" />
|
<Compile Include="src\dlangui\graphics\scene\camera.d" />
|
||||||
<Compile Include="src\dlangui\graphics\scene\drawableobject.d" />
|
<Compile Include="src\dlangui\graphics\scene\drawableobject.d" />
|
||||||
<Compile Include="src\dlangui\graphics\scene\effect.d" />
|
<Compile Include="src\dlangui\graphics\scene\effect.d" />
|
||||||
|
<Compile Include="src\dlangui\graphics\scene\fbximport.d" />
|
||||||
<Compile Include="src\dlangui\graphics\scene\light.d" />
|
<Compile Include="src\dlangui\graphics\scene\light.d" />
|
||||||
<Compile Include="src\dlangui\graphics\scene\material.d" />
|
<Compile Include="src\dlangui\graphics\scene\material.d" />
|
||||||
<Compile Include="src\dlangui\graphics\scene\mesh.d" />
|
<Compile Include="src\dlangui\graphics\scene\mesh.d" />
|
||||||
|
|
|
@ -775,6 +775,7 @@
|
||||||
<File path="src\dlangui\graphics\scene\camera.d" />
|
<File path="src\dlangui\graphics\scene\camera.d" />
|
||||||
<File path="src\dlangui\graphics\scene\drawableobject.d" />
|
<File path="src\dlangui\graphics\scene\drawableobject.d" />
|
||||||
<File path="src\dlangui\graphics\scene\effect.d" />
|
<File path="src\dlangui\graphics\scene\effect.d" />
|
||||||
|
<File path="src\dlangui\graphics\scene\fbximport.d" />
|
||||||
<File path="src\dlangui\graphics\scene\light.d" />
|
<File path="src\dlangui\graphics\scene\light.d" />
|
||||||
<File path="src\dlangui\graphics\scene\material.d" />
|
<File path="src\dlangui\graphics\scene\material.d" />
|
||||||
<File path="src\dlangui\graphics\scene\mesh.d" />
|
<File path="src\dlangui\graphics\scene\mesh.d" />
|
||||||
|
|
|
@ -8,8 +8,9 @@ import dlangui.graphics.scene.material;
|
||||||
import dlangui.graphics.scene.effect;
|
import dlangui.graphics.scene.effect;
|
||||||
import dlangui.graphics.scene.model;
|
import dlangui.graphics.scene.model;
|
||||||
import dlangui.graphics.scene.node;
|
import dlangui.graphics.scene.node;
|
||||||
import dlangui.graphics.scene.objimport;
|
|
||||||
import dlangui.graphics.scene.light;
|
import dlangui.graphics.scene.light;
|
||||||
|
import dlangui.graphics.scene.objimport;
|
||||||
|
import dlangui.graphics.scene.fbximport;
|
||||||
import dlangui.graphics.glsupport;
|
import dlangui.graphics.glsupport;
|
||||||
import dlangui.graphics.gldrawbuf;
|
import dlangui.graphics.gldrawbuf;
|
||||||
import derelict.opengl3.gl3;
|
import derelict.opengl3.gl3;
|
||||||
|
@ -121,8 +122,8 @@ class UiWidget : VerticalLayout, CellVisitor {
|
||||||
dirLightNode.translateX(2);
|
dirLightNode.translateX(2);
|
||||||
dirLightNode.translateY(3);
|
dirLightNode.translateY(3);
|
||||||
dirLightNode.translateZ(3);
|
dirLightNode.translateZ(3);
|
||||||
//dirLightNode.light = Light.createPoint(vec3(1, 0.5, 0.5), 15); //Light.createDirectional(vec3(1, 0.5, 0.5));
|
dirLightNode.light = Light.createPoint(vec3(1, 0.5, 0.5), 15); //Light.createDirectional(vec3(1, 0.5, 0.5));
|
||||||
dirLightNode.light = Light.createDirectional(vec3(1, 0.5, 0.8));
|
//dirLightNode.light = Light.createDirectional(vec3(1, 0.5, 0.8));
|
||||||
dirLightNode.light.enabled = true;
|
dirLightNode.light.enabled = true;
|
||||||
_scene.addChild(dirLightNode);
|
_scene.addChild(dirLightNode);
|
||||||
|
|
||||||
|
@ -147,13 +148,21 @@ class UiWidget : VerticalLayout, CellVisitor {
|
||||||
Node3d cubeNode = new Node3d("cubes", cubeDrawable);
|
Node3d cubeNode = new Node3d("cubes", cubeDrawable);
|
||||||
_scene.addChild(cubeNode);
|
_scene.addChild(cubeNode);
|
||||||
|
|
||||||
|
{
|
||||||
|
// test FBX import
|
||||||
|
FbxModelImport importer;
|
||||||
|
string src = loadTextResource("suzanne.fbx");
|
||||||
|
importer.filename = "suzanne.fbx";
|
||||||
|
importer.parse(src);
|
||||||
|
}
|
||||||
|
|
||||||
ObjModelImport importer;
|
ObjModelImport importer;
|
||||||
string src = loadTextResource("suzanne.obj");
|
string src = loadTextResource("suzanne.obj");
|
||||||
importer.parse(src);
|
importer.parse(src);
|
||||||
Log.d("suzanne mesh:", importer.mesh.dumpVertexes(20));
|
Log.d("suzanne mesh:", importer.mesh.dumpVertexes(20));
|
||||||
Material suzanneMaterial = new Material(EffectId("colored.vert", "colored.frag", null), null); //"SPECULAR"
|
Material suzanneMaterial = new Material(EffectId("colored.vert", "colored.frag", null), null); //"SPECULAR"
|
||||||
//suzanneMaterial.ambientColor = vec3(0.5, 0.5, 0.5);
|
//suzanneMaterial.ambientColor = vec3(0.5, 0.5, 0.5);
|
||||||
suzanneMaterial.diffuseColor = vec4(1.0, 0.7, 0.5, 1.0);
|
suzanneMaterial.diffuseColor = vec4(0.7, 0.7, 0.5, 1.0);
|
||||||
//suzanneMaterial.specular = true;
|
//suzanneMaterial.specular = true;
|
||||||
Model suzanneDrawable = new Model(suzanneMaterial, importer.mesh);
|
Model suzanneDrawable = new Model(suzanneMaterial, importer.mesh);
|
||||||
suzanneNode = new Node3d("suzanne", suzanneDrawable);
|
suzanneNode = new Node3d("suzanne", suzanneDrawable);
|
||||||
|
@ -364,8 +373,8 @@ class UiWidget : VerticalLayout, CellVisitor {
|
||||||
//projectionViewModelMatrix.setIdentity();
|
//projectionViewModelMatrix.setIdentity();
|
||||||
//Log.d("matrix uniform: ", projectionViewModelMatrix.m);
|
//Log.d("matrix uniform: ", projectionViewModelMatrix.m);
|
||||||
|
|
||||||
//checkgl!glEnable(GL_CULL_FACE);
|
checkgl!glEnable(GL_CULL_FACE);
|
||||||
checkgl!glDisable(GL_CULL_FACE);
|
//checkgl!glDisable(GL_CULL_FACE);
|
||||||
checkgl!glEnable(GL_DEPTH_TEST);
|
checkgl!glEnable(GL_DEPTH_TEST);
|
||||||
checkgl!glCullFace(GL_BACK);
|
checkgl!glCullFace(GL_BACK);
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -5,6 +5,7 @@ res/mdpi/tx_fabric.jpg
|
||||||
res/mdpi/crate.png
|
res/mdpi/crate.png
|
||||||
res/mdpi/blocks.png
|
res/mdpi/blocks.png
|
||||||
res/models/suzanne.obj
|
res/models/suzanne.obj
|
||||||
|
res/models/suzanne.fbx
|
||||||
res/shaders/colored.vert
|
res/shaders/colored.vert
|
||||||
res/shaders/colored.frag
|
res/shaders/colored.frag
|
||||||
res/shaders/lighting.vert
|
res/shaders/lighting.vert
|
||||||
|
|
|
@ -477,13 +477,19 @@ class Tokenizer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// tokenize source into array of tokens (excluding EOF)
|
/// tokenize source into array of tokens (excluding EOF)
|
||||||
public Token[] tokenize(string code, string[] _singleLineCommentPrefixes = ["//"]) {
|
public Token[] tokenize(string code, string[] _singleLineCommentPrefixes = ["//"], bool skipSpace = false, bool skipEols = false, bool skipComments = false) {
|
||||||
Token[] res;
|
Token[] res;
|
||||||
auto tokenizer = new Tokenizer(code, "");
|
auto tokenizer = new Tokenizer(code, "", _singleLineCommentPrefixes);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto token = tokenizer.nextToken();
|
auto token = tokenizer.nextToken();
|
||||||
if (token.type == TokenType.eof)
|
if (token.type == TokenType.eof)
|
||||||
break;
|
break;
|
||||||
|
if (skipSpace && token.type == TokenType.whitespace)
|
||||||
|
continue;
|
||||||
|
if (skipEols && token.type == TokenType.eol)
|
||||||
|
continue;
|
||||||
|
if (skipComments && token.type == TokenType.comment)
|
||||||
|
continue;
|
||||||
res ~= token;
|
res ~= token;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -1172,3 +1172,21 @@ class DrawableCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// load text resource
|
||||||
|
string loadTextResource(string resourceId) {
|
||||||
|
import dlangui.graphics.resources;
|
||||||
|
import std.string : endsWith;
|
||||||
|
string filename;
|
||||||
|
filename = drawableCache.findResource(resourceId);
|
||||||
|
if (!filename) {
|
||||||
|
Log.e("Object resource file not found for resourceId ", resourceId);
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
string s = cast(string)loadResourceBytes(filename);
|
||||||
|
if (!s) {
|
||||||
|
Log.e("Cannot read text resource ", resourceId, " from file ", filename);
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,181 @@
|
||||||
|
module dlangui.graphics.scene.fbximport;
|
||||||
|
|
||||||
|
import dlangui.core.logger;
|
||||||
|
import dlangui.core.math3d;
|
||||||
|
import dlangui.dml.tokenizer;
|
||||||
|
import dlangui.graphics.scene.mesh;
|
||||||
|
|
||||||
|
struct FbxModelImport {
|
||||||
|
Token[] tokens;
|
||||||
|
ParseState[] stateStack;
|
||||||
|
ParseState state;
|
||||||
|
string filename;
|
||||||
|
static class ParseState {
|
||||||
|
string paramName;
|
||||||
|
Token[] literalParams;
|
||||||
|
Token[] additionalLiteralParams;
|
||||||
|
this(string name) {
|
||||||
|
paramName = name;
|
||||||
|
}
|
||||||
|
void addLiteral(Token token) {
|
||||||
|
literalParams ~= token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected void pushState(ParseState state) {
|
||||||
|
stateStack ~= state;
|
||||||
|
this.state = state;
|
||||||
|
Log.d("pushState:[", stateStack.length, "] name=", state.paramName);
|
||||||
|
}
|
||||||
|
protected ParseState popState() {
|
||||||
|
if (!state || stateStack.length < 1)
|
||||||
|
error("stack is empty");
|
||||||
|
Log.d("popState: [", stateStack.length, "] name=", state.paramName, " params:", state.literalParams, " addParams: ", state.additionalLiteralParams );
|
||||||
|
stateStack.length = stateStack.length - 1;
|
||||||
|
state = stateStack.length ? stateStack[$ - 1] : null;
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
protected bool matchTypes(TokenType t1, TokenType t2) {
|
||||||
|
return (tokens.length > 1 && tokens[0].type == t1 && tokens[1].type == t2);
|
||||||
|
}
|
||||||
|
protected bool skip(int count) {
|
||||||
|
if (count >= tokens.length) {
|
||||||
|
tokens = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tokens = tokens[count .. $];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
protected string parseParamName() {
|
||||||
|
if (matchParamName()) {
|
||||||
|
string name = tokens[0].text;
|
||||||
|
skip(2);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
protected bool matchParamName() {
|
||||||
|
return matchTypes(TokenType.ident, TokenType.colon);
|
||||||
|
}
|
||||||
|
protected void error(string msg) {
|
||||||
|
if (tokens.length)
|
||||||
|
throw new ParserException(msg, filename, tokens[0].line, tokens[0].pos);
|
||||||
|
throw new ParserException(msg, filename, tokens[0].line, tokens[0].pos);
|
||||||
|
}
|
||||||
|
// current token is {, parse till matching }
|
||||||
|
protected void parseObject() {
|
||||||
|
if (!skip(1))
|
||||||
|
error("unexpected eof");
|
||||||
|
pushState(new ParseState(null));
|
||||||
|
for (;;) {
|
||||||
|
if (string name = parseParamName()) {
|
||||||
|
parseParam(name);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!tokens.length)
|
||||||
|
error("eof while looking for }");
|
||||||
|
if (tokens[0].type != TokenType.curlyClose)
|
||||||
|
error("} expected");
|
||||||
|
skip(1);
|
||||||
|
popState();
|
||||||
|
}
|
||||||
|
protected Token[] parseLiteralList() {
|
||||||
|
Token[] res;
|
||||||
|
if (!tokens.length)
|
||||||
|
error("unexpected eof");
|
||||||
|
Token t = tokens[0];
|
||||||
|
while (t.type == TokenType.str || t.type == TokenType.integer || t.type == TokenType.floating || t.type == TokenType.minus || (t.type == TokenType.ident && !matchParamName())) {
|
||||||
|
// unary minus handling
|
||||||
|
if (t.type == TokenType.minus) {
|
||||||
|
if (!skip(1))
|
||||||
|
error("Unexpected eof");
|
||||||
|
t = tokens[0];
|
||||||
|
if (t.type == TokenType.integer)
|
||||||
|
t.intvalue = -t.intvalue;
|
||||||
|
else if (t.type == TokenType.floating)
|
||||||
|
t.floatvalue = -t.floatvalue;
|
||||||
|
else
|
||||||
|
error("number expected");
|
||||||
|
}
|
||||||
|
res ~= t;
|
||||||
|
if (!skip(1)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
t = tokens[0];
|
||||||
|
if (t.type != TokenType.comma)
|
||||||
|
break;
|
||||||
|
if (!skip(1))
|
||||||
|
error("Unexpected eof");
|
||||||
|
t = tokens[0];
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
protected void parseParam(string name) {
|
||||||
|
pushState(new ParseState(name));
|
||||||
|
if (!tokens.length)
|
||||||
|
error("unexpected eof");
|
||||||
|
if (matchParamName()) {
|
||||||
|
// next param
|
||||||
|
popState();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// process non-named parameter list
|
||||||
|
Token t = tokens[0];
|
||||||
|
if (t.type == TokenType.str || t.type == TokenType.integer || t.type == TokenType.floating || t.type == TokenType.minus || (t.type == TokenType.ident && !matchParamName())) {
|
||||||
|
state.literalParams = parseLiteralList();
|
||||||
|
if (!tokens.length) {
|
||||||
|
popState();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
t = tokens[0];
|
||||||
|
}
|
||||||
|
if (t.type == TokenType.curlyOpen) {
|
||||||
|
parseObject();
|
||||||
|
if (tokens.length) {
|
||||||
|
t = tokens[0];
|
||||||
|
if (t.type == TokenType.comma) {
|
||||||
|
// additional params
|
||||||
|
if (!skip(1))
|
||||||
|
error("unexpected eof");
|
||||||
|
t = tokens[0];
|
||||||
|
if (t.type == TokenType.str || t.type == TokenType.integer || t.type == TokenType.floating || t.type == TokenType.minus || (t.type == TokenType.ident && !matchParamName())) {
|
||||||
|
state.additionalLiteralParams = parseLiteralList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
popState();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (matchParamName() || t.type == TokenType.curlyClose) {
|
||||||
|
// next param
|
||||||
|
popState();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
error("parameter name expected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected bool parseAll() {
|
||||||
|
while (tokens.length) {
|
||||||
|
if (string name = parseParamName()) {
|
||||||
|
parseParam(name);
|
||||||
|
} else {
|
||||||
|
if (tokens.length)
|
||||||
|
error("Parameter name expected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool parse(string source) {
|
||||||
|
import dlangui.dml.tokenizer;
|
||||||
|
try {
|
||||||
|
tokens = tokenize(source, [";"], true, true, true);
|
||||||
|
return parseAll();
|
||||||
|
} catch (ParserException e) {
|
||||||
|
Log.d("failed to tokenize OBJ source", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -264,20 +264,3 @@ struct ObjModelImport {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// load text resource
|
|
||||||
string loadTextResource(string resourceId) {
|
|
||||||
import dlangui.graphics.resources;
|
|
||||||
import std.string : endsWith;
|
|
||||||
string filename;
|
|
||||||
filename = drawableCache.findResource(resourceId);
|
|
||||||
if (!filename) {
|
|
||||||
Log.e("Object resource file not found for resourceId ", resourceId);
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
string s = cast(string)loadResourceBytes(filename);
|
|
||||||
if (!s) {
|
|
||||||
Log.e("Cannot read shader source resource ", resourceId, " from file ", filename);
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue