# HG changeset patch
# User John Tsiombikas <nuclear@member.fsf.org>
# Date 1397335075 -10800
# Node ID 964f8ea5f095dbd26efdcc38cc92b53b5850efb4
# Parent  d94a69933a7105a04e8b2350b58c7033f9c51795
missed quite a lot of things in my last commit apparently

diff -r d94a69933a71 -r 964f8ea5f095 GNUmakefile
--- a/GNUmakefile	Sat Apr 12 23:28:24 2014 +0300
+++ b/GNUmakefile	Sat Apr 12 23:37:55 2014 +0300
@@ -1,7 +1,7 @@
 baseobj = src/main.o src/logger.o src/screen.o src/scrman.o
 modelobj = src/modeller.o src/min3d.o src/m3drast.o src/lines.o
 rendobj = src/renderer.o src/vmath.o
-scnobj = src/scene.o src/object.o src/xfnode.o
+scnobj = src/scene.o src/object.o src/light.o src/camera.o src/snode.o
 sysobj = src/dosemu/dosemu.o
 obj = $(baseobj) $(modelobj) $(rendobj) $(scnobj) $(sysobj)
 dep = $(obj:.o=.d)
diff -r d94a69933a71 -r 964f8ea5f095 Makefile
--- a/Makefile	Sat Apr 12 23:28:24 2014 +0300
+++ b/Makefile	Sat Apr 12 23:37:55 2014 +0300
@@ -1,7 +1,7 @@
 baseobj = main.obj logger.obj screen.obj scrman.obj swapbuf.obj
 modelobj = modeller.obj min3d.obj m3drast.obj lines.obj
 rendobj = renderer.obj vmath.obj
-scnobj = scene.obj object.obj xfnode.obj
+scnobj = scene.obj object.obj light.obj camera.obj snode.obj
 sysobj = gfx.obj vbe.obj dpmi.obj timer.obj mouse.obj keyb.obj
 obj = $(baseobj) $(modelobj) $(rendobj) $(scnobj) $(sysobj)
 bin = rayzor.exe
diff -r d94a69933a71 -r 964f8ea5f095 doc/sample.rzr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/sample.rzr	Sat Apr 12 23:37:55 2014 +0300
@@ -0,0 +1,61 @@
+# vim:set ts=4 sw=4 sts=4 ai:
+scene {
+	name = "test"
+
+	material {
+		name = "red"
+		diffuse = [1, 0, 0]
+		specular = [0.8, 0.8, 0.8]
+		shininess = 32.0
+	}
+
+	material {
+		name = "mirror"
+		diffuse = [0.15 0.15 0.15]
+		specular = [0.9 0.9 0.9]
+		shininess = 60
+		reflect = 0.9
+	}
+
+	object {
+		name = "sph01"
+		type = "sphere"
+		material = "red"
+
+		xform { position = [0, 1, 0] }
+	}
+
+	object {
+		name = "box01"
+		type = "box"
+		material = "mirror"
+
+		xform { scale = [3, 0.2, 3] }
+	}
+
+	light {
+		name = "lt-prim"
+		type = "point"
+		color = [1, 0.95, 0.85]
+
+		xform { position = [-10, 10, 10] }
+	}
+
+	light {
+		name = "lt-sec"
+		type = "point"
+		color = [0.3, 0.4, 0.75]
+
+		xform { position = [20, 10, 6] }
+	}
+
+	camera {
+		name = "cam01"
+		type = "lookat"
+		fov = 50
+
+		xform { position = [0, 5, 6] }
+
+		target = [0, 0, 0]
+	}
+}
diff -r d94a69933a71 -r 964f8ea5f095 src/camera.cc
--- a/src/camera.cc	Sat Apr 12 23:28:24 2014 +0300
+++ b/src/camera.cc	Sat Apr 12 23:37:55 2014 +0300
@@ -9,12 +9,12 @@
 
 void Camera::set_target(const Vector3 &target)
 {
-	this->target->set_position(target);
+	this->target.set_position(target);
 }
 
-const Vector3 &Camera::get_target() const
+Vector3 Camera::get_target() const
 {
-	return target->get_position();
+	return target.get_position();
 }
 
 void Camera::set_fov(float fov)
@@ -30,7 +30,7 @@
 void Camera::calc_matrix() const
 {
 	xform.set_identity();
-	xform.lookat(pos, target, Vector3(0, 1, 0));
+	xform.lookat(pos, target.get_position(), Vector3(0, 1, 0));
 	xform_valid = true;
 }
 
@@ -43,7 +43,7 @@
 {
 }
 
-bool Camera::intersect(const Ray &ray, float *dist)
+bool Camera::intersect(const Ray &ray, float *dist) const
 {
 	return false;
 }
