three_js_wx_renderer 0.0.1
three_js_wx_renderer: ^0.0.1 copied to clipboard
This is a renderer for three_js using wxDart
import 'package:wx_dart/wx_dart.dart';
import 'package:three_js_wx_renderer/three_js_wx_renderer.dart';
import 'package:three_js_core/three_js_core.dart' as three;
import 'package:three_js_math/three_js_math.dart' as tmath;
import 'dart:math' as math;
class MyThreeGLContext extends WxGLContext
{
MyThreeGLContext( MyThreeWindow canvas, WxGLContextAttrs attrs ) : super( canvas, attrs )
{
setCurrent(canvas);
_canvas = canvas;
}
late ThreeJS threeJs;
bool _threeIsReady = false;
int _width = 460;
int _height = 489;
int startTime = 0;
late WxUIAnimation _animation;
late MyThreeWindow _canvas;
void setViewport( int width, int height )
{
final gl = this;
gl.viewport( 0, 0, width, height );
_width = width;
_height = height;
if (_threeIsReady) {
threeJs.setSize( width, height );
threeJs.camera.aspect = width/height;
threeJs.camera.updateProjectionMatrix();
}
}
@override
void onPrepare()
{
final gl = this;
// final version = gl.getString( WebGL.SHADING_LANGUAGE_VERSION );
// print( "wxGlCanvas with GLSL version: $version" );
threeJs = ThreeJS(gl, _width, _height, () {
// not yet ever called
});
threeJs.camera = three.PerspectiveCamera(45, threeJs.width / threeJs.height, 1, 2000);
threeJs.camera.position.y = 400;
threeJs.scene = three.Scene();
three.Mesh object;
final ambientLight = three.AmbientLight(0xffffff, 0.2);
threeJs.scene.add(ambientLight);
/*
final pointLight = three.PointLight(0xff0000, 0.6);
threeJs.camera.add(pointLight);
threeJs.scene.add(threeJs.camera);
*/
final dirLight = three.DirectionalLight( 0xffffff, 0.4 );
dirLight.position.setValues( - 500, 50, 500 );
threeJs.scene.add( dirLight );
final material = three.MeshPhongMaterial.fromMap({
"color": 0xffffff,
"side": tmath.DoubleSide,
"clipShadows": true
});
object = three.Mesh(three.SphereGeometry(75, 20, 10), material);
object.position.setValues(-300, 0, 200);
threeJs.scene.add(object);
object = three.Mesh(three.PlaneGeometry(100, 100, 4, 4), material);
object.position.setValues(-300, 0, 0);
threeJs.scene.add(object);
object = three.Mesh(three.BoxGeometry(100, 100, 100, 4, 4, 4), material);
object.position.setValues(-100, 0, 0);
threeJs.scene.add(object);
_threeIsReady = true;
startTime = DateTime.now().millisecondsSinceEpoch;
_animation = WxUIAnimation( (value) {
final timer = DateTime.now().millisecondsSinceEpoch * 0.0001;
threeJs.camera.position.x = math.cos(timer) * 800;
threeJs.camera.position.z = math.sin(timer) * 800;
threeJs.camera.lookAt(threeJs.scene.position);
threeJs.scene.traverse((object) {
if (object is three.Mesh) {
object.rotation.x = timer * 5;
object.rotation.y = timer * 2.5;
}
});
_canvas.updateThree();
}, 1000, callbackCompleted: () {
_animation.start();
});
_animation.start();
}
void checkError( String operation )
{
final gl = this;
final err = gl.getError();
if (err != WebGL.NO_ERROR) {
wxLogError( "$operation: error no: $err" );
}
}
void render()
{
final gl = this;
gl.clearColor(0.0, 0.0, 1.0, 1.0);
gl.clear(WebGL.COLOR_BUFFER_BIT | WebGL.DEPTH_BUFFER_BIT);
gl.enable(WebGL.DEPTH_TEST);
threeJs.renderer.clear();
checkError("end of three error" );
threeJs.renderer.setViewport(0,0,_width.toDouble(),_height.toDouble());
checkError("viewport three error" );
threeJs.renderer.render(threeJs.scene, threeJs.camera);
checkError("end of three error" );
gl.flush();
}
}
class MyThreeWindow extends WxGLCanvas
{
MyThreeWindow( WxWindow parent, WxGLAttributes attr ) : super( parent, attr, -1 )
{
final attrs = WxGLContextAttrs();
if (!wxUsesFlutter()){
attrs.forwardCompatible();
attrs.coreProfile();
}
attrs.endList();
_glContext = MyThreeGLContext(this,attrs);
bindSizeEvent( (_) => updateThree() );
}
late MyThreeGLContext _glContext;
void updateThree()
{
if (!setCurrent(_glContext)) return;
final size = getClientSize();
_glContext.setViewport( size.x, size.y );
_glContext.render();
swapBuffers();
}
}
const idAbout = 100;
// Every app needs a WxFrame as a main window.
class MyFrame extends WxFrame {
MyFrame( WxFrame? parent) : super( parent, -1, "Hello World", size: WxSize(900, 700) )
{
// Create a menu bar
final menubar = WxMenuBar();
// Create a menu
final filemenu = WxMenu();
// Create a menu item with short cuts and help text
filemenu.appendItem( idAbout, "About\tAlt-A", help: "About ThreeJS for wxDart" );
filemenu.appendSeparator();
filemenu.appendItem( wxID_EXIT, "Quit app\tCtrl-Q", help: "Run, baby, run!" );
// Attach menu to menu bar
menubar.append(filemenu, "File");
// Attach menu bar to this frame
setMenuBar(menubar);
// Create status bar at the bottom
createStatusBar( number: 2 );
setStatusText( "Welcome to wxDart with Three Dart" );
final attr = WxGLAttributes();
attr.defaults();
attr.endList();
mainWindow = MyThreeWindow( this, attr );
// Bind this function to idAbout ID menu item
bindMenuEvent((_) {
// Show a message dialog
final dialog = WxMessageDialog( this, "Welcome ThreeJS with wxDart", caption: "Three wxDart" );
dialog.showModal(null);
}, idAbout );
// Bind this function to wxID_EXIT
bindMenuEvent( (_) => close(false), wxID_EXIT );
// Someone requested to close.
bindCloseWindowEvent( (_) => destroy() );
}
late MyThreeWindow mainWindow;
}
// Every app needs an instance of WxApp
class MyApp extends WxApp {
MyApp();
@override
bool onInit() {
// create and show main window
WxFrame myFrame = MyFrame( null );
myFrame.show();
return true;
}
}
void main()
{
final myApp = MyApp();
myApp.run();
myApp.dispose();
}