Scene3d: OBJ import

This commit is contained in:
Vadim Lopatin 2016-04-01 10:11:33 +03:00
parent 7fc9dd9495
commit 52fbe8a38f
6 changed files with 171 additions and 5 deletions

View File

@ -0,0 +1,7 @@
uniform sampler2D tex;
in vec4 col;
out vec4 outColor;
void main(void)
{
outColor = col;
}

View File

@ -0,0 +1,9 @@
in vec4 vertex;
in vec4 colAttr;
out vec4 col;
uniform mat4 matrix;
void main(void)
{
gl_Position = matrix * vertex;
col = colAttr;
}

View File

@ -4,6 +4,8 @@ res/mdpi/cr3_logo.png
res/mdpi/tx_fabric.jpg
res/mdpi/crate.png
res/mdpi/blocks.png
res/models/suzanne.obj
res/shaders/colored.vert
res/shaders/colored.frag
res/shaders/textured.vert
res/shaders/textured.frag
res/models/suzanne.obj

View File

@ -22,6 +22,12 @@ struct vec2 {
this(float[2] v) {
vec = v;
}
this(float[] v) {
vec = v[0..2];
}
this(float * v) {
vec = v[0..2];
}
this(const vec2 v) {
vec = v.vec;
}
@ -258,6 +264,12 @@ struct vec3 {
this(float[3] v) {
vec = v;
}
this(float[] v) {
vec = v[0..3];
}
this(float * v) {
vec = v[0..3];
}
this(const vec3 v) {
vec = v.vec;
}
@ -1581,3 +1593,13 @@ unittest {
m.rotateY(10);
m.rotateZ(10);
}
/// calculate normal for triangle
vec3 triangleNormal(vec3 p1, vec3 p2, vec3 p3) {
return vec3.crossProduct(p2 - p1, p3 - p2).normalized();
}
/// calculate normal for triangle
vec3 triangleNormal(float[3] p1, float[3] p2, float[3] p3) {
return vec3.crossProduct(vec3(p2) - vec3(p1), vec3(p3) - vec3(p2)).normalized();
}

View File

@ -27,7 +27,7 @@ abstract class GraphicsEffect : RefCountedObject {
/// vertex element type
enum VertexElementType : ubyte {
POSITION = 1,
POSITION = 0,
NORMAL,
COLOR,
TEXCOORD0,
@ -40,6 +40,8 @@ enum VertexElementType : ubyte {
TEXCOORD7,
}
static assert(VertexElementType.max == VertexElementType.TEXCOORD7);
/// Graphics primitive type
enum PrimitiveType : int {
triangles,
@ -98,21 +100,61 @@ struct VertexElement {
/// Vertex format elements list
struct VertexFormat {
private VertexElement[] _elements;
private byte[VertexElementType.max + 1] _elementOffset = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1];
private int _vertexSize;
/// make using element list
this(inout VertexElement[] elems...) {
_elements = elems.dup;
foreach(elem; elems)
foreach(elem; elems) {
_elementOffset[elem.type] = cast(byte)(_vertexSize / float.sizeof);
_vertexSize += elem.size * float.sizeof;
}
}
/// init from vertex element types, using default sizes for types
this(inout VertexElementType[] types...) {
foreach(t; types) {
_elementOffset[t] = cast(byte)(_vertexSize / float.sizeof);
VertexElement elem = VertexElement(t);
_elements ~= elem;
_vertexSize += elem.size;
}
}
int elementOffset(VertexElementType type) const {
return _elementOffset[type];
}
bool hasElement(VertexElementType type) const {
return _elementOffset[type] >= 0;
}
/// set vec2 component value of vertex
void set(float * vertex, VertexElementType type, vec2 value) const {
int start = _elementOffset[type];
if (start >= 0) {
vertex += start;
vertex[0] = value.vec[0];
vertex[1] = value.vec[1];
}
}
/// set vec3 component value of vertex
void set(float * vertex, VertexElementType type, vec3 value) const {
int start = _elementOffset[type];
if (start >= 0) {
vertex += start;
vertex[0] = value.vec[0];
vertex[1] = value.vec[1];
vertex[2] = value.vec[2];
}
}
/// set vec4 component value of vertex
void set(float * vertex, VertexElementType type, vec4 value) const {
int start = _elementOffset[type];
if (start >= 0) {
vertex += start;
vertex[0] = value.vec[0];
vertex[1] = value.vec[1];
vertex[2] = value.vec[2];
vertex[3] = value.vec[3];
}
}
/// get number of elements
@property int length() const {
return cast(int)_elements.length;
@ -170,9 +212,10 @@ class Mesh : RefCountedObject {
protected VertexBuffer _vertexBuffer;
protected bool _dirtyVertexBuffer = true;
@property ref const(VertexFormat) vertexFormat() const { return _vertexFormat; }
@property ref VertexFormat vertexFormat() { return _vertexFormat; }
@property const(VertexFormat) * vertexFormatPtr() { return &_vertexFormat; }
@property VertexFormat vertexFormat() { return _vertexFormat; }
//@property ref VertexFormat vertexFormat() { return _vertexFormat; }
@property void vertexFormat(VertexFormat format) {
assert(_vertexCount == 0);

View File

@ -1,7 +1,9 @@
module dlangui.graphics.scene.objimport;
import dlangui.core.logger;
import dlangui.core.math3d;
import dlangui.dml.tokenizer;
import dlangui.graphics.scene.mesh;
struct ObjModelImport {
alias FaceIndex = int[3];
@ -14,6 +16,9 @@ struct ObjModelImport {
private int _triangleCount;
private int _txCount;
private float[8] _buf;
MeshRef mesh;
protected float[] parseFloatList(Token[] tokens, int maxItems = 3, float padding = 0) {
int i = 0;
foreach(t; tokens) {
@ -126,7 +131,85 @@ struct ObjModelImport {
return true;
}
vec3 vertexForIndex(int index) {
if (index < 0)
index = _vertexCount + 1 + index;
if (index >= 1 && index <= _vertexCount) {
index = (index - 1) * 3;
return vec3(&_vertexData[index]);
}
return vec3.init;
}
vec3 normalForIndex(int index) {
if (index < 0)
index = _normalCount + 1 + index;
if (index >= 1 && index <= _normalCount) {
index = (index - 1) * 3;
return vec3(&_normalData[index]);
}
return vec3(0, 0, 1);
}
vec2 txForIndex(int index) {
if (index < 0)
index = _txCount + 1 + index;
if (index >= 1 && index <= _txCount) {
index = (index - 1) * 2;
return vec2(&_txData[index]);
}
return vec2.init;
}
bool _meshHasTexture;
void createMeshIfNotExist() {
if (!mesh.isNull)
return;
if (_txCount) {
mesh = new Mesh(VertexFormat(VertexElementType.POSITION, VertexElementType.NORMAL, VertexElementType.COLOR, VertexElementType.TEXCOORD0));
_meshHasTexture = true;
} else {
mesh = new Mesh(VertexFormat(VertexElementType.POSITION, VertexElementType.NORMAL, VertexElementType.COLOR));
_meshHasTexture = false;
}
}
protected bool addTriangle(FaceIndex v1, FaceIndex v2, FaceIndex v3) {
createMeshIfNotExist();
float[16 * 3] data;
const (VertexFormat) * fmt = mesh.vertexFormatPtr;
int vfloats = fmt.vertexFloats;
vec3 p1 = vertexForIndex(v1[0]);
vec3 p2 = vertexForIndex(v2[0]);
vec3 p3 = vertexForIndex(v3[0]);
fmt.set(data.ptr, VertexElementType.POSITION, p1);
fmt.set(data.ptr + vfloats, VertexElementType.POSITION, p2);
fmt.set(data.ptr + vfloats * 2, VertexElementType.POSITION, p3);
if (fmt.hasElement(VertexElementType.TEXCOORD0)) {
fmt.set(data.ptr, VertexElementType.TEXCOORD0, txForIndex(v1[1]));
fmt.set(data.ptr + vfloats, VertexElementType.TEXCOORD0, txForIndex(v2[1]));
fmt.set(data.ptr + vfloats * 2, VertexElementType.TEXCOORD0, txForIndex(v3[1]));
}
if (fmt.hasElement(VertexElementType.COLOR)) {
const vec4 white = vec4(1, 1, 1, 1);
fmt.set(data.ptr, VertexElementType.COLOR, white);
fmt.set(data.ptr + vfloats, VertexElementType.COLOR, white);
fmt.set(data.ptr + vfloats * 2, VertexElementType.COLOR, white);
}
if (fmt.hasElement(VertexElementType.NORMAL)) {
vec3 normal;
if (!v1[2] || !v2[2] || !v3[2]) {
// no normal specified, calculate it
normal = triangleNormal(p1, p2, p3);
}
fmt.set(data.ptr, VertexElementType.NORMAL, v1[2] ? normalForIndex(v1[2]) : normal);
fmt.set(data.ptr + vfloats, VertexElementType.NORMAL, v2[2] ? normalForIndex(v2[2]) : normal);
fmt.set(data.ptr + vfloats * 2, VertexElementType.NORMAL, v3[2] ? normalForIndex(v3[2]) : normal);
}
int startVertex = mesh.addVertexes(data.ptr[0 .. vfloats * 3]);
mesh.addPart(PrimitiveType.triangles, [
cast(ushort)(startVertex + 0),
cast(ushort)(startVertex + 1),
cast(ushort)(startVertex + 2)]);
_triangleCount++;
return true;
}