diff -r d94a69933a71 -r 964f8ea5f095 src/camera.h
--- a/src/camera.h	Sat Apr 12 23:28:24 2014 +0300
+++ b/src/camera.h	Sat Apr 12 23:37:55 2014 +0300
@@ -2,7 +2,7 @@
 #define CAMERA_H_
 
 #include "vmath.h"
-#include "xfnode.h"
+#include "snode.h"
 
 class Camera : public SceneNode {
 private:
@@ -16,7 +16,7 @@
 	Camera();
 
 	void set_target(const Vector3 &target);
-	const Vector3 &get_target() const;
+	Vector3 get_target() const;
 
 	void set_fov(float fov);
 	float get_fov() const;
diff -r d94a69933a71 -r 964f8ea5f095 src/light.h
--- a/src/light.h	Sat Apr 12 23:28:24 2014 +0300
+++ b/src/light.h	Sat Apr 12 23:37:55 2014 +0300
@@ -2,7 +2,7 @@
 #define LIGHT_H_
 
 #include "vmath.h"
-#include "xfnode.h"
+#include "snode.h"
 
 class Light : public SceneNode {
 private:
diff -r d94a69933a71 -r 964f8ea5f095 src/object.h
--- a/src/object.h	Sat Apr 12 23:28:24 2014 +0300
+++ b/src/object.h	Sat Apr 12 23:37:55 2014 +0300
@@ -2,7 +2,7 @@
 #define OBJECT_H_
 
 #include "vmath.h"
-#include "xfnode.h"
+#include "snode.h"
 
 class Object : public SceneNode {
 protected:
diff -r d94a69933a71 -r 964f8ea5f095 src/quat.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/quat.h	Sat Apr 12 23:37:55 2014 +0300
@@ -0,0 +1,108 @@
+#ifndef QUATERNION_H_
+#define	QUATERNION_H_
+
+class Quat;
+
+inline Quat operator *(const Quat &a, const Quat &b);
+
+class Quat{
+public:
+	float x, y, z, w;
+
+	Quat() : x(0), y(0), z(0), w(1) {}
+	Quat(float xx, float yy, float zz, float ww) : x(xx), y(yy), z(zz), w(ww) {}
+
+	void set_identity()
+	{
+		x = y = z = 0.0f;
+		w = 1.0f;
+	}
+
+	Quat conjugate() const
+	{
+		return Quat(-x, -y, -z, w);
+	}
+
+	float length() const
+	{
+		return (float)sqrt(x * x + y * y + z * z + w * w);
+	}
+
+	float length_sq() const
+	{
+		return x * x + y * y + z * z + w * w;
+	}
+
+	void normalize()
+	{
+		float len = length();
+		if(len != 0.0) {
+			x /= len;
+			y /= len;
+			z /= len;
+			w /= len;
+		}
+	}
+
+	Quat inverse() const
+	{
+		Quat inv = conjugate();
+		float len_sq = length_sq();
+		if(len_sq != 0.0) {
+			inv.x /= len_sq;
+			inv.y /= len_sq;
+			inv.z /= len_sq;
+			inv.w /= len_sq;
+		}
+		return inv;
+	}
+
+	void set_rotation(float angle, float axis_x, float axis_y, float axis_z)
+	{
+		float half_angle = angle * 0.5;
+		float sin_half = sin(half_angle);
+
+		w = cos(half_angle);
+		x = axis_x * sin_half;
+		y = axis_y * sin_half;
+		z = axis_z * sin_half;
+	}
+
+	void rotate(float angle, float x, float y, float z)
+	{
+		Quat q;
+		q.set_rotation(angle, x, y, z);
+		*this = *this * q;
+	}
+
+	void rotate(const Quat &q)
+	{
+		*this = q * *this * q.conjugate();
+	}
+
+	Matrix4x4 get_matrix() const
+	{
+		return Matrix4x4(
+			1.0 - 2.0 * y*y - 2.0 * z*z,	2.0 * x * y - 2.0 * w * z,		2.0 * z * x + 2.0 * w * y, 0,
+			2.0 * x * y + 2.0 * w * z,		1.0 - 2.0 * x*x - 2.0 * z*z,	2.0 * y * z - 2.0 * w * x, 0,
+			2.0 * z * x - 2.0 * w * y,		2.0 * y * z + 2.0 * w * x,		1.0 - 2.0 * x*x - 2.0 * y*y, 0,
+			0, 0, 0, 1);
+	}
+};
+
+inline Quat operator *(const Quat &a, const Quat &b)
+{
+	float dot = a.x * b.x + a.y * b.y + a.z * b.z;
+	float cross_x = a.y * b.z - a.z * b.y;
+	float cross_y = a.z * b.x - a.x * b.z;
+	float cross_z = a.x * b.y - a.y * b.x;
+
+	float w = a.w * b.w - dot;
+	float x = a.x * b.w + b.x * a.w + cross_x;
+	float y = a.y * b.w + b.y * a.w + cross_y;
+	float z = a.z * b.w + b.z * a.w + cross_z;
+
+	return Quat(x, y, z, w);
+}
+
+#endif	// QUATERNION_H_
diff -r d94a69933a71 -r 964f8ea5f095 src/scene.h
--- a/src/scene.h	Sat Apr 12 23:28:24 2014 +0300
+++ b/src/scene.h	Sat Apr 12 23:37:55 2014 +0300
@@ -3,7 +3,7 @@
 
 #include <string>
 #include <vector.h>
-#include "xfnode.h"
+#include "snode.h"
 #include "object.h"
 #include "light.h"
 #include "camera.h"
diff -r d94a69933a71 -r 964f8ea5f095 src/snode.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/snode.cc	Sat Apr 12 23:37:55 2014 +0300
@@ -0,0 +1,193 @@
+#include <string.h>
+#include <assert.h>
+#include "snode.h"
+
+
+SceneNode::SceneNode()
+{
+	parent = 0;
+	name = 0;
+	type = NODE_NULL;
+	scale = Vector3(1, 1, 1);
+	invalidate();
+}
+
+SceneNode::~SceneNode()
+{
+	delete [] name;
+}
+
+void SceneNode::set_name(const char *name)
+{
+	this->name = new char[strlen(name) + 1];
+	strcpy(this->name, name);
+}
+
+const char *SceneNode::get_name() const
+{
+	return name ? name : "<unnamed>";
+}
+
+NodeType SceneNode::get_type() const
+{
+	return type;
+}
+
+SceneNode *SceneNode::get_parent()
+{
+	return parent;
+}
+
+const SceneNode *SceneNode::get_parent() const
+{
+	return parent;
+}
+
+void SceneNode::add_child(SceneNode *child)
+{
+	children.push_back(child);
+	child->parent = this;
+	invalidate();
+}
+
+void SceneNode::remove_child(SceneNode *child)
+{
+	// TODO
+	invalidate();
+}
+
+int SceneNode::get_children_count() const
+{
+	return (int)children.size();
+}
+
+SceneNode *SceneNode::get_child(int idx)
+{
+	if(idx >= 0 && idx < get_children_count()) {
+		return children[idx];
+	}
+	return 0;
+}
+
+const SceneNode *SceneNode::get_child(int idx) const
+{
+	if(idx >= 0 && idx < get_children_count()) {
+		return children[idx];
+	}
+	return 0;
+}
+
+
+
+void SceneNode::set_position(const Vector3 &pos)
+{
+	this->pos = pos;
+	invalidate();
+}
+
+Vector3 SceneNode::get_node_position() const
+{
+	return pos;
+}
+
+void SceneNode::set_rotation(const Quat &quat)
+{
+	rot = quat;
+	invalidate();
+}
+
+Quat SceneNode::get_node_rotation() const
+{
+	return rot;
+}
+
+void SceneNode::set_scaling(const Vector3 &scale)
+{
+	this->scale = scale;
+	invalidate();
+}
+
+Vector3 SceneNode::get_node_scaling() const
+{
+	return scale;
+}
+
+// these take hierarchy into account
+Vector3 SceneNode::get_position() const
+{
+	return transform(get_matrix(), Vector3(0, 0, 0));
+}
+
+Quat SceneNode::get_rotation() const
+{
+	if(parent) {
+		return parent->get_rotation() * rot;
+	}
+	return rot;
+}
+
+Vector3 SceneNode::get_scaling() const
+{
+	if(parent) {
+		return parent->get_scaling() * scale;
+	}
+	return scale;
+}
+
+void SceneNode::set_pivot(const Vector3 &pivot)
+{
+	this->pivot = pivot;
+	invalidate();
+}
+
+Vector3 SceneNode::get_pivot() const
+{
+	return pivot;
+}
+
+const Matrix4x4 &SceneNode::get_matrix() const
+{
+	calc_matrix();
+	return xform;
+}
+
+const Matrix4x4 &SceneNode::get_inv_matrix() const
+{
+	calc_inv_matrix();
+	return inv_xform;
+}
+
+void SceneNode::invalidate() const
+{
+	xform_valid = inv_xform_valid = false;
+}
+
+// TODO: hierarchy
+void SceneNode::calc_matrix() const
+{
+	xform.set_identity();
+	xform.translate(pivot.x, pivot.y, pivot.z);
+	xform = xform * rot.get_matrix();
+	xform.translate(pos.x, pos.y, pos.z);
+	xform.scale(scale.x, scale.y, scale.z);
+	xform.translate(-pivot.x, -pivot.y, -pivot.z);
+
+	xform_valid = true;
+}
+
+void SceneNode::calc_inv_matrix() const
+{
+	calc_matrix();
+
+	inv_xform = xform.inverse();
+	inv_xform_valid = true;
+}
+
+void SceneNode::draw() const
+{
+}
+
+bool SceneNode::intersect(const Ray &ray, float *dist) const
+{
+	return false;
+}
diff -r d94a69933a71 -r 964f8ea5f095 src/snode.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/snode.h	Sat Apr 12 23:37:55 2014 +0300
@@ -0,0 +1,85 @@
+#ifndef SCENE_NODE_H_
+#define SCENE_NODE_H_
+
+#include "vector.h"
+#include "vmath.h"
+#include "quat.h"
+#include "vmathmat.h"
+#include "vmathray.h"
+
+enum NodeType {
+	NODE_NULL,
+	NODE_OBJECT,
+	NODE_LIGHT,
+	NODE_CAMERA
+};
+
+class SceneNode {
+protected:
+	char *name;
+	NodeType type;
+
+	Vector3 pos;
+	Quat rot;
+	Vector3 scale;
+	Vector3 pivot;
+
+	mutable Matrix4x4 xform, inv_xform;
+	mutable bool xform_valid, inv_xform_valid;
+
+	vector<SceneNode*> children;
+	SceneNode *parent;
+
+	SceneNode(const SceneNode &node) {}
+	SceneNode &operator =(const SceneNode &node) { return *this; }
+
+	void invalidate() const;
+	virtual void calc_matrix() const;
+	virtual void calc_inv_matrix() const;
+
+public:
+	SceneNode();
+	virtual ~SceneNode();
+
+	virtual void set_name(const char *name);
+	virtual const char *get_name() const;
+
+	virtual NodeType get_type() const;
+
+	virtual SceneNode *get_parent();
+	virtual const SceneNode *get_parent() const;
+
+	// children management
+	virtual void add_child(SceneNode *child);
+	virtual void remove_child(SceneNode *child);
+
+	virtual int get_children_count() const;
+	virtual SceneNode *get_child(int idx);
+	virtual const SceneNode *get_child(int idx) const;
+
+	virtual void set_position(const Vector3 &pos);
+	virtual Vector3 get_node_position() const;
+
+	virtual void set_rotation(const Quat &quat);
+	virtual Quat get_node_rotation() const;
+
+	virtual void set_scaling(const Vector3 &scale);
+	virtual Vector3 get_node_scaling() const;
+
+	// these take hierarchy into account
+	virtual Vector3 get_position() const;
+	virtual Quat get_rotation() const;
+	virtual Vector3 get_scaling() const;
+
+	virtual void set_pivot(const Vector3 &pivot);
+	virtual Vector3 get_pivot() const;
+
+	virtual const Matrix4x4 &get_matrix() const;
+	virtual const Matrix4x4 &get_inv_matrix() const;
+
+	virtual void draw() const;
+
+	virtual bool intersect(const Ray &ray, float *dist = 0) const;
+};
+
+#endif	/* SCENE_NODE_H_ */
diff -r d94a69933a71 -r 964f8ea5f095 src/vmathmat.h
--- a/src/vmathmat.h	Sat Apr 12 23:28:24 2014 +0300
+++ b/src/vmathmat.h	Sat Apr 12 23:37:55 2014 +0300
@@ -34,7 +34,7 @@
 	inline void rotate(float angle, float x, float y, float z);
 	inline void scale(float x, float y, float z);
 	inline void perspective(float vfov, float aspect, float znear, float zfar);
-	inline void lookat(const Vector3 &pos, const Vector3 &targ, const Vector3 &up);
+	void lookat(const Vector3 &pos, const Vector3 &targ, const Vector3 &up);
 
 	float *operator [](int idx) { return m[idx]; }
 	const float *operator [](int idx) const { return m[idx]; }
diff -r d94a69933a71 -r 964f8ea5f095 src/vmathray.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/vmathray.h	Sat Apr 12 23:37:55 2014 +0300
@@ -0,0 +1,24 @@
+#ifndef VMATH_RAY_H_
+#define VMATH_RAY_H_
+
+#include "vmath.h"
+#include "vmathmat.h"
+
+class Ray {
+public:
+	Vector3 pos, dir;
+
+	Ray() {}
+	Ray(const Vector3 &p, const Vector3 &d) : pos(p), dir(d) {}
+};
+
+inline Ray transform(const Matrix4x4 &m, const Ray &r)
+{
+	Matrix4x4 rmat = m;
+	rmat[0][3] = rmat[1][3] = rmat[2][3] = rmat[3][0] = rmat[3][1] = rmat[3][2] = 0.0;
+	rmat[3][3] = 1.0;
+
+	return Ray(transform(m, r.pos), transform(rmat, r.dir));
+}
+
+#endif	// VMATH_RAY_H_