Bläddra i källkod

Added new Johan Code

Kenneth van Ewijk 9 år sedan
förälder
incheckning
a8415db4ac
24 ändrade filer med 2284 tillägg och 29 borttagningar
  1. 47 5
      CrystalJohan.cpp
  2. 2 0
      CrystalJohan.h
  3. 2 0
      CrystalJohan.vcxproj
  4. 6 0
      CrystalJohan.vcxproj.filters
  5. 13 0
      Entity.cpp
  6. 3 0
      Entity.h
  7. 9 1
      LevelObject.cpp
  8. 7 2
      LevelObject.h
  9. 42 9
      Main.cpp
  10. 30 6
      Model.cpp
  11. 7 1
      Model.h
  12. 14 1
      Player.cpp
  13. 4 0
      Player.h
  14. 10 0
      Vector.cpp
  15. 2 0
      Vector.h
  16. 40 3
      World.cpp
  17. 1 1
      World.h
  18. 770 0
      json.cpp
  19. 132 0
      json.h
  20. 192 0
      models/boom/Boom.mtl
  21. 243 0
      models/boom/Boom.obj
  22. 16 0
      models/portal_blue.mtl
  23. 676 0
      models/portal_blue.obj
  24. 16 0
      worlds/world1.json

+ 47 - 5
CrystalJohan.cpp

@@ -10,22 +10,51 @@ void CrystalJohan::init()
 
 	glClearColor(0.7, 0.7, 1.0, 1.0);
 	glEnable(GL_DEPTH_TEST);
+	glEnable(GL_LIGHTING);
+	glEnable(GL_LIGHT0);
 
+	mousePosition = Vec2f(width / 2, height / 2);
 }
 
 
 void CrystalJohan::draw()
 {
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+	//Draw world
+	glEnable(GL_LIGHTING);
+	glEnable(GL_DEPTH_TEST);
+
 	glMatrixMode(GL_PROJECTION);
 	glLoadIdentity();
 	gluPerspective(70, width / (float)height, 0.1f, 100);
 	glMatrixMode(GL_MODELVIEW);
 	glLoadIdentity();
-	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
+	world->draw();
+	
+	//Draw Cursor
+	glMatrixMode(GL_PROJECTION);
+	glLoadIdentity();
+	glOrtho(0,width, height,0,-10,10);
+	glMatrixMode(GL_MODELVIEW);
+	glLoadIdentity();
+
+	glDisable(GL_LIGHTING);
+	glDisable(GL_DEPTH_TEST);
+	glColor4f(1, cos(glutGet(GLUT_ELAPSED_TIME) / 1000.0f), sin(glutGet(GLUT_ELAPSED_TIME) / 1000.0f), 1);
+	glBegin(GL_TRIANGLES);
+	glVertex2f(mousePosition.x, mousePosition.y);
+	glVertex2f(mousePosition.x+15, mousePosition.y+15);
+	glVertex2f(mousePosition.x+5, mousePosition.y+20);
+
+	glEnd();
+
+
+
+	glutSwapBuffers();
 
 
-	world->draw();
 }
 
 
@@ -34,20 +63,33 @@ void CrystalJohan::update()
 	float frameTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
 	float deltaTime = frameTime - lastFrameTime;
 	lastFrameTime = frameTime;
-	
+
 	//	if(keyboardState.special[GLUT_KEY_LEFT] && !prevKeyboardState.special[GLUT_KEY_LEFT])
 	if (keyboardState.keys[27])
 		exit(0);
 
 
-	world->player.rotation.y += mouseOffset.x/10.0f;
-	world->player.rotation.x += mouseOffset.y/10.0f;
+	world->player.rotation.y += mouseOffset.x / 10.0f;
+	world->player.rotation.x += mouseOffset.y / 10.0f;
 	if (world->player.rotation.x > 90)
 		world->player.rotation.x = 90;
 	if (world->player.rotation.x < -90)
 		world->player.rotation.x = -90;
 
 
+	Vec3f oldPosition = world->player.position;
+	if (keyboardState.keys['a']) world->player.setPosition(0, deltaTime, false);
+	if (keyboardState.keys['d']) world->player.setPosition(180, deltaTime, false);
+	if (keyboardState.keys['w']) world->player.setPosition(90, deltaTime, false);
+	if (keyboardState.keys['s']) world->player.setPosition(270, deltaTime, false);
+	if (keyboardState.keys['q']) world->player.setPosition(1, deltaTime, true);
+	if (keyboardState.keys['e']) world->player.setPosition(-1, deltaTime, true);
+	if (!world->isPlayerPositionValid())
+		world->player.position = oldPosition;
+
+
+	mousePosition = mousePosition + mouseOffset;
+
 	mouseOffset = Vec2f(0, 0);
 	prevKeyboardState = keyboardState;
 	glutPostRedisplay();

+ 2 - 0
CrystalJohan.h

@@ -28,6 +28,8 @@ public:
 
 	Vec2f mouseOffset;
 
+	Vec2f mousePosition;
+
 	float lastFrameTime;
 
 };

+ 2 - 0
CrystalJohan.vcxproj

@@ -156,6 +156,7 @@
     <ClCompile Include="CrystalJohan.cpp" />
     <ClCompile Include="Enemy.cpp" />
     <ClCompile Include="Entity.cpp" />
+    <ClCompile Include="json.cpp" />
     <ClCompile Include="LevelObject.cpp" />
     <ClCompile Include="Main.cpp" />
     <ClCompile Include="Model.cpp" />
@@ -167,6 +168,7 @@
     <ClInclude Include="CrystalJohan.h" />
     <ClInclude Include="Enemy.h" />
     <ClInclude Include="Entity.h" />
+    <ClInclude Include="json.h" />
     <ClInclude Include="LevelObject.h" />
     <ClInclude Include="Main.h" />
     <ClInclude Include="Model.h" />

+ 6 - 0
CrystalJohan.vcxproj.filters

@@ -45,6 +45,9 @@
     <ClCompile Include="Player.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="json.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="CrystalJohan.h">
@@ -80,5 +83,8 @@
     <ClInclude Include="Main.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="json.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>

+ 13 - 0
Entity.cpp

@@ -8,6 +8,8 @@
 Entity::Entity()
 {
 	model = NULL;
+	scale = 1;
+	canCollide = true;
 }
 
 
@@ -34,3 +36,14 @@ void Entity::draw()
 
 }
 
+bool Entity::inObject(const Vec3f & point)
+{
+	if (!model)
+		return false;
+	Vec3f center = position + model->center;
+	float distance = sqrt((point.x - center.x) * (point.x - center.x) + (point.z - center.z)*(point.z - center.z));
+	if (distance < model->radius*scale)
+		return true;
+	return false;
+}
+

+ 3 - 0
Entity.h

@@ -16,5 +16,8 @@ public:
 	Vec3f position;
 	Vec3f rotation;
 	float scale;
+
+	bool canCollide;
+	bool inObject(const Vec3f &position);
 };
 

+ 9 - 1
LevelObject.cpp

@@ -1,12 +1,20 @@
 #include "LevelObject.h"
 
+#include "Model.h"
 
 
-LevelObject::LevelObject()
+LevelObject::LevelObject(const std::string &fileName, const Vec3f &position, const Vec3f &rotation, const float &scale, const bool &hasCollision)
 {
+	model = Model::load(fileName);
+	this->position = position;
+	this->rotation = rotation;
+	this->scale = scale;
+	this->canCollide = hasCollision;
 }
 
 
 LevelObject::~LevelObject()
 {
+	if (model)
+		Model::unload(model);
 }

+ 7 - 2
LevelObject.h

@@ -1,8 +1,13 @@
 #pragma once
-class LevelObject
+
+#include "Entity.h"
+#include <string>
+
+
+class LevelObject : public Entity
 {
 public:
-	LevelObject();
+	LevelObject(const std::string &fileName, const Vec3f &position, const Vec3f &rotation, const float &scale, const bool &hasCollision);
 	~LevelObject();
 };
 

+ 42 - 9
Main.cpp

@@ -4,6 +4,8 @@
 #include <stdio.h>
 #include "vector.h"
 
+void configureOpenGL(void);
+
 CrystalJohan* app;
 
 bool justMoved = false;
@@ -12,12 +14,8 @@ int main(int argc, char* argv[])
 {
 	app = new CrystalJohan();
 	glutInit(&argc, argv);
-	//Init window and glut display mode
-	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
-	glutInitWindowSize(800, 600);
-	glutCreateWindow("Crystal Point");
-	glutFullScreen();
-	//glutPositionWindow((glutGet(GLUT_SCREEN_WIDTH) / 2) - (glutGet(GLUT_WINDOW_WIDTH) / 2), (glutGet(GLUT_SCREEN_HEIGHT) / 2) - (glutGet(GLUT_WINDOW_HEIGHT) / 2));
+
+	configureOpenGL();
 
 	app->init();
 
@@ -28,9 +26,8 @@ int main(int argc, char* argv[])
 	//Keyboard
 	glutKeyboardFunc([](unsigned char c, int, int) { app->keyboardState.keys[c] = true; });
 	glutKeyboardUpFunc([](unsigned char c, int, int) { app->keyboardState.keys[c] = false; });
-
+	
 	//Mouse
-//	glutMouseFunc(mouse);
 	glutPassiveMotionFunc([](int x, int y)
 	{
 		if (justMoved)
@@ -49,7 +46,43 @@ int main(int argc, char* argv[])
 	});
 
 	glutMainLoop();
+	return 0;
+}
+
+void configureOpenGL()
+{
+	//Init window and glut display mode
+	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
+	glutInitWindowSize(800, 600);
+	glutCreateWindow("Crystal Point");
+	glutFullScreen();
 
+	//Depth testing
+	glEnable(GL_DEPTH_TEST);
 
-	return 0;
+	//Alpha blending
+	glEnable(GL_BLEND);
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+	//Alpha testing
+	glEnable(GL_ALPHA_TEST);
+	glAlphaFunc(GL_GREATER, 0.01f);
+
+	//Lighting
+	GLfloat mat_specular[] = { 0.2, 0.2, 0.2, 0 };
+	//GLfloat mat_shininess[] = { 5.0 };
+	GLfloat light_position[] = { 0.0, 2.0, 1.0, 0 };
+	GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 0 };
+	GLfloat light_ambient[] = { 0.3, 0.3, 0.3, 0 };
+	glClearColor(0.7, 0.7, 1.0, 1.0);
+
+	//glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
+	//glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
+	//glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
+	//glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
+
+	//glEnable(GL_LIGHTING);
+	//glEnable(GL_LIGHT0);
+
+	glutSetCursor(GLUT_CURSOR_CROSSHAIR);
 }

+ 30 - 6
Model.cpp

@@ -7,6 +7,7 @@
 #include <fstream>
 #include <string>
 #include <algorithm>
+#include <cmath>
 
 //Prototypes
 std::vector<std::string> split(std::string str, std::string sep);
@@ -170,8 +171,25 @@ void Model::draw()
 			}
 		}
 		glEnd();
+	}
 
+	minVertex = vertices[0];
+	maxVertex = vertices[0];
+	for (auto v : vertices)
+	{
+		for (int i = 0; i < 3; i++)
+		{
+			minVertex[i] = fmin(minVertex[i], v[i]);
+			maxVertex[i] = fmax(maxVertex[i], v[i]);
+		}
 	}
+	center = (minVertex + maxVertex) / 2.0f;
+	radius = 0;
+	for (auto v : vertices)
+		radius = fmax(radius, (center.x - v.x) * (center.x - v.x) + (center.z - v.z) * (center.z - v.z));
+	radius = sqrt(radius);
+
+
 }
 
 void Model::loadMaterialFile(std::string fileName, std::string dirName)
@@ -327,13 +345,19 @@ Model* Model::load(const std::string &fileName)
 	return cache[fileName].first;
 }
 
-void Model::unload(const std::string & fileName)
+void Model::unload(Model* model)
 {
-	assert(cache.find(fileName) != cache.end());
-	cache[fileName].second--;
-	if (cache[fileName].second == 0)
+	for (auto m : cache)
 	{
-		delete cache[fileName].first;
-		cache.erase(cache.find(fileName));
+		if (m.second.first == model)
+		{
+			m.second.second--;
+			if (m.second.second == 0)
+			{
+				delete m.second.first;
+				cache.erase(cache.find(m.first));
+			}
+
+		}
 	}
 }

+ 7 - 1
Model.h

@@ -71,7 +71,13 @@ public:
 
 	static std::map<std::string, std::pair<Model*, int> > cache;
 	static Model* load(const std::string &fileName);
