dlangui/examples/d3d/src/d3d.d

277 lines
12 KiB
D

module d3d;
import dlangui;
import dlangui.graphics.scene.scene3d;
import dlangui.graphics.scene.camera;
import dlangui.graphics.scene.mesh;
import dlangui.graphics.scene.material;
import dlangui.graphics.scene.effect;
import dlangui.graphics.scene.model;
import dlangui.graphics.scene.node;
import dlangui.graphics.scene.light;
import dlangui.graphics.scene.objimport;
import dlangui.graphics.scene.fbximport;
import dlangui.graphics.glsupport;
import dlangui.graphics.gldrawbuf;
import bindbc.opengl;
mixin APP_ENTRY_POINT;
/// entry point for dlangui based application
extern (C) int UIAppMain(string[] args) {
// embed resources listed in views/resources.list into executable
embeddedResourceList.addResources(embedResourcesFromList!("resources.list")());
// create window
Window window = Platform.instance.createWindow("DlangUI example - 3D Application", null, WindowFlag.Resizable, 600, 500);
static if (ENABLE_OPENGL) {
window.mainWidget = new UiWidget();
} else {
window.mainWidget = new TextWidget("error", "Please build with OpenGL enabled"d);
}
//MeshPart part = new MeshPart();
// show window
window.show();
// run message loop
return Platform.instance.enterMessageLoop();
}
static if (ENABLE_OPENGL):
class UiWidget : VerticalLayout {
this() {
super("OpenGLView");
layoutWidth = FILL_PARENT;
layoutHeight = FILL_PARENT;
alignment = Align.Center;
try {
parseML(q{
{
margins: 10
padding: 10
backgroundImageId: "tx_fabric.tiled"
layoutWidth: fill
layoutHeight: fill
VerticalLayout {
id: glView
margins: 10
padding: 10
layoutWidth: fill
layoutHeight: fill
TextWidget { text: "There should be OpenGL animation on background"; textColor: "red"; fontSize: 150%; fontWeight: 800; fontFace: "Arial" }
TextWidget { text: "Do you see it? If no, there is some bug in Mesh rendering code..."; fontSize: 120% }
// arrange controls as form - table with two columns
TableLayout {
colCount: 6
TextWidget { text: "Translation X" }
TextWidget { id: lblTranslationX; text: "0.0"; minWidth: 80; backgroundColor: 0x80FFFFFF }
ScrollBar { id: sbTranslationX; orientation: horizontal; minValue: -100; maxValue: 100; position: 0; minWidth: 200; alpha: 0.6 }
TextWidget { text: "Rotation X" }
TextWidget { id: lblRotationX; text: "0.0"; minWidth: 80; backgroundColor: 0x80FFFFFF }
ScrollBar { id: sbRotationX; orientation: horizontal; minValue: -180; maxValue: 180; position: 0; minWidth: 200; alpha: 0.6 }
TextWidget { text: "Translation Y" }
TextWidget { id: lblTranslationY; text: "0.0"; minWidth: 80; backgroundColor: 0x80FFFFFF }
ScrollBar { id: sbTranslationY; orientation: horizontal; minValue: -100; maxValue: 100; position: 15; minWidth: 200; alpha: 0.6 }
TextWidget { text: "Rotation Y" }
TextWidget { id: lblRotationY; text: "0.0"; minWidth: 80; backgroundColor: 0x80FFFFFF }
ScrollBar { id: sbRotationY; orientation: horizontal; minValue: -180; maxValue: 180; position: 0; minWidth: 150; alpha: 0.6 }
TextWidget { text: "Translation Z" }
TextWidget { id: lblTranslationZ; text: "0.0"; minWidth: 80; backgroundColor: 0x80FFFFFF }
ScrollBar { id: sbTranslationZ; orientation: horizontal; minValue: -100; maxValue: 100; position: 45; minWidth: 150; alpha: 0.6 }
TextWidget { text: "Rotation Z" }
TextWidget { id: lblRotationZ; text: "0.0"; minWidth: 80; backgroundColor: 0x80FFFFFF }
ScrollBar { id: sbRotationZ; orientation: horizontal; minValue: -180; maxValue: 180; position: 0; minWidth: 150; alpha: 0.6 }
TextWidget { text: "Near" }
TextWidget { id: lblNear; text: "0.1"; minWidth: 80; backgroundColor: 0x80FFFFFF }
ScrollBar { id: sbNear; orientation: horizontal; minValue: 1; maxValue: 100; position: 1; minWidth: 150; alpha: 0.6 }
TextWidget { text: "Far" }
TextWidget { id: lblFar; text: "0.0"; minWidth: 80; backgroundColor: 0x80FFFFFF }
ScrollBar { id: sbFar; orientation: horizontal; minValue: 20; maxValue: 1000; position: 1000; minWidth: 150; alpha: 0.6 }
}
VSpacer { layoutWeight: 30 }
HorizontalLayout {
TextWidget { text: "Some buttons:" }
Button { id: btnOk; text: "Ok"; fontSize: 27px }
Button { id: btnCancel; text: "Cancel"; fontSize: 27px }
}
}
}
}, "", this);
} catch (Exception e) {
Log.e("Failed to parse dml", e);
}
// assign OpenGL drawable to child widget background
childById("glView").backgroundDrawable = DrawableRef(new OpenGLDrawable(&doDraw));
controlsToVars();
assignHandlers();
_scene = new Scene3d();
_cam = new Camera();
_cam.translate(vec3(0, 14, -7));
_scene.activeCamera = _cam;
dirLightNode = new Node3d();
//dirLightNode.lookAt(vec3(-5, -5, -5), vec3(0, 0, 0), vec3(0, 1, 0));
dirLightNode.rotateY(-15);
//dirLightNode.rotateX(20);
dirLightNode.translateX(2);
dirLightNode.translateY(3);
dirLightNode.translateZ(0);
dirLightNode.light = Light.createPoint(vec3(2, 2, 2), 15); //Light.createDirectional(vec3(1, 0.5, 0.5));
//dirLightNode.light = Light.createDirectional(vec3(1, 0.5, 0.8));
dirLightNode.light.enabled = true;
_scene.addChild(dirLightNode);
int x0 = 0;
int y0 = 0;
int z0 = 0;
Mesh _mesh = Mesh.createCubeMesh(vec3(x0+ 0, y0 + 0, z0 + 0), 0.3f);
for (int i = 0; i < 10; i++) {
_mesh.addCubeMesh(vec3(x0+ 0, y0+0, z0+ i * 2 + 1.0f), 0.2f, vec4(i / 12, 1, 1, 1));
_mesh.addCubeMesh(vec3(x0+ i * 2 + 1.0f, y0+0, z0+ 0), 0.2f, vec4(1, i / 12, 1, 1));
_mesh.addCubeMesh(vec3(x0+ -i * 2 - 1.0f, y0+0, z0+ 0), 0.2f, vec4(1, i / 12, 1, 1));
_mesh.addCubeMesh(vec3(x0+ 0, y0+i * 2 + 1.0f, z0+ 0), 0.2f, vec4(1, 1, i / 12 + 0.1, 1));
_mesh.addCubeMesh(vec3(x0+ 0, y0+-i * 2 - 1.0f, z0+ 0), 0.2f, vec4(1, 1, i / 12 + 0.1, 1));
_mesh.addCubeMesh(vec3(x0+ i * 2 + 1.0f, y0+i * 2 + 1.0f, z0+ i * 2 + 1.0f), 0.2f, vec4(i / 12, i / 12, i / 12, 1));
_mesh.addCubeMesh(vec3(x0+ -i * 2 + 1.0f, y0+i * 2 + 1.0f, z0+ i * 2 + 1.0f), 0.2f, vec4(i / 12, i / 12, 1 - i / 12, 1));
_mesh.addCubeMesh(vec3(x0+ i * 2 + 1.0f, y0+-i * 2 + 1.0f, z0+ i * 2 + 1.0f), 0.2f, vec4(i / 12, 1 - i / 12, i / 12, 1));
_mesh.addCubeMesh(vec3(x0+ -i * 2 - 1.0f, y0+-i * 2 - 1.0f, z0+ -i * 2 - 1.0f), 0.2f, vec4(1 - i / 12, i / 12, i / 12, 1));
}
Material cubeMaterial = new Material(EffectId("textured.vert", "textured.frag", null), "crate");
Model cubeDrawable = new Model(cubeMaterial, _mesh);
Node3d cubeNode = new Node3d("cubes", cubeDrawable);
_scene.addChild(cubeNode);
debug(fbximport) {
// test FBX import
FbxModelImport importer;
string src = loadTextResource("suzanne.fbx");
importer.filename = "suzanne.fbx";
importer.parse(src);
}
ObjModelImport importer;
string src = loadTextResource("suzanne.obj");
importer.parse(src);
Log.d("suzanne mesh:", importer.mesh.dumpVertexes(20));
Material suzanneMaterial = new Material(EffectId("colored.vert", "colored.frag", null), null); //"SPECULAR"
//suzanneMaterial.ambientColor = vec3(0.5, 0.5, 0.5);
suzanneMaterial.diffuseColor = vec4(0.7, 0.7, 0.5, 1.0);
//suzanneMaterial.specular = true;
Model suzanneDrawable = new Model(suzanneMaterial, importer.mesh);
suzanneNode = new Node3d("suzanne", suzanneDrawable);
suzanneNode.translate(vec3(2, 2, -5));
_scene.addChild(suzanneNode);
brickNode = new Node3d("brick");
brickNode.translate(vec3(-2, 2, -3));
Mesh brickMesh = Mesh.createCubeMesh(vec3(0, 0, 0), 0.8, vec4(0.8, 0.8, 0.8, 1));
Material brickMaterial = new Material(EffectId("textured.vert", "textured.frag", null), "brick", "brickn"); // with bump mapping
//brickMaterial.specular = true;
brickNode.drawable = new Model(brickMaterial, brickMesh);
_scene.addChild(brickNode);
}
Node3d dirLightNode;
Node3d suzanneNode;
Node3d brickNode;
float rotationX;
float rotationY;
float rotationZ;
float translationX;
float translationY;
float translationZ;
float near;
float far;
/// handle scroll event
bool onScrollEvent(AbstractSlider source, ScrollEvent event) {
controlsToVars();
return true;
}
void assignHandlers() {
childById!ScrollBar("sbNear").scrollEvent = &onScrollEvent;
childById!ScrollBar("sbFar").scrollEvent = &onScrollEvent;
childById!ScrollBar("sbRotationX").scrollEvent = &onScrollEvent;
childById!ScrollBar("sbRotationY").scrollEvent = &onScrollEvent;
childById!ScrollBar("sbRotationZ").scrollEvent = &onScrollEvent;
childById!ScrollBar("sbTranslationX").scrollEvent = &onScrollEvent;
childById!ScrollBar("sbTranslationY").scrollEvent = &onScrollEvent;
childById!ScrollBar("sbTranslationZ").scrollEvent = &onScrollEvent;
}
void controlsToVars() {
near = childById!ScrollBar("sbNear").position / 10.0f;
far = childById!ScrollBar("sbFar").position / 10.0f;
translationX = childById!ScrollBar("sbTranslationX").position / 10.0f;
translationY = childById!ScrollBar("sbTranslationY").position / 10.0f;
translationZ = childById!ScrollBar("sbTranslationZ").position / 10.0f;
rotationX = childById!ScrollBar("sbRotationX").position;
rotationY = childById!ScrollBar("sbRotationY").position;
rotationZ = childById!ScrollBar("sbRotationZ").position;
childById("lblNear").text = to!dstring(near);
childById("lblFar").text = to!dstring(far);
childById("lblTranslationX").text = to!dstring(translationX);
childById("lblTranslationY").text = to!dstring(translationY);
childById("lblTranslationZ").text = to!dstring(translationZ);
childById("lblRotationX").text = to!dstring(rotationX);
childById("lblRotationY").text = to!dstring(rotationY);
childById("lblRotationZ").text = to!dstring(rotationZ);
}
/// returns true is widget is being animated - need to call animate() and redraw
@property override bool animating() { return true; }
/// animates window; interval is time left from previous draw, in hnsecs (1/10000000 of second)
override void animate(long interval) {
//Log.d("animating");
_cam.rotateX(0.01);
_cam.rotateY(0.02);
angle += interval * 0.000002f;
invalidate();
suzanneNode.rotateY(interval * 0.000002f);
brickNode.rotateY(interval * 0.00000123f);
brickNode.rotateZ(interval * 0.0000004123f);
brickNode.rotateX(interval * 0.0000007543f);
}
float angle = 0;
Scene3dRef _scene;
Camera _cam;
/// this is OpenGLDrawableDelegate implementation
private void doDraw(Rect windowRect, Rect rc) {
_cam.setPerspective(rc.width, rc.height, 45.0f, near, far);
_cam.setIdentity();
_cam.translateX(translationX);
_cam.translateY(translationY);
_cam.translateZ(translationZ);
_cam.rotateX(rotationX);
_cam.rotateY(rotationY);
_cam.rotateZ(rotationZ);
checkgl!glEnable(GL_CULL_FACE);
//checkgl!glDisable(GL_CULL_FACE);
checkgl!glEnable(GL_DEPTH_TEST);
checkgl!glCullFace(GL_BACK);
_scene.drawScene(false);
checkgl!glDisable(GL_DEPTH_TEST);
checkgl!glDisable(GL_CULL_FACE);
}
~this() {
}
}