Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1463)

Unified Diff: samples/openglui/src/openglui_canvas_tests.dart

Issue 12390045: Added a rudimentary DOM, to assist with event dispatch. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/embedders/openglui/emulator/emulator_embedder.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: samples/openglui/src/openglui_canvas_tests.dart
===================================================================
--- samples/openglui/src/openglui_canvas_tests.dart (revision 19252)
+++ samples/openglui/src/openglui_canvas_tests.dart (working copy)
@@ -25,15 +25,19 @@
if (canvasp == null) {
log("Allocating canvas");
canvas = new CanvasElement(width: w, height: h);
+ document.body.nodes.add(canvas);
} else {
log("Using parent canvas");
canvas = canvasp;
- // called from gl_driver.dart.
- // This is a kludge; we need a clean way of handling events.
- canvas.on.mouseDown.add((e) {
- ++testnum;
- });
}
+ canvas.onMouseDown.listen((e) {
+ ++testnum;
+ isDirty = true;
+ });
+ canvas.onKeyDown.listen((e) {
+ ++testnum;
+ isDirty = true;
+ });
ctx = canvas.getContext("2d");
if (ctx == null) {
throw "Failed to get 2D context";
@@ -649,7 +653,7 @@
ctx.stroke();
}
-int testnum = -1; // Start with latest.
+int testnum = 0; // Set this to -1 to start with last test.
void update() {
if (testnum == 0) {
@@ -724,9 +728,13 @@
case 22:
smiley();
break;
+ case 23:
+ var rayTracer = new RayTracer();
+ rayTracer.render(defaultScene(), ctx, width, height);
+ break;
default:
if (testnum < 0) {
- testnum = 22;
+ testnum = 23;
} else {
testnum = 0;
}
@@ -736,39 +744,265 @@
isDirty = false;
}
-/*
-TODO(gram): below are the current entry points for input events for the
-native code version. We need to integrate these somehow with the WebGL
-version:
-*/
-onMotionDown(num when, num x, num y) {
- ++testnum;
- isDirty = true;
- log("Marking dirty");
+// Raytracer adapted from https://gist.github.com/mythz/3817303.
+
+Scene defaultScene() =>
+ new Scene(
+ [new Plane(new Vector(0.0, 1.0, 0.0), 0.0, Surfaces.checkerboard),
+ new Sphere(new Vector(0.0, 1.0, -0.25), 1.0, Surfaces.shiny),
+ new Sphere(new Vector(-1.0, 0.5, 1.5), 0.5, Surfaces.shiny)],
+ [new Light(new Vector(-2.0, 2.5, 0.0), new Color(0.49, 0.07, 0.07) ),
+ new Light(new Vector(1.5, 2.5, 1.5), new Color(0.07, 0.07, 0.49) ),
+ new Light(new Vector(1.5, 2.5, -1.5), new Color(0.07, 0.49, 0.071) ),
+ new Light(new Vector(0.0, 3.5, 0.0), new Color(0.21, 0.21, 0.35) )],
+ new Camera(new Vector(3.0, 2.0, 4.0), new Vector(-1.0, 0.5, 0.0))
+ );
+
+
+class Vector {
+ num x, y, z;
+ Vector(this.x, this.y, this.z);
+
+ operator -(Vector v) => new Vector(x - v.x, y - v.y, z - v.z);
+ operator +(Vector v) => new Vector(x + v.x, y + v.y, z + v.z);
+ static times(num k, Vector v) => new Vector(k * v.x, k * v.y, k * v.z);
+ static num dot(Vector v1, Vector v2) =>
+ v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
+ static num mag(Vector v) => Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
+ static Vector norm(Vector v) {
+ var _mag = mag(v);
+ var div = _mag == 0 ? double.INFINITY : 1.0 / _mag;
+ return times(div, v);
+ }
+ static Vector cross(Vector v1, Vector v2) {
+ return new Vector(v1.y * v2.z - v1.z * v2.y,
+ v1.z * v2.x - v1.x * v2.z,
+ v1.x * v2.y - v1.y * v2.x);
+ }
}
-onMotionUp(num when, num x, num y) {}
-onMotionMove(num when, num x, num y) {}
-onMotionCancel(num when, num x, num y) {}
-onMotionOutside(num when, num x, num y) {}
-onMotionPointerDown(num when, num x, num y) {
- ++testnum;
- isDirty = true;
- log("Marking dirty");
+
+class Color {
+ num r, g, b;
+ static final white = new Color(1.0, 1.0, 1.0);
+ static final grey = new Color(0.5, 0.5, 0.5);
+ static final black = new Color(0.0, 0.0, 0.0);
+ static final background = Color.black;
+ static final defaultColor = Color.black;
+
+ Color(this.r,this.g,this.b);
+ static scale(num k, Color v) => new Color(k * v.r, k * v.g, k * v.b);
+ operator +(Color v) => new Color(r + v.r, g + v.g, b + v.b);
+ operator *(Color v) => new Color(r * v.r, g * v.g, b * v.b);
+ static _intColor(num d) => ((d > 1 ? 1 : d) * 255).toInt();
+ static String toDrawingRGB(Color c) =>
+ "rgb(${_intColor(c.r)}, ${_intColor(c.g)}, ${_intColor(c.b)})";
}
-onMotionPointerUp(num when, num x, num y) {}
+class Camera {
+ Vector pos, forward, right, up;
+ Camera (this.pos, Vector lookAt) {
+ var down = new Vector(0.0, -1.0, 0.0);
+ forward = Vector.norm(lookAt - pos);
+ right = Vector.times(1.5, Vector.norm(Vector.cross(forward, down)));
+ up = Vector.times(1.5, Vector.norm(Vector.cross(forward, right)));
+ }
+}
-onKeyDown(num when, int flags, int keycode, int metastate, int repeat) {
- if (keycode == 32) {
- ++testnum;
- isDirty = true;
- log("Marking dirty");
+class Ray {
+ Vector start, dir;
+ Ray([this.start, this.dir]);
+}
+
+class Intersection {
+ Thing thing;
+ Ray ray;
+ num dist;
+ Intersection(this.thing, this.ray, this.dist);
+}
+
+class Light {
+ Vector pos;
+ Color color;
+ Light(this.pos, this.color);
+}
+
+abstract class Surface {
+ int roughness;
+ Color diffuse(Vector pos);
+ Color specular(Vector pos);
+ num reflect(Vector pos);
+}
+
+abstract class Thing {
+ Intersection intersect(Ray ray);
+ Vector normal(Vector pos);
+ Surface surface;
+}
+
+class Scene {
+ List<Thing> things;
+ List<Light> lights;
+ Camera camera;
+ Scene([this.things,this.lights,this.camera]);
+}
+
+class Sphere implements Thing {
+ num radius2, radius;
+ Vector center;
+ Surface surface;
+
+ Sphere (this.center, this.radius, this.surface) {
+ this.radius2 = radius * radius;
}
+ normal(Vector pos) => Vector.norm(pos - center);
+ intersect(Ray ray) {
+ var eo = this.center - ray.start;
+ var v = Vector.dot(eo, ray.dir);
+ var dist = 0;
+ if (v >= 0) {
+ var disc = this.radius2 - (Vector.dot(eo, eo) - v * v);
+ if (disc >= 0) {
+ dist = v - Math.sqrt(disc);
+ }
+ }
+ return dist == 0 ? null : new Intersection(this, ray, dist);
+ }
}
-onKeyUp(num when, int flags, int keycode, int metastate, int repeat) {}
+class Plane implements Thing {
+ Vector norm;
+ num offset;
+ Surface surface;
+ Plane(this.norm, this.offset, this.surface);
+ Vector normal(Vector pos) => norm;
+ Intersection intersect(Ray ray) {
+ var denom = Vector.dot(norm, ray.dir);
+ if (denom > 0) {
+ return null;
+ } else {
+ var dist = (Vector.dot(norm, ray.start) + offset) / (-denom);
+ return new Intersection(this, ray, dist);
+ }
+ }
+}
-onKeyMultiple(num when, int flags, int keycode, int metastate, int repeat) {
+class CustomSurface implements Surface {
+ Color diffuseColor, specularColor;
+ int roughness;
+ num reflectPos;
+ CustomSurface(this.diffuseColor, this.specularColor,
+ this.reflectPos, this.roughness);
+ diffuse(pos) => diffuseColor;
+ specular(pos) => specularColor;
+ reflect(pos) => reflectPos;
}
+class CheckerBoardSurface implements Surface {
+ int roughness;
+ CheckerBoardSurface([this.roughness=150]);
+ diffuse(pos) => (pos.z.floor() + pos.x.floor()) % 2 != 0
+ ? Color.white
+ : Color.black;
+ specular(pos) => Color.white;
+ reflect(pos) => (pos.z.floor() + pos.x.floor()) % 2 != 0 ? 0.1 : 0.7;
+}
+class Surfaces {
+ static final shiny = new CustomSurface(Color.white, Color.grey, 0.7, 250);
+ static final checkerboard = new CheckerBoardSurface();
+}
+
+class RayTracer {
+ num _maxDepth = 5;
+
+ Intersection _intersections(Ray ray, Scene scene) {
+ var closest = double.INFINITY;
+ Intersection closestInter = null;
+ for (Thing thing in scene.things) {
+ var inter = thing.intersect(ray);
+ if (inter != null && inter.dist < closest) {
+ closestInter = inter;
+ closest = inter.dist;
+ }
+ }
+ return closestInter;
+ }
+
+ _testRay(Ray ray, Scene scene) {
+ var isect = _intersections(ray, scene);
+ return isect != null ? isect.dist : null;
+ }
+
+ _traceRay(Ray ray, Scene scene, num depth) {
+ var isect = _intersections(ray, scene);
+ return isect == null ? Color.background : _shade(isect, scene, depth);
+ }
+
+ _shade(Intersection isect, Scene scene, num depth) {
+ var d = isect.ray.dir;
+ var pos = Vector.times(isect.dist, d) + isect.ray.start;
+ var normal = isect.thing.normal(pos);
+ var reflectDir = d -
+ Vector.times(2, Vector.times(Vector.dot(normal, d), normal));
+ var naturalColor = Color.background +
+ _getNaturalColor(isect.thing, pos, normal, reflectDir, scene);
+ var reflectedColor = (depth >= _maxDepth) ? Color.grey :
+ _getReflectionColor(isect.thing, pos, normal, reflectDir,
+ scene, depth);
+ return naturalColor + reflectedColor;
+ }
+
+ _getReflectionColor(Thing thing, Vector pos, Vector normal, Vector rd,
+ Scene scene, num depth) =>
+ Color.scale(thing.surface.reflect(pos),
+ _traceRay(new Ray(pos, rd), scene, depth + 1));
+
+ _getNaturalColor(Thing thing, Vector pos, Vector norm, Vector rd,
+ Scene scene) {
+ var addLight = (col, light) {
+ var ldis = light.pos - pos;
+ var livec = Vector.norm(ldis);
+ var neatIsect = _testRay(new Ray(pos, livec), scene);
+ var isInShadow = neatIsect == null ? false :
+ (neatIsect <= Vector.mag(ldis));
+ if (isInShadow) {
+ return col;
+ } else {
+ var illum = Vector.dot(livec, norm);
+ var lcolor = (illum > 0) ? Color.scale(illum, light.color)
+ : Color.defaultColor;
+ var specular = Vector.dot(livec, Vector.norm(rd));
+ var scolor = (specular > 0)
+ ? Color.scale(Math.pow(specular, thing.surface.roughness),
+ light.color)
+ : Color.defaultColor;
+ return col + (thing.surface.diffuse(pos) * lcolor)
+ + (thing.surface.specular(pos) * scolor);
+ }
+ };
+ return scene.lights.reduce(Color.defaultColor, addLight);
+ }
+
+ render(Scene scene, CanvasRenderingContext2D ctx, num screenWidth,
+ num screenHeight) {
+ var getPoint = (x, y, camera) {
+ var recenterX = (x) => (x - (screenWidth / 2.0)) / 2.0 / screenWidth;
+ var recenterY = (y) => - (y - (screenHeight / 2.0)) / 2.0 / screenHeight;
+ return Vector.norm(camera.forward
+ + Vector.times(recenterX(x), camera.right)
+ + Vector.times(recenterY(y), camera.up));
+ };
+ for (int y = 0; y < screenHeight; y++) {
+ for (int x = 0; x < screenWidth; x++) {
+ var color = _traceRay(new Ray(scene.camera.pos,
+ getPoint(x, y, scene.camera) ), scene, 0);
+ ctx.fillStyle = Color.toDrawingRGB(color);
+ ctx.fillRect(x, y, x + 1, y + 1);
+ }
+ }
+ }
+}
+
+
+
+
« no previous file with comments | « runtime/embedders/openglui/emulator/emulator_embedder.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698