-	static void unload(const std::string &fileName);
+	static void unload(Model* model);
 
 	void draw();
+
+	Vec3f minVertex;
+	Vec3f maxVertex;
+
+	Vec3f center;
+	float radius;
 };

+ 14 - 1
Player.cpp

@@ -1,9 +1,11 @@
+#define _USE_MATH_DEFINES
+#include <cmath>
 #include "Player.h"
 #include <GL/freeglut.h>
 
 Player::Player()
 {
-
+	speed = 10;
 }
 
 void Player::setCamera()
@@ -13,3 +15,14 @@ void Player::setCamera()
 	glTranslatef(-position.x, -position.y, -position.z);
 
 }
+
+void Player::setPosition(float angle, float fac, bool height)
+{
+	if (height)
+		position.y += angle*fac;
+	else
+	{
+		position.x -= (float)cos((rotation.y + angle) / 180 * M_PI) * fac*speed;
+		position.z -= (float)sin((rotation.y + angle) / 180 * M_PI) * fac*speed;
+	}
+}

+ 4 - 0
Player.h

@@ -12,10 +12,14 @@ public:
 	Player();
 
 	void setCamera();
+	void setPosition(float angle, float fac, bool height);
 
 	Vec3f position;
 	Vec2f rotation;
 
 	Model* leftWeapon;
 	Model* rightWeapon;
+
+
+	float speed;
 };

+ 10 - 0
Vector.cpp

@@ -24,6 +24,16 @@ float& Vec3f::operator [](int index)
 	return v[index];
 }
 
+Vec3f Vec3f::operator+(const Vec3f & other)
+{
+	return Vec3f(x + other.x, y + other.y, z + other.z);
+}
+
+Vec3f Vec3f::operator/(float value)
+{
+	return Vec3f(x / value, y / value, z / value);
+}
+
 
 
 Vec2f::Vec2f(float x, float y)

+ 2 - 0
Vector.h

@@ -15,6 +15,8 @@ public:
 	Vec3f(Vec3f &other);
 	Vec3f(float x, float y, float z);
 	float& operator [](int);
+	Vec3f operator + (const Vec3f &other);
+	Vec3f operator / (float value);
 };
 
 class Vec2f

+ 40 - 3
World.cpp

@@ -1,12 +1,35 @@
 #include "World.h"
 #include <GL/freeglut.h>
 #include "Entity.h"
+#include "LevelObject.h"
+#include "json.h"
+#include <fstream>
 
 World::World() : player(Player::getInstance())
 {
-	player.position.y = 1.7;
+	json::Value v = json::readJson(std::ifstream("worlds/world1.json"));
 
-	//entities.push_back(new LevelObject("tree"));
+	player.position.x = v["player"]["startposition"][0];
+	player.position.y = v["player"]["startposition"][1];
+	player.position.z = v["player"]["startposition"][2];
+
+	for (auto object : v["objects"])
+	{
+		bool hasCollision = true;
+		if (!object["collide"].isNull())
+			hasCollision = object["collide"].asBool();
+
+		Vec3f rotation(0, 0, 0);
+		if(!object["rot"].isNull())
+			rotation = Vec3f(object["rot"][0], object["rot"][1], object["rot"][2]);
+
+		float scale = 1;
+		if (!object["scale"].isNull())
+			scale = object["scale"].asFloat();
+		
+		Vec3f position(object["pos"][0], object["pos"][1], object["pos"][2]);
+		entities.push_back(new LevelObject(object["file"], position, rotation, scale, hasCollision));
+	}
 }
 
 
@@ -18,8 +41,13 @@ void World::draw()
 {
 	player.setCamera();
 
+	float lightPosition[4] = { 0, 2, 1, 0 };
+	glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
+	float lightAmbient[4] = { 0.5, 0.5, 0.5, 1 };
+	glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
 
 	glColor3f(0.5f, 0.9f, 0.5f);
+	glNormal3f(0, 1, 0);
 	glBegin(GL_QUADS);
 	glVertex3f(-50, 0, -50);
 	glVertex3f(-50, 0, 50);
@@ -30,7 +58,6 @@ void World::draw()
 	for (auto e : entities)
 		e->draw();
 
-	glutSwapBuffers();
 }
 
 void World::update(float elapsedTime)
@@ -38,3 +65,13 @@ void World::update(float elapsedTime)
 	for (auto e : entities)
 		e->update(elapsedTime);
 }
+
+bool World::isPlayerPositionValid()
+{
+	for (auto e : entities)
+	{
+		if (e->canCollide && e->inObject(player.position))
+			return false;
+	}
+	return true;
+}

+ 1 - 1
World.h

@@ -17,6 +17,6 @@ public:
 
 	void draw();
 	void update(float elapsedTime);
-
+	bool isPlayerPositionValid();
 };
 

+ 770 - 0
json.cpp

