Last active
September 25, 2020 18:15
-
-
Save ykmnkmi/edfe5bfa0fc3f61a673446a10c7874bf to your computer and use it in GitHub Desktop.
gl vertex math dart:ui
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'dart:math' as math; | |
import 'dart:typed_data'; | |
import 'dart:ui'; | |
import 'package:vector_math/vector_math.dart'; | |
typedef Renderer = void Function(Canvas canvas, Rect paintBounds); | |
Renderer render; | |
const black = const Color(0xFF000000); | |
const red = const Color(0xFFFF0000); | |
const white = const Color(0xFFFFFFFF); | |
void main() { | |
final canvasHalf = Size(480.0, 320.0).center(Offset.zero); | |
final cameraPosition = Vector3(0.0, 0.0, 300.0); | |
final cameraFocusPosition = Vector3(0.0, 0.0, 0.0); | |
final upDirection = Vector3(0.0, 1.0, 0.0); | |
List<Offset> positions; | |
final view = Matrix4.identity(); | |
final projection = Matrix4.identity(); | |
final position = Vector3.zero(); | |
var rotation = Quaternion.euler(radians(0.0), radians(0.0), radians(0.0)); | |
final scale = Vector3.all(1.0); | |
final vertexPoints = <Vector3>[ | |
position + Vector3(-100.0, 0, -100.0), | |
position + Vector3(100.0, 0, -100.0), | |
position + Vector3(100.0, 0, 100.0), | |
position + Vector3(-100.0, 0, 100.0), | |
]; | |
final colors = const <Color>[red, red, red, red]; | |
final length = vertexPoints.length; | |
positions = List<Offset>(length); | |
final paint = Paint(); | |
paint.color = red; | |
render = (Canvas canvas, Rect paintBounds) { | |
final size = paintBounds.size; | |
final mid = size.center(Offset.zero); | |
setViewMatrix(view, cameraPosition, cameraFocusPosition, upDirection); | |
final fov = 70.0; | |
final near = 1.0; | |
final far = 1000.0; | |
final zoom = 1.0; | |
final aspectRatio = size.aspectRatio; | |
final top = near * math.tan(radians(fov) / 2.0) / zoom; | |
final bottom = -top; | |
final right = top * aspectRatio; | |
final left = -right; | |
// setFrustumMatrix(projection, left, right, bottom, top, near, far); | |
setPerspectiveMatrix(projection, fov, aspectRatio, near, far); | |
final model = Matrix4.compose(position, rotation, scale); | |
final mvp = projection * view * model; | |
for (int i = 0; i < length; i++) { | |
final position3 = vertexPoints[i]; | |
final position4 = Vector4(position3.x, position3.y, position3.z, 1.0); | |
position4.applyMatrix4(mvp); | |
final dx = position4.x / position4.w; | |
final dy = -position4.y / position4.w; | |
positions[i] = mid + canvasHalf.scale(dx, dy); | |
} | |
canvas.drawColor(white, BlendMode.srcOver); | |
// vertex | |
final vertices = Vertices(VertexMode.triangleFan, positions, colors: colors); | |
canvas.drawVertices(vertices, BlendMode.src, paint); | |
}; | |
window.onBeginFrame = beginFrame; | |
window.scheduleFrame(); | |
var waiting = true; | |
Timer.periodic(Duration(milliseconds: 1000 ~/ 60), (Timer timer) { | |
if (waiting) { | |
waiting = false; | |
rotation = Quaternion.euler(radians(timer.tick.toDouble()), radians(0.0), radians(0.0)); | |
cameraPosition.y = math.sin(radians(timer.tick.toDouble() * 0.8)) * 200.0; | |
window.scheduleFrame(); | |
waiting = true; | |
} | |
}); | |
} | |
void beginFrame(Duration timeStamp) { | |
final paintBounds = Offset.zero & (window.physicalSize / window.devicePixelRatio); | |
final picture = paint(paintBounds); | |
final scene = composite(picture, paintBounds); | |
window.render(scene); | |
} | |
Scene composite(Picture picture, Rect paintBounds) { | |
final devicePixelRatio = window.devicePixelRatio; | |
final deviceTransform = Float64List(16) | |
..[0] = devicePixelRatio | |
..[5] = devicePixelRatio | |
..[10] = 1.0 | |
..[15] = 1.0; | |
final sceneBuilder = SceneBuilder() | |
..pushTransform(deviceTransform) | |
..addPicture(Offset.zero, picture) | |
..pop(); | |
return sceneBuilder.build(); | |
} | |
Picture paint(Rect paintBounds) { | |
final recorder = PictureRecorder(); | |
final canvas = Canvas(recorder, paintBounds); | |
render(canvas, paintBounds); | |
return recorder.endRecording(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment