File SceneNode.cs
File List > Render > src > SceneNode.cs
Go to the documentation of this file.
using System;
using System.Collections;
using System.Collections.Generic;
using Qkmaxware.Geometry;
namespace Qkmaxware.Rendering {
public class SceneNode : IEnumerable<SceneNode> {
public Scene? Scene => (Parent != null) ? Parent.Scene : this.root_scene;
// Use this to hide the property from doxygen
internal Scene? root_scene = null;
public SceneNode? Parent {get; private set;} = null;
public Transformation Transform = Transformation.Identity();
public Vec3 Position => LocalToWorldMatrix * Vec3.Zero;
public Vec3 Forward => LocalToWorldMatrix * Vec3.J;
public Vec3 Backward => -Forward;
public Vec3 Up => LocalToWorldMatrix * Vec3.K;
public Vec3 Down => -Up;
public Vec3 Left => -Right;
public Vec3 Right => LocalToWorldMatrix * Vec3.I;
public Transformation LocalToWorldMatrix => (Parent != null) ? Parent.LocalToWorldMatrix * this.Transform : this.Transform;
public Transformation WorldToLocalMatrix => LocalToWorldMatrix.Inverse;
private List<SceneNode> children = new List<SceneNode>();
public IEnumerable<SceneNode> Children => children.AsReadOnly();
public void Add(SceneNode node) {
// Remove from old parent
node.Parent?.Remove(node);
// Add to new parent
this.children.Add(node);
node.Parent = this;
}
public void Remove(SceneNode node) {
if (this.children.Remove(node)) {
node.Parent = null;
}
}
public void Detach() {
this.Parent?.Remove(this);
}
public IEnumerator<SceneNode> GetEnumerator() {
foreach (var child in children) {
yield return child;
foreach (var subchild in child) {
yield return subchild;
}
}
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
public void Rotate(Vec3 axis, double angle) {
var norm = axis.Normalized;
double c = Math.Cos(angle);
double s = Math.Sin(angle);
double t = 1.0 - c;
double x = norm.X;
double y = norm.Y;
double z = norm.Z;
var rotation = new Transformation(
t * x * x + c, t * x * y - z * s, t * x * z + y * s, 0,
t * x * y + z * s, t * y * y + c, t * y * z - x * s, 0,
t * x * z - y * s, t * y * z + x * s, t * z * z + c, 0
);
this.Transform = rotation * this.Transform;
}
public void RotateAround(Vec3 point, Vec3 axis, double angle) {
var norm = axis.Normalized;
double c = Math.Cos(angle);
double s = Math.Sin(angle);
double t = 1.0 - c;
double x = norm.X;
double y = norm.Y;
double z = norm.Z;
var rotation = new Transformation(
t * x * x + c, t * x * y - z * s, t * x * z + y * s, 0,
t * x * y + z * s, t * y * y + c, t * y * z - x * s, 0,
t * x * z - y * s, t * y * z + x * s, t * z * z + c, 0
);
this.Transform = (Transformation.Offset(point) * rotation * Transformation.Offset(-point)) * this.Transform;
}
public void Move(Vec3 delta) {
this.Transform = Transformation.Offset(delta) * this.Transform;
}
}
}