@@ -0,0 +1,770 @@
+#include "json.h"
+#include <iomanip>
+#include <sstream>
+#include <iostream>
+#include <cmath>
+#include <cfloat>
+#include <set>
+#include <regex>
+
+namespace json
+{
+
+	Value Value::null;
+	//constructors
+	Value::Value()
+	{
+		type = Type::nullValue;
+		value.objectValue = NULL;
+	}
+
+	Value::Value(Type type)
+	{
+		this->type = type;
+		if (type == Type::stringValue)
+			value.stringValue = new std::string();
+		if (type == Type::arrayValue)
+			value.arrayValue = new std::vector<Value>();
+		if (type == Type::objectValue)
+			value.objectValue = new std::map<std::string, Value>();
+	}
+
+	Value::Value(int value)
+	{
+		type = Type::intValue;
+		this->value.intValue = value;
+	}
+
+	Value::Value(__int64 value)
+	{
+		//todo: value too big ?
+		type = Type::intValue;
+		this->value.intValue = value;
+	}
+
+	Value::Value(float value)
+	{
+		type = Type::floatValue;
+		this->value.floatValue = value;
+	}
+
+	Value::Value(bool value)
+	{
+		type = Type::boolValue;
+		this->value.boolValue = value;
+	}
+
+	Value::Value(const std::string &value)
+	{
+		type = Type::stringValue;
+		this->value.stringValue = new std::string();
+		this->value.stringValue->assign(value);
+	}
+	Value::Value(const char* value)
+	{
+		type = Type::stringValue;
+		this->value.stringValue = new std::string();
+		this->value.stringValue->assign(value);
+	}
+
+	Value::Value(const Value& other) : Value(other.type)
+	{
+		if (type == Type::objectValue)
+			*this->value.objectValue = *other.value.objectValue;
+		else if (type == Type::arrayValue)
+			*this->value.arrayValue = *other.value.arrayValue;
+		else if (type == Type::stringValue)
+			this->value.stringValue->assign(*other.value.stringValue);
+		else
+			this->value = other.value;
+	}
+
+	void Value::operator=(const Value& other)
+	{
+		if (type != other.type)
+		{
+			if (type == Type::stringValue)
+				delete value.stringValue;
+			if (type == Type::arrayValue)
+				delete value.arrayValue;
+			if (type == Type::objectValue)
+				delete value.objectValue;
+			this->type = other.type;
+			if (type == Type::stringValue)
+				value.stringValue = new std::string();
+			if (type == Type::arrayValue)
+				value.arrayValue = new std::vector<Value>();
+			if (type == Type::objectValue)
+				value.objectValue = new std::map<std::string, Value>();
+		}
+
+		if (type == Type::objectValue)
+			*this->value.objectValue = *other.value.objectValue;
+		else if (type == Type::arrayValue)
+			*this->value.arrayValue = *other.value.arrayValue;
+		else if (type == Type::stringValue)
+			this->value.stringValue->assign(*other.value.stringValue);
+		else
+			this->value = other.value;
+	}
+
+	Value::~Value()
+	{
+		if (type == Type::stringValue)
+			delete value.stringValue;
+		else if (type == Type::arrayValue)
+			delete value.arrayValue;
+		else if (type == Type::objectValue)
+			delete value.objectValue;
+	}
+
+	size_t Value::size() const
+	{
+		assert(type == Type::arrayValue || type == Type::objectValue);
+		if (type == Type::arrayValue)
+			return value.arrayValue->size();
+		else if (type == Type::objectValue)
+			return value.objectValue->size();
+		throw "Unsupported";
+	}
+
+	void Value::push_back(const Value& value)
+	{
+		assert(type == Type::arrayValue || type == Type::nullValue);
+		if (type == Type::nullValue)
+		{
+			type = Type::arrayValue;
+			this->value.arrayValue = new std::vector<Value>();
+		}
+		this->value.arrayValue->push_back(value);
+	}
+
+
+	Value& Value::operator[](const std::string &key)
+	{
+		assert(type == Type::objectValue || type == Type::nullValue);
+		if (type == Type::nullValue)
+		{
+			type = Type::objectValue;
+			value.objectValue = new std::map<std::string, Value>();
+		}
+		return (*value.objectValue)[key];
+	}
+	Value& Value::operator[](const std::string &key) const
+	{
+		assert(type == Type::objectValue);
+		return (*value.objectValue)[key];
+	}
+
+	Value& Value::operator[](const char* key)
+	{
+		assert(type == Type::objectValue || type == Type::nullValue);
+		if (type == Type::nullValue)
+		{
+			type = Type::objectValue;
+			value.objectValue = new std::map<std::string, Value>();
+		}
+		return (*value.objectValue)[std::string(key)];
+	}
+
+	Value& Value::operator[](const char* key) const
+	{
+		assert(type == Type::objectValue);
+		return (*value.objectValue)[std::string(key)];
+	}
+
+	Value& Value::operator[](size_t index)
+	{
+		assert(type == Type::arrayValue);
+		return (*value.arrayValue)[index];
+	}
+	Value& Value::operator[](size_t index) const
+	{
+		assert(type == Type::arrayValue);
+		return (*value.arrayValue)[index];
+	}
+	Value& Value::operator[](int index)
+	{
+		assert(type == Type::arrayValue);
+		return (*value.arrayValue)[index];
+	}
+	Value& Value::operator[](int index) const
+	{
+		assert(type == Type::arrayValue);
+		return (*value.arrayValue)[index];
+	}
+
+	void Value::erase(size_t index)
+	{
+		throw "Cannot cast";
+	}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	Value::Iterator Value::end() const
+	{
+		if (type == Type::objectValue)
+			return Iterator(value.objectValue->end());
+		else if (type == Type::arrayValue)
+			return Iterator(value.arrayValue->end());
+		throw "oops";
+	}
+
+	Value::Iterator Value::begin() const
+	{
+		if (type == Type::objectValue)
+			return Iterator(value.objectValue->begin());
+		else if (type == Type::arrayValue)
+			return Iterator(value.arrayValue->begin());
+		throw "oops";
+	}
+
+	///iterator stuff
+
+	Value Value::Iterator::operator*()
+	{
+		if (type == Type::objectValue)
+			return this->objectIterator->second;
+		else  if (type == Type::arrayValue)
+			return *arrayIterator;
+		throw "Oops";
+	}
+
+	bool Value::Iterator::operator!=(const Iterator &other)
+	{
+		if (type == Type::objectValue)
+			return this->objectIterator != other.objectIterator;
+		else  if (type == Type::arrayValue)
+			return this->arrayIterator != other.arrayIterator;
+		throw "Oops";
+	}
+
+	void Value::Iterator::operator++()
+	{
+		if (type == Type::objectValue)
+			this->objectIterator++;
+		else  if (type == Type::arrayValue)
+			this->arrayIterator++;
+	}
+	void Value::Iterator::operator++(int)
+	{
+		if (type == Type::objectValue)
+			this->objectIterator++;
+		else  if (type == Type::arrayValue)
+			this->arrayIterator++;
+	}
+
+	Value::Iterator::Iterator(const std::vector<Value>::iterator& arrayIterator)
+	{
+		type = Type::arrayValue;
+		this->arrayIterator = arrayIterator;
+	}
+
+	Value::Iterator::Iterator(const std::map<std::string, Value>::iterator& objectIterator)
+	{
+		type = Type::objectValue;
+		this->objectIterator = objectIterator;
+	}
+
+	std::string Value::Iterator::key()
+	{
+		assert(type == Type::objectValue);
+		return this->objectIterator->first;
+	}
+	Value& Value::Iterator::value()
+	{
+		assert(type == Type::objectValue);
+		return this->objectIterator->second;
+	}
+
+
+
+
+
+
+
+	static int lineNumber;
+
+	static void ltrim(std::istream& stream);
+	static void eatComment(std::istream& stream);
+	static Value eatString(std::istream& stream);
+	static Value eatObject(std::istream& stream);
+	static Value eatArray(std::istream& stream);
+	static Value eatNumeric(std::istream& stream, char firstChar);
+	static Value eatBool(std::istream& stream);
+	static Value eatNull(std::istream& stream);
+	static Value eatValue(std::istream& stream);
+
+	//reading
+	static void ltrim(std::istream& stream)
+	{
+		char c = stream.peek();
+		while (c == ' ' || c == '\t' || c == '\n' || c == '\r')
+		{
+			if (c == '\n')
+				lineNumber++;
+			stream.get();
+			c = stream.peek();
+		}
+	};
+
+
+	static Value eatString(std::istream& stream)
+	{
+		std::string value = "";
+		bool escaped = false;
+		while (!stream.eof())
+		{
+			char c = stream.get();
+			if (c == '\\' && !escaped)
+				escaped = !escaped;
+			else if (c == '\"' && !escaped)
+				return Value(value);
+			else
+			{
+				value += c;
+				escaped = false;
+			}
+		}
+		return Value(value);
+	};
+
+
+
+
+	static Value eatObject(std::istream& stream)
+	{
+		Value obj(Type::objectValue);
+		while (!stream.eof())
+		{
+			ltrim(stream);
+			char token = stream.get();
+			if (token == '}')
+				break; //empty object
+			if (token == '/')
+			{
+				eatComment(stream);
+				token = stream.get();
+			}
+
+			assert(token == '"');
+			Value key = eatString(stream);
+			ltrim(stream);
+			token = stream.get();
+			assert(token == ':');
+			ltrim(stream);
+			Value val = eatValue(stream);
+			obj[key.asString()] = val;
+			ltrim(stream);
+
+			token = stream.get();
+			if (token == '}')
+				break;
+			if (token != ',')
+				throw "arg";
+			assert(token == ',');
+		}
+		return obj;
+	};
+	static Value eatArray(std::istream& stream)
+	{
+		Value obj(Type::arrayValue);
+		while (!stream.eof())
+		{
+			ltrim(stream);
+			if (stream.peek() == ']')
+			{
+				stream.get();
+				break;
+			}
+			obj.push_back(eatValue(stream));
+			ltrim(stream);
+			char token = stream.get();
+			if (token == '/')
+			{
+				eatComment(stream);
+				token = stream.get();
+			}
+			if (token == ']')
+				break;
+			assert(token == ',');
+		}
+		return obj;
+	};
+	static Value eatNumeric(std::istream& stream, char firstChar)
+	{
+		std::string numeric(1, firstChar);
+		while (!stream.eof())
+		{
+			char token = stream.peek();
+			if ((token >= '0' && token <= '9') || token == '.' || token == '-' || token == 'E')
+				numeric += stream.get();
+			else
+				break;
+		}
+		if (numeric.find('.') == std::string::npos)
+			return Value(atoi(numeric.c_str()));
+		else
+			return Value((float)atof(numeric.c_str()));
+	};
+
+	static Value eatBool(std::istream& stream)
+	{
+		char token = stream.get();
+		if (token == 'a') //fAlse
+		{
+			stream.get(); //l
+			stream.get(); //s
+			stream.get(); //e
+			return false;
+		}
+		else if (token == 'r') //tRue
+		{
+			stream.get(); // u
+			stream.get(); // e
+			return true;
+		}
+		return Value(Type::nullValue);
+	};
+	static Value eatNull(std::istream& stream)
+	{
+		stream.get(); // u
+		stream.get(); // l
+		stream.get(); // l
+		return Value(Type::nullValue);
+	};
+
+	//precondition: / is already eaten
+	static void eatComment(std::istream& stream)
+	{
+		char token = stream.get();
+		assert(token == '/' || token == '*');
+		if (token == '*')
+		{
+			char last = token;
+			while ((last != '*' || token != '/') && !stream.eof())
+			{
+				last = token;
+				token = stream.get();
+			}
+		}
+		else if (token == '/')
+			while (token != '\n' && !stream.eof())
+				token = stream.get();
+		ltrim(stream);
+	}
+
+
+	static Value eatValue(std::istream& stream)
+	{
+		ltrim(stream);
+		char token = stream.get();
+		if (token == '{')
+			return eatObject(stream);
+		if (token == '[')
+			return eatArray(stream);
+		if ((token >= '0' && token <= '9') || token == '.' || token == '-')
+			return eatNumeric(stream, token);
+		if (token == '"')
+			return eatString(stream);
+		if (token == 't' || token == 'f')
+			return eatBool(stream);
+		if (token == 'n')
+			return eatNull(stream);
+		if (token == '/')
+		{
+			eatComment(stream);
+			return eatValue(stream);
+		}
+		throw "Unable to parse json";
+	};
+
+
+	Value readJson(const std::string &data)
+	{
+		std::stringstream stream;
+		stream << data;
+		lineNumber = 1;
+		return eatValue(stream);
+	}
+
+	Value readJson(std::istream &stream)
+	{
+		assert(!stream.eof() && stream.good() && !stream.bad());
+		lineNumber = 1;
+		return eatValue(stream);
+	}
+
+
+
+	std::ostream& indent(std::ostream& stream, int level)
+	{
+		for (int i = 0; i < level; i++)
+			stream << '\t';
+		return stream;
+	}
+
+	std::ostream& Value::prettyPrint(std::ostream& stream, json::Value& printConfig, int level) const
+	{
+		stream << std::fixed << std::setprecision(6);
+		switch (type)
+		{
+		case Type::intValue:
+			stream << value.intValue;
+			break;
+		case Type::floatValue:
+			assert(!isnan(value.floatValue));
+			//assert(isnormal(value.floatValue));
+			if (value.floatValue >= 0)
+				stream << " ";
+			stream << value.floatValue;
+			break;
+		case Type::boolValue:
+			stream << (value.boolValue ? "true" : "false");
+			break;
+		case Type::stringValue:
+			stream << "\"" << *value.stringValue << "\""; //TODO: escape \'s
+			break;
+		case Type::arrayValue:
+		{
+			stream << "[";
+			int wrap = 99999;
+			if (value.arrayValue->size() > 10)
+				wrap = 1;
+			if (value.arrayValue->at(0).isArray() || value.arrayValue->at(0).isObject())
+				wrap = 1;
+			else
+				wrap = 3;
+
+			std::string seperator = " ";
+
+			if (!printConfig.isNull() && printConfig.isMember("wrap"))
+				wrap = printConfig["wrap"];
+			if (!printConfig.isNull() && printConfig.isMember("seperator"))
+				seperator = printConfig["seperator"].asString();
+
+
+			int index = 0;
+
+			if ((long)size() > wrap)
+			{
+				stream << "\n";
+				indent(stream, level + 1);
+			}
+			for (auto v : *this)
+			{
+				if (index > 0)
+				{
+					stream << "," << seperator;
+					if (index % wrap == 0)
+					{
+						stream << "\n";
+						indent(stream, level + 1);
+					}
+				}
+
+				json::Value childPrintConfig = json::Value::null;
+				if (!printConfig.isNull())
+				{
+					if (printConfig.isMember("elements"))
+						childPrintConfig = printConfig["elements"];
+					else if (printConfig.isMember("recursive") && printConfig["recursive"].asBool() == true)
+						childPrintConfig = printConfig;
+				}
+
+				v.prettyPrint(stream, childPrintConfig, level + 1);
+				index++;
+			}
+			if ((long)size() > wrap)
+			{
+				stream << "\n";
+				indent(stream, level);
+			}
+			stream << "]";
+			break;
+		}
+		case Type::objectValue:
+		{
+			stream << "{\n";
+			int wrap = 99999;
+			if (value.arrayValue->size() > 10)
+				wrap = 1;
+			if (value.arrayValue->at(0).isArray() || value.arrayValue->at(0).isObject())
+				wrap = 1;
+			else
+				wrap = 3;
+
+			std::string seperator = " ";
+
+			if (!printConfig.isNull() && printConfig.isMember("wrap"))
+				wrap = printConfig["wrap"];
+			if (!printConfig.isNull() && printConfig.isMember("seperator"))
+				seperator = printConfig["seperator"].asString();
+
+
+			int index = 0;
+			indent(stream, level + 1);
+
+
+
+			//for (auto v : *value.objectValue)
+			auto printEl = [&](const std::pair<const std::string&, const Value&> v)
+			{
+				if (index > 0)
+				{
+					stream << "," << seperator;
+					if (index % wrap == 0)
+					{
+						stream << "\n";
+						indent(stream, level + 1);
+					}
+				}
+				stream << "\"" << v.first << "\" : ";
+				if (
+					(v.second.isArray() || v.second.isObject()) &&
+					(printConfig.isNull() ||
+						(
+							printConfig.isMember(v.first) &&
+							printConfig[v.first].isObject() &&
+							printConfig[v.first].isMember("wrap") &&
+							printConfig[v.first]["wrap"].asInt() < (int)v.second.size())
+						)
+					)
+				{
+					stream << "\n";
+					indent(stream, level + 1);
+				}
+
+				json::Value childPrintConfig = json::Value::null;
+				if (!printConfig.isNull())
+				{
+					if (printConfig.isMember(v.first))
+						childPrintConfig = printConfig[v.first];
+					else if (printConfig.isMember("recursive") && printConfig["recursive"].asBool() == true)
+						childPrintConfig = printConfig;
+				}
+
+				v.second.prettyPrint(stream, childPrintConfig, level + 1);;
+				index++;
+			};
+
+
+
+			std::set<std::string> printed;
+			if (!printConfig.isNull())
+			{
+				if (printConfig.isMember("sort"))
+				{
+					for (std::string el : printConfig["sort"])
+					{
+						if (isMember(el))
+						{
+							printEl(std::pair<const std::string&, const Value&>(el, (*value.objectValue)[el]));
+							printed.insert(el);
+						}
+					}
+				}
+			}
+
+			for (auto v : *value.objectValue)
+				if (printed.find(v.first) == printed.end())
+					printEl(v);
+
+			stream << "\n";
+			indent(stream, level);
+			stream << "}";
+			break;
+		}
+		case Type::nullValue:
+			stream << "null";
+			break;
+		}
+		return stream;
+	}
+
+	const Value& Value::get(const char* key, const Value& default) const
+	{
+		if (isMember(key))
+			return (*this)[key];
+		return default;
+	}
+
+
+	std::string& operator <<(std::string &string, const Value& value)
+	{
+		std::stringstream stream;
+		stream << value;
+		string += stream.str();
+		return string;
+	}
+
+
+	std::ostream & operator<<(std::ostream &stream, const Value& value)
+	{
+		stream << std::fixed << std::setprecision(6);
+		switch (value.type)
+		{
+		case Type::intValue:
+			stream << value.value.intValue;
+			break;
+		case Type::floatValue:
+			assert(!isnan(value.value.floatValue));
+			//assert(isnormal(value.value.floatValue));
+			stream << value.value.floatValue;
+			break;
+		case Type::boolValue:
+			stream << (value.value.boolValue ? "true" : "false");
+			break;
+		case Type::stringValue:
+		{
+			std::string escaped = *value.value.stringValue;
+			escaped = std::regex_replace(escaped, std::regex("\\\\"), "\\\\");
+			stream << "\"" << escaped << "\""; //TODO: escape \'s
+			break;
+		}
+		case Type::arrayValue:
+		{
+			stream << "[";
+			bool first = true;
+			for (auto v : value)
+			{
+				if (!first)
+					stream << ", ";
+				stream << v;
+				first = false;
+			}
+			stream << "]";
+			break;
+		}
+		case Type::objectValue:
+		{
+			stream << "{";
+			bool first = true;
+			for (auto v : *value.value.objectValue)
+			{
+				if (!first)
+					stream << ", ";
+				stream << "\"" << v.first << "\" : " << v.second << std::endl;
+				first = false;
+			}
+			stream << "}";
+			break;
+		}
+		case Type::nullValue:
+			stream << "null";
+			break;
+		}
+		return stream;
+	}
+}

+ 132 - 0
json.h

