Browse Source

Added new Johan Code

Kenneth van Ewijk 10 năm trước cách đây
mục cha
commit
a8415db4ac
24 tập tin đã thay đổi với 2284 bổ sung29 xóa
  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 ]
+    }
+  ]
+}