@@ -0,0 +1,132 @@
+#pragma once
+
+#include <string>
+#include <map>
+#include <vector>
+#include <assert.h>
+
+namespace json
+{
+	enum class Type
+	{
+		intValue,
+		floatValue,
+		boolValue,
+		stringValue,
+		arrayValue,
+		objectValue,
+		nullValue
+	};
+
+	class Value
+	{
+	public:
+		Type type;
+		union ValueHolder
+		{
+			int								intValue;
+			float							floatValue;
+			bool							boolValue;
+			std::string*					stringValue;
+			std::vector<Value>*				arrayValue;
+			std::map<std::string, Value>*	objectValue;
+		} value;
+
+		static Value null;
+
+		Value();
+		Value(Type type);
+		Value(int value);
+		Value(__int64 value);
+		Value(float value);
+		Value(bool value);
+		Value(const std::string &value);
+		Value(const char* value);
+		Value(const Value& other);
+		virtual ~Value();
+
+		void operator = (const Value& other);
+
+
+
+
+		inline operator int() const { return asInt(); }
+		inline operator float()	const { return asFloat(); }
+		inline operator bool() const { return asBool(); }
+		inline operator const std::string&() const { return asString(); }
+
+
+		inline int asInt() const { assert(type == Type::intValue); return value.intValue; }
+		inline float asFloat() const { assert(type == Type::floatValue || type == Type::intValue); return type == Type::floatValue ? value.floatValue : value.intValue; }
+		inline bool asBool() const { assert(type == Type::boolValue); return value.boolValue; }
+		inline const std::string& asString() const { assert(type == Type::stringValue); return *value.stringValue; }
+		inline bool isNull() const { return type == Type::nullValue; }
+		inline bool isString() const { return type == Type::stringValue; }
+		inline bool isInt() const { return type == Type::intValue; }
+		inline bool isBool() const { return type == Type::boolValue; }
+		inline bool isFloat() const { return type == Type::floatValue; }
+		inline bool isObject() const { return type == Type::objectValue; }
+		inline bool isArray() const { return type == Type::arrayValue; }
+		inline bool isMember(const std::string &name) const { if (type != Type::objectValue) return false; return value.objectValue->find(name) != value.objectValue->end(); }
+		//array/object
+		virtual size_t size() const;
+		//array
+		virtual void push_back(const Value& value);
+		virtual void erase(size_t index);
+		virtual Value& operator [] (size_t index);
+		virtual Value& operator [] (int index);
+		virtual Value& operator [] (size_t index) const;
+		virtual Value& operator [] (int index) const;
+
+		virtual Value& operator [] (const std::string &key);
+		virtual Value& operator [] (const char* key);
+		virtual Value& operator [] (const std::string &key) const;
+		virtual Value& operator [] (const char* key) const;
+
+		virtual const Value& get(const char* key, const Value& default) const;
+
+		virtual bool operator == (const std::string &other) { return asString() == other; }
+		virtual bool operator == (const int other) { return asInt() == other; }
+		virtual bool operator == (const float other) { return asFloat() == other; }
+
+
+		std::ostream& prettyPrint(std::ostream& stream, json::Value& printConfig = null, int level = 0) const;
+
+		class Iterator;
+	private:
+
+	public:
+		Iterator begin() const;
+		Iterator end() const;
+	};
+
+	class Value::Iterator
+	{
+	private:
+		Type type;
+		std::map<std::string, Value>::iterator objectIterator;
+		std::vector<Value>::iterator arrayIterator;
+	public:
+		Iterator(const std::map<std::string, Value>::iterator& objectIterator);
+		Iterator(const std::vector<Value>::iterator& arrayIterator);
+
+		void operator ++();
+		void operator ++(int);
+		bool operator != (const Iterator &other);
+		Value operator*();
+
+		std::string key();
+		Value& value();
+
+	};
+
+
+
+	Value readJson(const std::string &data);
+	Value readJson(std::istream &stream);
+	std::ostream &operator << (std::ostream &stream, const Value& value);	//serializes json data
+	std::string &operator << (std::string &stream, const Value& value);	//serializes json data
+
+
+
+}

+ 192 - 0
models/boom/Boom.mtl

@@ -0,0 +1,192 @@
+newmtl initialShadingGroup
+illum 4
+Kd 0.21 0.09 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl lambert2SG
+illum 4
+Kd 0.00 1.00 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl lambert3SG
+illum 4
+Kd 0.50 0.21 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl lambert4SG
+illum 4
+Kd 0.50 0.21 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl lambert5SG
+illum 4
+Kd 0.00 0.16 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl lambert6SG
+illum 4
+Kd 0.00 0.16 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl lambert8SG
+illum 4
+Kd 0.00 0.16 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl lambert9SG
+illum 4
+Kd 1.00 1.00 1.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl lambert10SG
+illum 4
+Kd 0.12 0.28 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl lambert11SG
+illum 4
+Kd 0.50 0.21 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert2SG
+illum 4
+Kd 0.00 1.00 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert2SG1
+illum 4
+Kd 0.00 1.00 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert2SG2
+illum 4
+Kd 0.00 1.00 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert2SG3
+illum 4
+Kd 0.00 1.00 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert2SG4
+illum 4
+Kd 0.00 1.00 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert3SG
+illum 4
+Kd 0.50 0.21 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert3SG1
+illum 4
+Kd 0.50 0.21 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert3SG2
+illum 4
+Kd 0.50 0.21 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert3SG3
+illum 4
+Kd 0.50 0.21 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert3SG4
+illum 4
+Kd 0.50 0.21 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert4SG
+illum 4
+Kd 0.50 0.21 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert4SG1
+illum 4
+Kd 0.50 0.21 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert4SG2
+illum 4
+Kd 0.50 0.21 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert5SG
+illum 4
+Kd 0.00 0.16 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert5SG1
+illum 4
+Kd 0.00 0.16 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert5SG2
+illum 4
+Kd 0.00 0.16 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert6SG
+illum 4
+Kd 0.00 0.16 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert6SG1
+illum 4
+Kd 0.00 0.16 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert6SG2
+illum 4
+Kd 0.00 0.16 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert8SG
+illum 4
+Kd 0.00 0.16 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert8SG1
+illum 4
+Kd 0.00 0.16 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00
+newmtl pasted__lambert8SG2
+illum 4
+Kd 0.00 0.16 0.00
+Ka 0.00 0.00 0.00
+Tf 1.00 1.00 1.00
+Ni 1.00

+ 243 - 0
models/boom/Boom.obj

@@ -0,0 +1,243 @@
+# This file uses centimeters as units for non-parametric coordinates.
+
+mtllib Boom.mtl
+g default
+v 8.891173 1.289464 2.183208
+v 6.060002 1.289464 2.982580
+v 5.945371 1.289464 5.922204
+v 8.705695 1.289464 6.939618
+v 10.526301 1.289464 4.628792
+v 8.025709 4.070336 4.531281
+v 8.546361 2.777066 2.928877
+v 6.662623 2.777066 3.540941
+v 6.662623 2.777066 5.521620
+v 8.546361 2.777066 6.133684
+v 9.710575 2.777066 4.531281
+v 8.025709 4.889092 4.531281
+v 8.358277 3.919804 3.507741
+v 7.155033 3.919804 3.898698
+v 7.155033 3.919804 5.163863
+v 8.358277 3.919804 5.554821
+v 9.101922 3.919804 4.531281
+v 8.025709 5.919804 4.531281
+v 8.135743 -0.024354 4.192630
+v 7.737635 -0.024354 4.321983
+v 7.737635 -0.024354 4.740578
+v 8.135743 -0.024354 4.869931
+v 8.381787 -0.024354 4.531281
+v 8.135743 2.286371 4.192630
+v 7.737635 2.286371 4.321983
+v 7.737635 2.286371 4.740578
+v 8.135743 2.286371 4.869931
+v 8.381787 2.286371 4.531281
+v 8.025709 -0.024354 4.531281
+v 8.025709 2.286371 4.531281
+vt 0.577254 0.012236
+vt 0.297746 0.103054
+vt 0.297746 0.396946
+vt 0.577254 0.487764
+vt 0.750000 0.250000
+vt 0.250000 0.500000
+vt 0.350000 0.500000
+vt 0.450000 0.500000
+vt 0.550000 0.500000
+vt 0.650000 0.500000
+vt 0.750000 0.500000
+vt 0.500000 1.000000
+vt 0.577254 0.012236
+vt 0.750000 0.250000
+vt 0.577254 0.487764
+vt 0.297746 0.396946
+vt 0.297746 0.103054
+vt 0.250000 0.500000
+vt 0.350000 0.500000
+vt 0.500000 1.000000
+vt 0.450000 0.500000
+vt 0.550000 0.500000
+vt 0.650000 0.500000
+vt 0.750000 0.500000
+vt 0.577254 0.012236
+vt 0.750000 0.250000
+vt 0.577254 0.487764
+vt 0.297746 0.396946
+vt 0.297746 0.103054
+vt 0.250000 0.500000
+vt 0.350000 0.500000
+vt 0.500000 1.000000
+vt 0.450000 0.500000
+vt 0.550000 0.500000
+vt 0.650000 0.500000
+vt 0.750000 0.500000
+vt 0.375000 0.312500
+vt 0.425000 0.312500
+vt 0.425000 0.688440
+vt 0.375000 0.688440
+vt 0.475000 0.312500
+vt 0.475000 0.688440
+vt 0.525000 0.312500
+vt 0.525000 0.688440
+vt 0.575000 0.312500
+vt 0.575000 0.688440
+vt 0.625000 0.312500
+vt 0.625000 0.688440
+vt 0.373591 0.064409
+vt 0.548284 0.007647
+vt 0.500000 0.150000
+vt 0.373591 0.248091
+vt 0.548284 0.304853
+vt 0.656250 0.156250
+vt 0.548284 0.992353
+vt 0.373591 0.935591
+vt 0.500000 0.837500
+vt 0.373591 0.751909
+vt 0.548284 0.695147
+vt 0.656250 0.843750
+vn 0.000000 -1.000000 -0.000000
+vn 0.000000 -1.000000 -0.000000
+vn 0.000000 -1.000000 -0.000000
+vn 0.000000 -1.000000 -0.000000
+vn 0.000000 -1.000000 -0.000000
+vn -0.219674 0.588572 -0.778027
+vn -0.219674 0.588572 -0.778027
+vn -0.219674 0.588572 -0.778027
+vn -0.807831 0.588572 -0.031502
+vn -0.807831 0.588572 -0.031502
+vn -0.807831 0.588572 -0.031502
+vn -0.279593 0.588572 0.758558
+vn -0.279593 0.588572 0.758558
+vn -0.279593 0.588572 0.758558
+vn 0.635033 0.588572 0.500316
+vn 0.635033 0.588572 0.500316
+vn 0.635033 0.588572 0.500316
+vn 0.672065 0.588572 -0.449346
+vn 0.672065 0.588572 -0.449346
+vn 0.672065 0.588572 -0.449345
+vn 0.000000 -1.000000 -0.000000
+vn 0.000000 -1.000000 -0.000000
+vn 0.000000 -1.000000 -0.000000
+vn 0.000000 -1.000000 -0.000000
+vn 0.000000 -1.000000 -0.000000
+vn -0.259639 0.542264 -0.799085
+vn -0.259639 0.542264 -0.799085
+vn -0.259639 0.542264 -0.799085
+vn -0.840208 0.542264 0.000000
+vn -0.840208 0.542264 0.000000
+vn -0.840208 0.542264 0.000000
+vn -0.259639 0.542264 0.799085
+vn -0.259639 0.542264 0.799085
+vn -0.259639 0.542264 0.799085
+vn 0.679743 0.542264 0.493862
+vn 0.679743 0.542264 0.493862
+vn 0.679743 0.542264 0.493862
+vn 0.679743 0.542264 -0.493862
+vn 0.679743 0.542264 -0.493862
+vn 0.679743 0.542264 -0.493862
+vn 0.000000 -1.000000 0.000000
+vn 0.000000 -1.000000 0.000000
+vn 0.000000 -1.000000 0.000000
+vn 0.000000 -1.000000 0.000000
+vn 0.000000 -1.000000 0.000000
+vn -0.283333 0.399154 -0.872008
+vn -0.283333 0.399154 -0.872008
+vn -0.283333 0.399154 -0.872008
+vn -0.916884 0.399154 -0.000000
+vn -0.916884 0.399154 -0.000000
+vn -0.916884 0.399154 -0.000000
+vn -0.283333 0.399154 0.872008
+vn -0.283333 0.399154 0.872008
+vn -0.283333 0.399154 0.872008
+vn 0.741775 0.399154 0.538931
+vn 0.741775 0.399154 0.538931
+vn 0.741775 0.399154 0.538931
+vn 0.741775 0.399154 -0.538931
+vn 0.741775 0.399154 -0.538931
+vn 0.741775 0.399154 -0.538931
+vn -0.309017 0.000000 -0.951057
+vn -0.309017 0.000000 -0.951057
+vn -0.309017 0.000000 -0.951057
+vn -0.309017 0.000000 -0.951057
+vn -1.000000 0.000000 -0.000000
+vn -1.000000 0.000000 -0.000000
+vn -1.000000 0.000000 -0.000000
+vn -1.000000 0.000000 -0.000000
+vn -0.309017 0.000000 0.951057
+vn -0.309017 0.000000 0.951057
+vn -0.309017 0.000000 0.951057
+vn -0.309017 0.000000 0.951057
+vn 0.809017 0.000000 0.587785
+vn 0.809017 0.000000 0.587785
+vn 0.809017 0.000000 0.587785
+vn 0.809017 0.000000 0.587785
+vn 0.809017 0.000000 -0.587785
+vn 0.809017 0.000000 -0.587785
+vn 0.809017 0.000000 -0.587785
+vn 0.809017 0.000000 -0.587785
+vn 0.000000 -1.000000 0.000000
+vn 0.000000 -1.000000 0.000000
+vn 0.000000 -1.000000 0.000000
+vn 0.000000 -1.000000 0.000000
+vn 0.000000 -1.000000 0.000000
+vn 0.000000 -1.000000 0.000000
+vn 0.000000 -1.000000 0.000000
+vn 0.000000 -1.000000 0.000000
+vn 0.000000 -1.000000 0.000000
+vn 0.000000 -1.000000 0.000000
+vn 0.000000 -1.000000 0.000000
+vn 0.000000 -1.000000 0.000000
+vn 0.000000 -1.000000 -0.000000
+vn 0.000000 -1.000000 -0.000000
+vn 0.000000 -1.000000 -0.000000
+vn 0.000000 1.000000 0.000000
+vn 0.000000 1.000000 0.000000
+vn 0.000000 1.000000 0.000000
+vn 0.000000 1.000000 0.000000
+vn 0.000000 1.000000 0.000000
+vn 0.000000 1.000000 0.000000
+vn 0.000000 1.000000 0.000000
+vn 0.000000 1.000000 0.000000
+vn 0.000000 1.000000 0.000000
+vn 0.000000 1.000000 -0.000001
+vn 0.000000 1.000000 -0.000001
+vn 0.000000 1.000000 -0.000001
+vn 0.000000 1.000000 0.000000
+vn 0.000000 1.000000 0.000000
+vn 0.000000 1.000000 0.000000
+s off
+g PineConeTree
+usemtl lambert5SG
+f 1/1/1 5/5/2 4/4/3 3/3/4 2/2/5
+f 1/6/6 2/7/7 6/12/8
+f 2/7/9 3/8/10 6/12/11
+f 3/8/12 4/9/13 6/12/14
+f 4/9/15 5/10/16 6/12/17
+f 5/10/18 1/11/19 6/12/20
+usemtl lambert6SG
+f 7/13/21 11/14/22 10/15/23 9/16/24 8/17/25
+f 7/18/26 8/19/27 12/20/28
+f 8/19/29 9/21/30 12/20/31
+f 9/21/32 10/22/33 12/20/34
+f 10/22/35 11/23/36 12/20/37
+f 11/23/38 7/24/39 12/20/40
+usemtl lambert8SG
+f 13/25/41 17/26/42 16/27/43 15/28/44 14/29/45
+f 13/30/46 14/31/47 18/32/48
+f 14/31/49 15/33/50 18/32/51
+f 15/33/52 16/34/53 18/32/54
+f 16/34/55 17/35/56 18/32/57
+f 17/35/58 13/36/59 18/32/60
+usemtl lambert4SG
+f 19/37/61 20/38/62 25/39/63 24/40/64
+f 20/38/65 21/41/66 26/42/67 25/39/68
+f 21/41/69 22/43/70 27/44/71 26/42/72
+f 22/43/73 23/45/74 28/46/75 27/44/76
+f 23/45/77 19/47/78 24/48/79 28/46/80
+f 20/49/81 19/50/82 29/51/83
+f 21/52/84 20/49/85 29/51/86
+f 22/53/87 21/52/88 29/51/89
+f 23/54/90 22/53/91 29/51/92
+f 19/50/93 23/54/94 29/51/95
+f 24/55/96 25/56/97 30/57/98
+f 25/56/99 26/58/100 30/57/101
+f 26/58/102 27/59/103 30/57/104
+f 27/59/105 28/60/106 30/57/107
+f 28/60/108 24/55/109 30/57/110

+ 16 - 0
models/portal_blue.mtl

@@ -0,0 +1,16 @@
+# WaveFront *.mtl file (generated by CINEMA 4D)
+
+newmtl Mat
+Kd 0.00000000000000 0.76666665077209 1.00000000000000
+d 0
+Tf 1.00000000000000 1.00000000000000 1.00000000000000
+illum 7
+
+newmtl Mat.2
+Kd 0.43200001120567 0.62826669216156 0.80000001192093
+illum 7
+
+newmtl Mat.1
+Kd 0.00000000000000 0.00000000000000 0.80000001192093
+illum 7
+

+ 676 - 0
models/portal_blue.obj

@@ -0,0 +1,676 @@
+# WaveFront *.obj file (generated by CINEMA 4D)
+
+mtllib ./portal_blue.mtl
+
+v 0.00000000000000 -171.96217544392707 0.00000000000000
+v 0.00000000000000 171.96217544392707 0.00000000000000
+v 85.98108772196353 -171.96217544392707 0.00000000000000
+v 85.98108772196353 7.33235190308497 0.00000000000000
+v 85.98108772196353 171.96217544392707 0.00000000000000
+v 65.86533446273555 -171.96217544392707 55.26757785504959
+v 65.86533446273555 7.33235190308497 55.26757785504959
+v 65.86533446273555 171.96217544392707 55.26757785504959
+v 14.93045919673945 -171.96217544392707 84.67484180101245
+v 14.93045919673945 7.33235190308497 84.67484180101245
+v 14.93045919673945 171.96217544392707 84.67484180101245
+v -42.99054386098175 -171.96217544392707 74.46180621223871
+v -42.99054386098175 7.33235190308497 74.46180621223871
+v -42.99054386098175 171.96217544392707 74.46180621223871
+v -80.79579365947500 -171.96217544392707 29.40726394596288
+v -80.79579365947500 7.33235190308497 29.40726394596288
+v -80.79579365947500 171.96217544392707 29.40726394596288
+v -80.79579365947501 -171.96217544392707 -29.40726394596286
+v -80.79579365947501 7.33235190308497 -29.40726394596286
+v -80.79579365947501 171.96217544392707 -29.40726394596286
+v -42.99054386098180 -171.96217544392707 -74.46180621223869
+v -42.99054386098180 7.33235190308497 -74.46180621223869
+v -42.99054386098180 171.96217544392707 -74.46180621223869
+v 14.93045919673942 -171.96217544392707 -84.67484180101246
+v 14.93045919673942 7.33235190308497 -84.67484180101246
+v 14.93045919673942 171.96217544392707 -84.67484180101246
+v 65.86533446273553 -171.96217544392707 -55.26757785504962
+v 65.86533446273553 7.33235190308497 -55.26757785504962
+v 65.86533446273553 171.96217544392707 -55.26757785504962
+# 29 vertices
+
+vn -0.76604445295859 0.00000000000000 0.64278759796015
+vn 0.93969261684974 0.00000000000000 0.34202015414020
+vn 0.50000002562450 0.00000000000000 -0.86602538899013
+vn -1.00000000000000 0.00000000000000 0.00000000000000
+vn 0.50000002562450 0.00000000000000 0.86602538899013
+vn -0.17364817233999 0.00000000000000 -0.98480775395149
+vn -0.76604445295859 0.00000000000000 -0.64278759796015
+vn -0.17364817233999 0.00000000000000 0.98480775395149
+vn 0.93969261684974 0.00000000000000 -0.34202015414020
+# 9 normals
+
+vt 0.33333334326744 -1.00000000000000 0.00000000000000
+vt 0.33333334326744 -0.00000000000000 0.00000000000000
+vt 0.44444444775581 -0.00000000000000 0.00000000000000
+vt 0.44444444775581 -1.00000000000000 0.00000000000000
+vt 0.00000000000000 -1.00000000000000 0.00000000000000
+vt 0.00000000000000 -0.00000000000000 0.00000000000000
+vt 0.11111111193895 -0.00000000000000 0.00000000000000
+vt 0.11111111193895 -1.00000000000000 0.00000000000000
+vt 0.77777779102325 -1.00000000000000 0.00000000000000
+vt 0.77777779102325 -0.00000000000000 0.00000000000000
+vt 0.88888889551163 -0.00000000000000 0.00000000000000
+vt 0.88888889551163 -1.00000000000000 0.00000000000000
+vt 0.55555558204651 -0.00000000000000 0.00000000000000
+vt 0.55555558204651 -1.00000000000000 0.00000000000000
+vt 0.22222222387791 -0.00000000000000 0.00000000000000
+vt 0.22222222387791 -1.00000000000000 0.00000000000000
+vt 0.66666668653488 -1.00000000000000 0.00000000000000
+vt 0.66666668653488 -0.00000000000000 0.00000000000000
+vt 1.00000000000000 -0.00000000000000 0.00000000000000
+vt 1.00000000000000 -1.00000000000000 0.00000000000000
+# 20 texture coordinates
+
+o Cylinder
+usemtl Mat
+f 13/1/1 14/2/1 17/3/1 16/4/1
+f 4/5/2 5/6/2 8/7/2 7/8/2
+f 25/9/3 26/10/3 29/11/3 28/12/3
+f 16/4/4 17/3/4 20/13/4 19/14/4
+f 7/8/5 8/7/5 11/15/5 10/16/5
+f 22/17/6 23/18/6 26/10/6 25/9/6
+f 19/14/7 20/13/7 23/18/7 22/17/7
+f 10/16/8 11/15/8 14/2/8 13/1/8
+f 28/12/9 29/11/9 5/19/9 4/20/9
+
+v -93.96926207859083 10.00000000000000 34.20201433256689
+v 0.01217485718138 11.00001403290715 -0.01021591817053
+v 76.60444431189778 0.00000000000000 -64.27876096865396
+v 76.60444431189778 2.50000000000000 -64.27876096865396
+v 76.60444431189778 5.00000000000000 -64.27876096865396
+v -50.00000000000004 0.00000000000000 -86.60254037844383
+v -50.00000000000004 2.50000000000000 -86.60254037844383
+v -50.00000000000004 5.00000000000000 -86.60254037844383
+v -82.30250693287560 12.34005811377603 29.95566272905449
+v -50.00000000000004 7.50000000000000 -86.60254037844383
+v -50.00000000000004 10.00000000000000 -86.60254037844383
+v -43.79224924850548 12.34005811377603 -75.85040067613139
+v 100.00000000000000 0.00000000000000 0.00000000000000
+v 100.00000000000000 2.50000000000000 0.00000000000000
+v 100.00000000000000 5.00000000000000 0.00000000000000
+v 100.00000000000000 7.50000000000000 0.00000000000000
+v 100.00000000000000 10.00000000000000 0.00000000000000
+v 87.58449849701088 12.34005811377603 0.00000000000000
+v 75.13523150260404 14.36993599551963 0.00000000000000
+v 62.65699844618840 16.08885108866691 0.00000000000000
+v 49.25862759706679 8.53560575575546 0.00000000000000
+v 36.96020780186315 9.61341698032146 -0.00000000000000
+v 24.64786635501281 10.38345526352774 0.00000000000000
+v 12.28883806870444 10.84628486838432 -0.01362332794681
+v 76.60444431189778 7.50000000000000 -64.27876096865396
+v 76.60444431189778 10.00000000000000 -64.27876096865396
+v -93.96926207859085 0.00000000000000 -34.20201433256687
+v -37.56761575130206 14.36993599551963 -65.06901920047991
+v -31.32849922309423 16.08885108866691 -54.26255237928124
+v -24.62931379853342 8.53560575575546 -42.65922285461705
+v -70.60402260403794 14.36993599551963 25.69776264732795
+v -18.48010390093159 9.61341698032146 -32.00847888556528
+v -12.32393317750641 10.38345526352774 -21.34567841252484
+v -6.15621718243825 10.84628486838432 -10.63563428651794
+v -93.96926207859085 2.50000000000000 -34.20201433256687
+v 76.60444431189781 0.00000000000000 64.27876096865393
+v 76.60444431189781 2.50000000000000 64.27876096865393
+v 76.60444431189781 5.00000000000000 64.27876096865393
+v 76.60444431189781 7.50000000000000 64.27876096865393
+v 76.60444431189781 10.00000000000000 64.27876096865393
+v 67.09361837699767 12.34005811377603 56.29823043448791
+v 57.55692657502781 14.36993599551963 48.29599586080362
+v 47.99804548221707 16.08885108866691 40.27514226135865
+v 37.73429794640015 8.53560575575546 31.66283548955796
+v 28.31316180313996 9.61341698032146 23.75756362647740
+v 18.88136105599678 10.38345526352774 15.84334309821196
+v 9.40503920851309 10.84628486838432 7.90954892267792
+v -93.96926207859085 5.00000000000000 -34.20201433256687
+v -93.96926207859085 7.50000000000000 -34.20201433256687
+v -93.96926207859085 10.00000000000000 -34.20201433256687
+v -82.30250693287562 12.34005811377603 -29.95566272905447
+v -70.60402260403794 14.36993599551963 -25.69776264732793
+v -58.87831908047738 16.08885108866691 -21.42995558892156
+v -58.87831908047737 16.08885108866691 21.42995558892157
+v -46.28796886300476 8.53560575575546 16.84744287077453
+v 17.36481776669300 0.00000000000000 -98.48077530122082
+v 17.36481776669300 2.50000000000000 -98.48077530122082
+v 17.36481776669300 5.00000000000000 -98.48077530122082
+v 17.36481776669304 0.00000000000000 98.48077530122080
+v 17.36481776669304 2.50000000000000 98.48077530122080
+v 17.36481776669304 5.00000000000000 98.48077530122080
+v 17.36481776669304 7.50000000000000 98.48077530122080
+v 17.36481776669304 10.00000000000000 98.48077530122080
+v 15.20888855587795 12.34005811377603 86.25389316354240
+v 13.04709602901014 14.36993599551963 73.99375850813155
+v 10.88027359826031 16.08885108866691 61.70509785028021
+v 8.55367091660462 8.53560575575546 48.51027836033248
+v 6.41807273098460 9.61341698032146 36.39869919621713
+v 4.28005707592602 10.38345526352774 24.27340988162536
+v 2.12051797729068 10.84628486838432 12.10450867164343
+v -46.28796886300477 8.53560575575546 -16.84744287077452
+v -34.73123453412457 9.61341698032146 -12.64113556973973
+v -23.16141813192280 10.38345526352774 -8.43006678341341
+v -11.54307099861758 10.84628486838432 -4.21583189830639
+v 17.36481776669300 7.50000000000000 -98.48077530122082
+v 17.36481776669300 10.00000000000000 -98.48077530122082
+v -34.73123453412456 9.61341698032146 12.64113556973974
+v 15.20888855587791 12.34005811377603 -86.25389316354242
+v 13.04709602901010 14.36993599551963 -73.99375850813156
+v 10.88027359826028 16.08885108866691 -61.70509785028022
+v 8.55367091660459 8.53560575575546 -48.51027836033249
+v -49.99999999999998 0.00000000000000 86.60254037844388
+v -49.99999999999998 2.50000000000000 86.60254037844388
+v -49.99999999999998 5.00000000000000 86.60254037844388
+v -49.99999999999998 7.50000000000000 86.60254037844388
+v -49.99999999999998 10.00000000000000 86.60254037844388
+v -43.79224924850542 12.34005811377603 75.85040067613141
+v -37.56761575130201 14.36993599551963 65.06901920047994
+v -31.32849922309419 16.08885108866691 54.26255237928126
+v -24.62931379853339 8.53560575575546 42.65922285461706
+v -18.48010390093157 9.61341698032146 32.00847888556530
+v -12.32393317750640 10.38345526352774 21.34567841252484
+v -6.15621718243824 10.84628486838432 10.63563428651794
+v 67.09361837699765 12.34005811377603 -56.29823043448795
+v 57.55692657502779 14.36993599551963 -48.29599586080364
+v 47.99804548221705 16.08885108866691 -40.27514226135867
+v -23.16141813192279 10.38345526352774 8.43006678341341
+v 6.41807273098458 9.61341698032146 -36.39869919621714
+v 4.28005707592601 10.38345526352774 -24.27340988162536
+v 2.14735069525837 10.84628486838432 -12.09977733949999
+v -11.54307099861758 10.84628486838432 4.21583189830639
+v 37.73429794640014 8.53560575575546 -31.66283548955798
+v 28.31316180313996 9.61341698032146 -23.75756362647741
+v 18.88136105599677 10.38345526352774 -15.84334309821196
+v 9.40503920851308 10.84628486838432 -7.90954892267792
+v -93.96926207859083 0.00000000000000 34.20201433256689
+v -93.96926207859083 2.50000000000000 34.20201433256689
+v -93.96926207859083 5.00000000000000 34.20201433256689
+v -93.96926207859083 7.50000000000000 34.20201433256689
+v -80.93917847801794 3.44213696955998 29.45945175195817
+v -43.06683732938375 3.44213696955998 -74.59395037579651
+v 86.13367465876743 3.44213696955998 0.00000000000000
+v 73.68440766436059 5.47201485130358 0.00000000000000
+v -36.84220383218033 5.47201485130358 -63.81256890014504
+v -69.24069414918027 5.47201485130358 25.20155167023162
+v 65.98222283776673 3.44213696955998 55.36565884742716
+v 56.44553103579686 5.47201485130358 47.36342427374285
+v -80.93917847801795 3.44213696955998 -29.45945175195815
+v -69.24069414918027 5.47201485130358 -25.20155167023161
+v 14.95695564025123 3.44213696955998 84.82511059938531
+v 12.79516311338342 5.47201485130358 72.56497594397446
+v 14.95695564025119 3.44213696955998 -84.82511059938533
+v 12.79516311338339 5.47201485130358 -72.56497594397447
+v -43.06683732938370 3.44213696955998 74.59395037579654
+v -36.84220383218028 5.47201485130358 63.81256890014507
+v 65.98222283776671 3.44213696955998 -55.36565884742719
+v 56.44553103579685 5.47201485130358 -47.36342427374289
+v 61.64946696987336 7.13792180161393 0.00000000000000
+v -30.82473348493671 7.13792180161393 -53.39000452567997
+v 47.22623159351846 7.13792180161393 39.62751351201415
+v -57.93154918697460 7.13792180161393 -21.08535952898716
+v -57.93154918697459 7.13792180161393 21.08535952898718
+v 10.70531759345613 7.13792180161393 60.71287304100132
+v 10.70531759345610 7.13792180161393 -60.71287304100133
+v -30.82473348493667 7.13792180161393 53.39000452567999
+v 47.22623159351845 7.13792180161393 -39.62751351201417
+v 3.62814454378410 0.07000000000000 114.53939352316701
+v 3.62814454378410 3.28500000000000 114.53939352316701
+v 3.62814454378410 5.00000000000000 114.53939352316701
+v 3.62814454378410 6.71500000000000 114.53939352316701
+v 3.62814454378410 6.93000000000000 114.53939352316701
+v -42.58412044416730 0.07000000000000 106.39092436614204
+v -42.58412044416730 3.28500000000000 106.39092436614204
+v -42.58412044416730 5.00000000000000 106.39092436614204
+v -42.58412044416730 6.71500000000000 106.39092436614204
+v -42.58412044416730 6.93000000000000 106.39092436614204
+v -70.53739817655406 0.00000000000000 -90.44119596785730
+v -70.53739817655406 3.25000000000000 -90.44119596785730
+v -70.53739817655406 5.00000000000000 -90.44119596785730
+v -70.53739817655406 6.75000000000000 -90.44119596785730
+v -70.53739817655406 7.00000000000000 -90.44119596785730
+v -101.31588163156762 0.00000000000000 -53.76082773574343
+v -101.31588163156762 3.25000000000000 -53.76082773574343
+v -101.31588163156762 5.00000000000000 -53.76082773574343
+v -101.31588163156762 6.75000000000000 -53.76082773574343
+v -101.31588163156762 7.00000000000000 -53.76082773574343
+v 97.21618336341665 0.00000000000000 -60.86171343188304
+v 97.21618336341665 3.25000000000000 -60.86171343188304
+v 97.21618336341665 5.00000000000000 -60.86171343188304
+v 113.59307234508819 0.00000000000000 -15.86658075382527
+v 113.59307234508819 3.25000000000000 -15.86658075382527
+v 113.59307234508819 5.00000000000000 -15.86658075382527
+v 113.59307234508819 6.75000000000000 -15.86658075382527
+v 113.59307234508819 7.00000000000000 -15.86658075382527
+v 97.21618336341665 6.75000000000000 -60.86171343188304
+v 97.21618336341665 7.00000000000000 -60.86171343188304
+# 166 vertices
+
+vn -0.19665808619539 0.98047212970791 0.00000000000000
+vn -0.17096171580051 0.98527767240030 0.00000000000000
+vn -0.14504370205155 0.98942524957431 0.00000000000000
+vn -0.11918337919454 0.99287225871396 0.00000000000000
+vn 0.93969262382216 0.00000000000000 0.34202013498363
+vn 0.18479816258070 0.98047212849648 0.06726101655775
+vn 0.16065150684356 0.98527766408730 0.05847236953959
+vn 0.13629644509239 0.98942525800021 0.04960784097704
+vn 0.11199575940161 0.99287225631785 0.04076312684726
+vn 0.08725951913662 0.99567920870674 0.03175987514404
+vn 0.06240394405703 0.99779249304688 0.02271318087430
+vn 0.03740401526039 0.99920748596035 0.01361395031560
+vn 0.01252223852369 0.99991120640625 0.00455772372410
+vn 0.00000000000000 0.00000000000000 0.00000000000000
+vn -0.09285966373172 0.99567920679887 0.00000000000000
+vn -0.06640890306397 0.99779249225169 0.00000000000000
+vn -0.03980452152388 0.99920748599390 0.00000000000000
+vn -0.01330268900060 0.99991151531791 0.00000000000000
+vn -0.03414931804942 0.98047212208198 -0.19367044662728
+vn -0.02968721123287 0.98527766099421 -0.16836448626413
+vn -0.02518657098508 0.98942525288617 -0.14284013999273
+vn -0.02069597978439 0.99287225679984 -0.11737273149223
+vn -0.01612491261274 0.99567920643049 -0.09144892057968
+vn -0.01153178339161 0.99779249308424 -0.06539999018760
+vn -0.00691198270819 0.99920748594613 -0.03919980260488
+vn -0.00231401612509 0.99991120639602 -0.01312343906989
+vn 0.49999995856928 0.00000000000000 0.86602542770448
+vn 0.09832902812412 0.98047212898587 0.17031091130661
+vn 0.08548088694937 0.98527766371861 0.14805722996041
+vn 0.07252181751881 0.98942525863608 0.12561147860243
+vn 0.05959168951892 0.99287225740849 0.10321584669447
+vn 0.04642982540080 0.99567920764963 0.08041882097783
+vn 0.03320445329494 0.99779249288809 0.05751178503193
+vn 0.01989513607874 0.99920652902614 0.03450356375710
+vn 0.00664128799372 0.99991144280459 0.01153255575468
+vn 0.18479816258070 0.98047212849648 -0.06726101655775
+vn 0.16065149236198 0.98527766666057 -0.05847236596702
+vn 0.13629645313039 0.98942525674626 -0.04960784390263
+vn 0.11199575940161 0.99287225631785 -0.04076312684726
+vn 0.08725951915726 0.99567920894235 -0.03175986770098
+vn 0.06240394034624 0.99779249327884 -0.02271318087958
+vn 0.03740395492580 0.99920716843738 -0.01363740075164
+vn 0.01251970487735 0.99991117055467 -0.00457252553575
+vn 0.49999995856928 0.00000000000000 -0.86602542770448
+vn -0.17364815788816 0.00000000000000 0.98480775649974
+vn -0.17364814343632 0.00000000000000 0.98480775904799
+vn -0.03414931442702 0.98047212503627 0.19367043230968
+vn -0.02968721309388 0.98527766093973 0.16836448625482
+vn -0.02518657109230 0.98942525709813 0.14284011079847
+vn -0.02069597794064 0.99287225770638 0.11737272414882
+vn -0.01612491261274 0.99567920643049 0.09144892057968
+vn -0.01153178525401 0.99779249306281 0.06539999018620
+vn -0.00693790511801 0.99920652903996 0.03921960984633
+vn -0.00232356852067 0.99991158690294 0.01309272342093
+vn 0.09832904263167 0.98047212506099 -0.17031092552601
+vn 0.08548088694937 0.98527766371861 -0.14805722996041
+vn 0.07252181751881 0.98942525863608 -0.12561147860243
+vn 0.05959168951892 0.99287225740849 -0.10321584669447
+vn 0.04642982540080 0.99567920764963 -0.08041882097783
+vn 0.03320444958798 0.99779249343906 -0.05751177761311
+vn 0.01991821206097 0.99920621453817 -0.03449935733593
+vn 0.00666159899357 0.99991124226914 -0.01153822701473
+vn -0.76604442833138 0.00000000000000 0.64278762730971
+vn -0.15064887256782 0.98047211845827 0.12640942259180
+vn -0.13096431712387 0.98527766152995 0.10989211677986
+vn -0.11110991348716 0.98942525166848 0.09323228242209
+vn -0.09129977602114 0.99287225761365 0.07660960096268
+vn -0.07113462739735 0.99567920714147 0.05968903794818
+vn -0.05087216252574 0.99779249299289 0.04268681303383
+vn -0.03051647074462 0.99920621459625 0.02560636103619
+vn -0.01017896945524 0.99991171461749 0.00854116804275
+vn -0.15064887285159 0.98047212030514 -0.12640940792875
+vn -0.13096431744556 0.98527766395006 -0.10989209469805
+vn -0.11110989884714 0.98942525399393 -0.09323227519063
+vn -0.09129976858055 0.99287225772232 -0.07660960842164
+vn -0.07113462000028 0.99567920789057 -0.05968903426779
+vn -0.05087216252574 0.99779249299289 -0.04268681303383
+vn -0.03051647078805 0.99920621463405 -0.02560635950969
+vn -0.01019053593323 0.99991151385348 -0.00855087367662
+vn 0.93969264297872 0.00000000000000 -0.34202008235141
+vn 0.93969265255700 0.00000000000000 -0.34202005603530
+vn 0.00000000000000 -1.00000000000000 0.00000000000000
+vn 0.98846473802528 0.15145118580127 0.00000000000000
+vn -0.98846473665810 -0.15145119472433 0.00000000000000
+vn -0.92885302594117 0.15145119877413 -0.33807482986731
+vn 0.92885298744057 -0.15145135122680 0.33807486735087
+vn 0.17164509815197 0.15145141782323 0.97344770189247
+vn -0.17164517289927 -0.15145094119918 -0.97344776286674
+vn -0.49423234715525 0.15145125697307 -0.85603557390256
+vn 0.49423238039546 -0.15145145174166 0.85603552025251
+vn -0.92885303412084 0.15145119038919 0.33807481115015
+vn 0.92885298835789 -0.15145132675655 -0.33807487579276
+vn 0.17164509776460 0.15145143238260 -0.97344769969559
+vn -0.17164518619931 -0.15145098448992 0.97344775378632
+vn -0.49423234938602 0.15145122785434 0.85603557776636
+vn 0.49423238374161 -0.15145140806357 -0.85603552604822
+vn 0.75720786045583 0.15145155586903 -0.63537286870684
+vn -0.75720792689815 -0.15145119960879 0.63537287444434
+vn 0.75720787412678 0.15145143939411 0.63537288017813
+vn -0.75720795782858 -0.15145089585037 -0.63537290998845
+vn 0.99445250530214 0.10518657090281 0.00000000000000
+vn -0.93447968959132 0.10518661618010 -0.34012275066201
+vn 0.17268482835063 0.10518680949942 0.97934451811650
+vn -0.49722621438918 0.10518658401438 -0.86122115293785
+vn -0.93447968592956 0.10518665302082 0.34012274932923
+vn 0.17268481470582 0.10518676556122 -0.97934452524165
+vn -0.49722625026737 0.10518681626770 0.86122110385691
+vn 0.76179478336745 0.10518668286006 -0.63922176885885
+vn 0.76179481716844 0.10518662792257 0.63922173761660
+vn -0.00066787260224 -0.99999260363101 0.00378769447847
+vn -0.93640329589009 0.00000000000000 0.35092572924507
+vn -0.93640328609681 0.00000000000000 0.35092575537727
+vn -0.02888317292269 0.98606987879052 0.16380462894547
+vn 0.75990752558337 0.00000000000000 0.65003119352978
+vn 0.18372862996709 0.00000000000000 -0.98297700406999
+vn -0.12458981649409 0.98668540184593 -0.10454327051564
+vn -0.93613918929888 0.00000000000000 0.35162966066421
+vn 0.75941870623911 0.00000000000000 0.65060220458750
+vn 0.15283203796476 0.98668540199390 -0.05562630370322
+vn 0.16354942482305 0.00000000000000 -0.98653514161435
+vn 0.16354948283336 0.00000000000000 -0.98653513199731
+vn 0.16354939581789 0.00000000000000 -0.98653514642288
+# 122 normals
+
+vt 0.44444444775581 -0.50000000000000 0.00000000000000
+vt 0.44444444775581 -0.37500000000000 0.00000000000000
+vt 0.55555558204651 -0.37500000000000 0.00000000000000
+vt 0.55555558204651 -0.50000000000000 0.00000000000000
+vt 0.44444444775581 -0.25000000000000 0.00000000000000
+vt 0.55555558204651 -0.25000000000000 0.00000000000000
+vt 0.44444444775581 -0.12500000000000 0.00000000000000
+vt 0.55555558204651 -0.12500000000000 0.00000000000000
+vt 0.44444444775581 -0.87448954582214 0.00000000000000
+vt 0.55555558204651 -0.87448954582214 0.00000000000000
+vt 0.44444444775581 -0.74918210506439 0.00000000000000
+vt 0.55555558204651 -0.74918210506439 0.00000000000000
+vt 0.44444444775581 -0.62404942512512 0.00000000000000
+vt 0.55555558204651 -0.62404942512512 0.00000000000000
+vt 0.44444444775581 -0.49906313419342 0.00000000000000
+vt 0.55555558204651 -0.49906313419342 0.00000000000000
+vt 0.66666668653488 -0.50000000000000 0.00000000000000
+vt 0.66666668653488 -0.37500000000000 0.00000000000000
+vt 0.77777779102325 -0.37500000000000 0.00000000000000
+vt 0.77777779102325 -0.50000000000000 0.00000000000000
+vt 0.66666668653488 -0.25000000000000 0.00000000000000
+vt 0.77777779102325 -0.25000000000000 0.00000000000000
+vt 0.66666668653488 -0.12500000000000 0.00000000000000
+vt 0.77777779102325 -0.12500000000000 0.00000000000000
+vt 0.00000000000000 -0.50000000000000 0.00000000000000
+vt 0.00000000000000 -0.37500000000000 0.00000000000000
+vt 0.11111111193895 -0.37500000000000 0.00000000000000
+vt 0.11111111193895 -0.50000000000000 0.00000000000000
+vt 0.00000000000000 -0.25000000000000 0.00000000000000
+vt 0.11111111193895 -0.25000000000000 0.00000000000000
+vt 0.00000000000000 -0.12500000000000 0.00000000000000
+vt 0.11111111193895 -0.12500000000000 0.00000000000000
+vt 0.00000000000000 -0.87448954582214 0.00000000000000
+vt 0.11111111193895 -0.87448954582214 0.00000000000000
+vt 0.00000000000000 -0.74918210506439 0.00000000000000
+vt 0.11111111193895 -0.74918210506439 0.00000000000000
+vt 0.00000000000000 -0.62404942512512 0.00000000000000
+vt 0.11111111193895 -0.62404942512512 0.00000000000000
+vt 0.00000000000000 -0.49906313419342 0.00000000000000
+vt 0.11111111193895 -0.49906313419342 0.00000000000000
+vt 0.00000000000000 -0.37419420480728 0.00000000000000
+vt 0.11111111193895 -0.37419420480728 0.00000000000000
+vt 0.00000000000000 -0.24941366910934 0.00000000000000
+vt 0.11111111193895 -0.24941366910934 0.00000000000000
+vt 0.00000000000000 -0.12469206750393 0.00000000000000
+vt 0.11111111193895 -0.12469206750393 0.00000000000000
+vt 0.05555555596948 -0.00000000000000 0.00000000000000
+vt 0.44444444775581 -0.37419420480728 0.00000000000000
+vt 0.55555558204651 -0.37419420480728 0.00000000000000
+vt 0.44444444775581 -0.24941366910934 0.00000000000000
+vt 0.55555558204651 -0.24941366910934 0.00000000000000
+vt 0.44444444775581 -0.12469206750393 0.00000000000000
+vt 0.55555558204651 -0.12469206750393 0.00000000000000
+vt 0.50000000000000 -0.00000000000000 0.00000000000000
+vt 0.66666668653488 -0.87448954582214 0.00000000000000
+vt 0.77777779102325 -0.87448954582214 0.00000000000000
+vt 0.66666668653488 -0.74918210506439 0.00000000000000
+vt 0.77777779102325 -0.74918210506439 0.00000000000000
+vt 0.66666668653488 -0.62404942512512 0.00000000000000
+vt 0.77777779102325 -0.62404942512512 0.00000000000000
+vt 0.66666668653488 -0.49906313419342 0.00000000000000
+vt 0.77777779102325 -0.49906313419342 0.00000000000000
+vt 0.66666668653488 -0.37419420480728 0.00000000000000
+vt 0.77777779102325 -0.37419420480728 0.00000000000000
+vt 0.66666668653488 -0.24941366910934 0.00000000000000
+vt 0.77777779102325 -0.24941366910934 0.00000000000000
+vt 0.66666668653488 -0.12469206750393 0.00000000000000
+vt 0.77777779102325 -0.12469206750393 0.00000000000000
+vt 0.72222220897675 -0.00000000000000 0.00000000000000
+vt 0.22222222387791 -0.37500000000000 0.00000000000000
+vt 0.22222222387791 -0.50000000000000 0.00000000000000
+vt 0.22222222387791 -0.25000000000000 0.00000000000000
+vt 0.22222222387791 -0.12500000000000 0.00000000000000
+vt 0.22222222387791 -0.87448954582214 0.00000000000000
+vt 0.22222222387791 -0.74918210506439 0.00000000000000
+vt 0.22222222387791 -0.62404942512512 0.00000000000000
+vt 0.22222222387791 -0.49906313419342 0.00000000000000
+vt 0.22222222387791 -0.37419420480728 0.00000000000000
+vt 0.22222222387791 -0.24941366910934 0.00000000000000
+vt 0.22222222387791 -0.12469206750393 0.00000000000000
+vt 0.16666667163372 -0.00000000000000 0.00000000000000
+vt 0.88888889551163 -0.87448954582214 0.00000000000000
+vt 1.00000000000000 -0.87448954582214 0.00000000000000
+vt 0.88888889551163 -0.74918210506439 0.00000000000000
+vt 1.00000000000000 -0.74918210506439 0.00000000000000
+vt 0.88888889551163 -0.62404942512512 0.00000000000000
+vt 1.00000000000000 -0.62404942512512 0.00000000000000
+vt 0.88888889551163 -0.49906313419342 0.00000000000000
+vt 1.00000000000000 -0.49906313419342 0.00000000000000
+vt 0.88888889551163 -0.37419420480728 0.00000000000000
+vt 1.00000000000000 -0.37419420480728 0.00000000000000
+vt 0.88888889551163 -0.24941366910934 0.00000000000000
+vt 1.00000000000000 -0.24941366910934 0.00000000000000
+vt 0.88888889551163 -0.12469206750393 0.00000000000000
+vt 1.00000000000000 -0.12469206750393 0.00000000000000
+vt 0.94444441795349 -0.00000000000000 0.00000000000000
+vt 0.88888889551163 -0.37500000000000 0.00000000000000
+vt 0.88888889551163 -0.50000000000000 0.00000000000000
+vt 0.88888889551163 -0.25000000000000 0.00000000000000
+vt 0.88888889551163 -0.12500000000000 0.00000000000000
+vt 0.33333334326744 -0.37500000000000 0.00000000000000
+vt 0.33333334326744 -0.25000000000000 0.00000000000000
+vt 0.33333334326744 -0.12500000000000 0.00000000000000
+vt 0.33333334326744 -0.50000000000000 0.00000000000000
+vt 0.33333334326744 -0.87448954582214 0.00000000000000
+vt 0.33333334326744 -0.74918210506439 0.00000000000000
+vt 0.33333334326744 -0.62404942512512 0.00000000000000
+vt 0.33333334326744 -0.49906313419342 0.00000000000000
+vt 0.33333334326744 -0.37419420480728 0.00000000000000
+vt 0.33333334326744 -0.24941366910934 0.00000000000000
+vt 0.33333334326744 -0.12469206750393 0.00000000000000
+vt 0.27777779102325 -0.00000000000000 0.00000000000000
+vt 0.83333331346512 -0.00000000000000 0.00000000000000
+vt 0.38888889551163 -0.00000000000000 0.00000000000000
+vt 0.61111110448837 -0.00000000000000 0.00000000000000
+vt 1.00000000000000 -0.37500000000000 0.00000000000000
+vt 1.00000000000000 -0.50000000000000 0.00000000000000
+vt 1.00000000000000 -0.25000000000000 0.00000000000000
+vt 1.00000000000000 -0.12500000000000 0.00000000000000
+vt 0.93969261646271 -0.22668159008026 0.00000000000000
+vt 0.06030737981200 -0.22668159008026 0.00000000000000
+vt 0.17364817857742 -0.87938523292542 0.00000000000000
+vt 1.00000000000000 -0.57397794723511 0.00000000000000
+vt 0.67364817857742 -0.00000000000000 0.00000000000000
+vt 0.32635182142258 -0.00000000000000 0.00000000000000
+vt 0.00000000000000 -0.57397794723511 0.00000000000000
+vt 0.50000000000000 -1.00000000000000 0.00000000000000
+vt 0.82635182142258 -0.87938523292542 0.00000000000000
+# 128 texture coordinates
+
+o Oil:Tank
+usemtl Mat.2
+f 135/21/4 136/22/4 64/23/4 56/24/4
+f 136/22/4 137/25/4 77/26/4 64/23/4
+f 137/25/4 138/27/4 78/28/4 77/26/4
+f 138/27/4 30/3/4 79/13/4 78/28/4
+f 30/4/10 38/29/10 80/30/10 79/14/10
+f 60/31/12 83/33/12 82/34/12 81/32/12
+f 35/37/6 36/38/6 86/39/6 85/40/6
+f 36/38/6 37/41/6 87/42/6 86/39/6
+f 37/41/6 39/43/6 104/44/6 87/42/6
+f 39/43/6 40/18/6 105/10/6 104/44/6
+f 42/45/14 43/46/14 66/47/14 65/48/14
+f 43/46/14 44/49/14 67/50/14 66/47/14
+f 44/49/14 45/51/14 68/52/14 67/50/14
+f 45/51/14 46/6/14 69/7/14 68/52/14
+f 46/5/15 47/53/15 70/54/15 69/8/15
+f 48/55/17 49/57/17 72/58/17 71/56/17
+f 40/17/28 41/75/28 107/76/28 105/9/28
+f 57/77/30 58/79/30 109/80/30 108/78/30
+f 65/48/36 66/47/36 89/90/36 88/91/36
+f 66/47/36 67/50/36 90/92/36 89/90/36
+f 67/50/36 68/52/36 91/93/36 90/92/36
+f 68/52/36 69/7/36 92/15/36 91/93/36
+f 69/8/37 70/54/37 93/94/37 92/16/37
+f 71/56/39 72/58/39 95/96/39 94/95/39
+f 55/12/45 123/102/45 47/103/45 46/20/45
+f 124/104/47 125/106/47 49/107/47 48/105/47
+f 85/40/53 86/39/53 33/117/53 32/118/53
+f 86/39/53 87/42/53 34/119/53 33/117/53
+f 87/42/53 104/44/53 54/120/53 34/119/53
+f 104/44/53 105/10/53 55/11/53 54/120/53
+f 166/121/54 167/90/54 168/92/54 169/122/54 170/122/55 175/92/55 174/93/55 173/123/55 172/123/55 171/93/55
+f 1 1 1
+f 1 1 1
+f 1 1 1
+f 92/16/56 93/94/56 116/125/56 115/1/56
+f 94/95/58 95/96/58 118/127/58 117/126/58
+f 181/24/7 182/23/7 183/38/7 184/37/7 185/38/7 180/23/7 179/26/7 178/41/7 177/26/7 176/28/7
+f 1 1 1
+f 1 1 1
+f 1 1 1
+f 105/9/64 107/76/64 123/102/64 55/12/64
+f 108/78/66 109/80/66 125/106/66 124/104/66
+f 111/124/72 112/121/72 136/22/72 135/21/72
+f 112/121/72 113/122/72 137/25/72 136/22/72
+f 113/122/72 114/123/72 138/27/72 137/25/72
+f 114/123/72 115/2/72 30/3/72 138/27/72
+f 115/1/73 116/125/73 38/29/73 30/4/73
+f 117/126/75 118/127/75 83/33/75 60/31/75
+f 79/14/81 80/30/81 41/75/81 40/17/81
+f 81/32/83 82/34/83 58/79/83 57/77/83
+f 186/118/89 187/117/89 188/136/89 194/137/89 195/136/90 193/117/90 192/119/90 191/138/90 190/119/90 189/120/90
+f 1 1 1
+f 1 1 1
+f 1 1 1
+f 35/140/91 85/141/91 32/142/91 42/143/91 65/141/91 88/140/91 111/144/91 135/145/91 56/141/91
+f 1 1 1
+f 1 1 1
+f 1 1 1
+f 38/6/92 139/19/92 147/20/92 80/5/92
+f 81/32/93 148/32/93 144/31/93 60/31/93
+f 47/6/94 141/19/94 145/20/94 70/5/94
+f 71/56/95 146/56/95 142/55/95 48/55/95
+f 41/6/96 140/19/96 151/20/96 107/5/96
+f 108/78/97 152/78/97 143/77/97 57/77/97
+f 70/6/98 145/19/98 149/20/98 93/5/98
+f 94/95/99 150/95/99 146/56/99 71/56/99
+f 123/6/100 155/19/100 141/20/100 47/5/100
+f 48/105/101 142/105/101 156/104/101 124/104/101
+f 93/6/102 149/19/102 153/20/102 116/5/102
+f 117/126/103 154/126/103 150/95/103 94/95/103
+f 107/6/104 151/19/104 155/20/104 123/5/104
+f 124/104/105 156/104/105 152/78/105 108/78/105
+f 116/6/106 153/19/106 139/20/106 38/5/106
+f 60/31/107 144/31/107 154/126/107 117/126/107
+f 80/6/108 147/19/108 140/20/108 41/5/108
+f 57/77/109 143/77/109 148/32/109 81/32/109
+f 83/6/110 161/19/110 160/20/110 82/5/110
+f 49/6/111 157/19/111 159/20/111 72/5/111
+f 58/6/112 158/19/112 163/20/112 109/5/112
+f 72/6/113 159/19/113 162/20/113 95/5/113
+f 125/6/114 165/19/114 157/20/114 49/5/114
+f 95/6/115 162/19/115 164/20/115 118/5/115
+f 109/6/116 163/19/116 165/20/116 125/5/116
+f 118/6/117 164/19/117 161/20/117 83/5/117
+f 82/6/118 160/19/118 158/20/118 58/5/118
+f 88/6/119 166/19/119 171/20/119 111/5/119
+f 111/5/120 171/6/121 172/19/121 173/20/120 174/20/120 175/20/120 115/5/120 114/5/120 113/5/120 112/20/120
+f 1 1 1
+f 1 1 1
+f 1 1 1
+f 115/6/122 175/19/122 170/20/122 92/5/122
+f 92/5/123 170/6/123 169/19/123 168/20/123 167/5/123 166/20/123 88/20/123 89/5/123 90/20/123 91/20/123
+f 1 1 1
+f 1 1 1
+f 1 1 1
+f 56/6/91 181/19/91 176/20/91 35/5/91
+f 35/5/124 176/6/124 177/19/124 178/20/124 179/20/124 180/20/124 40/5/124 39/5/124 37/5/124 36/20/124
+f 1 1 1
+f 1 1 1
+f 1 1 1
+f 40/6/125 180/19/125 185/20/125 79/5/125
+f 79/28/126 185/6/126 184/19/126 183/28/126 182/28/126 181/28/126 56/26/126 64/26/126 77/26/126 78/20/126
+f 1 1 1
+f 1 1 1
+f 1 1 1
+f 32/6/91 186/19/91 189/20/91 42/5/91
+f 42/6/127 189/19/127 190/20/127 191/5/127 192/20/127 193/20/127 46/5/127 45/5/127 44/5/127 43/20/127
+f 1 1 1
+f 1 1 1
+f 1 1 1
+f 46/6/128 193/19/128 195/20/128 55/5/128
+f 55/6/129 195/19/129 194/20/129 188/5/129 187/5/130 186/20/130 32/20/130 33/5/130 34/20/130 54/20/130
+f 1 1 1
+f 1 1 1
+f 1 1 1
+
+usemtl Mat.1
+f 139/29/11 144/31/11 148/32/11 147/30/11
+f 161/33/13 84/35/13 100/36/13 160/34/13
+f 141/53/16 142/55/16 146/56/16 145/54/16
+f 157/57/18 50/59/18 73/60/18 159/58/18
+f 50/59/19 51/61/19 74/62/19 73/60/19
+f 51/61/20 52/63/20 75/64/20 74/62/20
+f 52/63/21 53/65/21 76/66/21 75/64/21
+f 53/65/22 31/67/22 76/66/22
+f 84/35/24 106/68/24 101/69/24 100/36/24
+f 106/68/25 126/70/25 102/71/25 101/69/25
+f 126/70/26 130/72/26 103/73/26 102/71/26
+f 130/72/27 31/74/27 103/73/27
+f 140/75/29 143/77/29 152/78/29 151/76/29
+f 158/79/31 59/81/31 110/82/31 163/80/31
+f 59/81/32 61/83/32 127/84/32 110/82/32
+f 61/83/33 62/85/33 128/86/33 127/84/33
+f 62/85/34 63/87/34 129/88/34 128/86/34
+f 63/87/35 31/89/35 129/88/35
+f 145/54/38 146/56/38 150/95/38 149/94/38
+f 159/58/40 73/60/40 96/97/40 162/96/40
+f 73/60/41 74/62/41 97/98/41 96/97/41
+f 74/62/42 75/64/42 98/99/42 97/98/42
+f 75/64/43 76/66/43 99/100/43 98/99/43
+f 76/66/44 31/101/44 99/100/44
+f 155/102/46 156/104/46 142/105/46 141/103/46
+f 165/106/48 131/108/48 50/109/48 157/107/48
+f 131/108/49 132/110/49 51/111/49 50/109/49
+f 132/110/50 133/112/50 52/113/50 51/111/50
+f 133/112/51 134/114/51 53/115/51 52/113/51
+f 134/114/52 31/116/52 53/115/52
+f 149/94/57 150/95/57 154/126/57 153/125/57
+f 162/96/59 96/97/59 119/128/59 164/127/59
+f 96/97/60 97/98/60 120/129/60 119/128/60
+f 97/98/61 98/99/61 121/130/61 120/129/61
+f 98/99/62 99/100/62 122/131/62 121/130/62
+f 99/100/63 31/132/63 122/131/63
+f 151/76/65 152/78/65 156/104/65 155/102/65
+f 163/80/67 110/82/67 131/108/67 165/106/67
+f 110/82/68 127/84/68 132/110/68 131/108/68
+f 127/84/69 128/86/69 133/112/69 132/110/69
+f 128/86/70 129/88/70 134/114/70 133/112/70
+f 129/88/71 31/133/71 134/114/71
+f 153/125/74 154/126/74 144/31/74 139/29/74
+f 164/127/76 119/128/76 84/35/76 161/33/76
+f 119/128/77 120/129/77 106/68/77 84/35/77
+f 120/129/78 121/130/78 126/70/78 106/68/78
+f 121/130/79 122/131/79 130/72/79 126/70/79
+f 122/131/80 31/134/80 130/72/80
+f 147/30/82 148/32/82 143/77/82 140/75/82
+f 160/34/84 100/36/84 59/81/84 158/79/84
+f 100/36/85 101/69/85 61/83/85 59/81/85
+f 101/69/86 102/71/86 62/85/86 61/83/86
+f 102/71/87 103/73/87 63/87/87 62/85/87
+f 103/73/88 31/135/88 63/87/88
+

+ 16 - 0
worlds/world1.json

@@ -0,0 +1,16 @@
+{
+  "player": {
+    "startposition": [ 0, 1.7, 0 ]
+  },
+  "objects": [
+    {
+      "file": "models/boom/boom.obj",
+      "pos": [ 0, 0, -4 ],
+      "rot": [ 0, 20, 0 ]
+    },
+    {
+      "file": "models/boom/boom.obj",
+      "pos": [ 4, 0, -4 ]
+    }
+  ]
+}