Exemple #1
0
void drawTriangle(RenderingContext & rc, const Geometry::Vec3f & vertexA, const Geometry::Vec3f & vertexB, const Geometry::Vec3f & vertexC) {
	static Util::Reference<Mesh> mesh;
	if (mesh.isNull()) {
		VertexDescription vertexDescription;
		vertexDescription.appendPosition3D();
		mesh = new Mesh(vertexDescription, 3, 3);

		MeshIndexData & id = mesh->openIndexData();
		uint32_t * indices = id.data();
		indices[0] = 0;
		indices[1] = 1;
		indices[2] = 2;
		id.updateIndexRange();
		id.markAsChanged();
	}

	MeshVertexData & vd = mesh->openVertexData();
	float * vertices = reinterpret_cast<float *>(vd.data());
	// First vertex
	*vertices++ = vertexA.getX();
	*vertices++ = vertexA.getY();
	*vertices++ = vertexA.getZ();
	// Second vertex
	*vertices++ = vertexB.getX();
	*vertices++ = vertexB.getY();
	*vertices++ = vertexB.getZ();
	// Third vertex
	*vertices++ = vertexC.getX();
	*vertices++ = vertexC.getY();
	*vertices++ = vertexC.getZ();
	vd.updateBoundingBox();
	vd.markAsChanged();

	rc.displayMesh(mesh.get());
}
Exemple #2
0
//! Deprecated
Mesh * MeshBuilder::createMeshFromBitmaps(const VertexDescription& vd, Util::Reference<Util::Bitmap> depth, Util::Reference<Util::Bitmap> color, Util::Reference<Util::Bitmap> normals) {
	
	Util::Reference<Util::PixelAccessor> depthAcc = Util::PixelAccessor::create(std::move(depth));
	if( depth.isNull() || depth->getPixelFormat()!=Util::PixelFormat::MONO_FLOAT ){
		WARN("createMeshFromBitmaps: unsupported depth texture format");
		return nullptr;
	}
	Util::Reference<Util::PixelAccessor> colorReader;
	if(color.isNotNull()) {
		colorReader = Util::PixelAccessor::create(std::move(color));
		if(colorReader.isNull() || (colorReader->getPixelFormat() != Util::PixelFormat::RGBA && colorReader->getPixelFormat() != Util::PixelFormat::RGB)) {
			WARN("createMeshFromBitmaps: unsupported color texture format");
			return nullptr;
		}
	}
	Util::Reference<Util::PixelAccessor> normalReader;
	if(normals.isNotNull()) {
		normalReader = Util::PixelAccessor::create(std::move(normals));
		if(normalReader.isNull()){
			WARN("createMeshFromBitmaps: unsupported normal texture format");
			return nullptr;
		}
	}
	return MeshUtils::createMeshFromBitmaps(vd,depthAcc,colorReader,normalReader);
}
Exemple #3
0
void StatChart::update(const Statistics & fStats) {
	Util::Reference<Util::PixelAccessor> pixels = Util::PixelAccessor::create(bitmap.get());
	if(pixels == nullptr)
		return;

	pixels->fill(0, 0, bitmap->getWidth(), bitmap->getHeight(), Util::Color4f(0, 0, 0, 0));

	// show grids
	static const Util::Color4ub gridColor(0xa0, 0xa0, 0xa0, 0xa0);
	for(float f = 10.0; f < timeRange; f += 10.0) {
		const uint32_t x = static_cast<uint32_t> (bitmap->getWidth() * f / timeRange);
		for (uint32_t row = 0; row < bitmap->getHeight(); ++row) {
			pixels->writeColor(x, row, gridColor);
		}
	}

	const float timeScale = getWidth() / (timeRange * 1000.0);
	for(size_t i = 0; i < fStats.getNumEvents(); ++i) {
		const Statistics::Event & event = fStats.getEvent(i);
		const int x = static_cast<int> (event.time * timeScale);
		if(x >= static_cast<int> (getWidth()))
			continue;

		const DataRow & dataRow = dataRows[event.type];
		const int yTo = std::max(static_cast<int> (bitmap->getHeight()) - static_cast<int> (event.value * dataRow.scale), 0);
		for(int y = bitmap->getHeight() - 1; y > yTo; --y)
			pixels->writeColor(x, y, dataRow.color);
	}

}
Exemple #4
0
void drawFullScreenRect(RenderingContext & rc){
	GET_GL_ERROR();

	static Geometry::Matrix4x4f projectionMatrix(Geometry::Matrix4x4f::orthographicProjection(-1, 1, -1, 1, -1, 1));
	static Geometry::Matrix4x4f modelViewMatrix;
	static Util::Reference<Mesh> mesh;
	if(mesh.isNull()) {
		VertexDescription vertexDescription;
		vertexDescription.appendPosition3D();
		vertexDescription.appendTexCoord();
		MeshUtils::MeshBuilder mb(vertexDescription);
		mb.position(Geometry::Vec3f(-1,-1,0)); 	mb.texCoord0(Geometry::Vec2f(0,0));	uint32_t a = mb.addVertex();
		mb.position(Geometry::Vec3f(1,-1,0)); 	mb.texCoord0(Geometry::Vec2f(1,0));	uint32_t b = mb.addVertex();
		mb.position(Geometry::Vec3f(-1,1,0)); 	mb.texCoord0(Geometry::Vec2f(0,1));	uint32_t c = mb.addVertex();
		mb.position(Geometry::Vec3f(1,1,0)); 	mb.texCoord0(Geometry::Vec2f(1,1));	uint32_t d = mb.addVertex();
		mb.addTriangle(a, b, c);
		mb.addTriangle(c, b, d);
		mesh = mb.buildMesh();
	}

	rc.pushMatrix_cameraToClipping();
	rc.setMatrix_cameraToClipping(projectionMatrix);

	rc.pushMatrix_modelToCamera();
	rc.setMatrix_modelToCamera(modelViewMatrix);

	rc.displayMesh(mesh.get());

	rc.popMatrix_modelToCamera();
	rc.popMatrix_cameraToClipping();

	GET_GL_ERROR();
}
Exemple #5
0
 void AbstractJoint::doAddChild(Util::Reference<Node> child) {
     if(dynamic_cast<AbstractJoint *>(child.get()) == nullptr)
         return;
 
     if(dynamic_cast<ArmatureNode *> (child.get()) != nullptr)
         return;
     
     ListNode::doAddChild(child);
 }
Exemple #6
0
		Util::StringIdentifier createAndSetId(Util::Reference<Obj> obj){
			Util::StringIdentifier id = getId(obj.get());
			if(obj.isNotNull() && id.empty()) {
				do { // Create a new, random identifier....
					id = Util::StringIdentifier("$" + Util::StringUtils::createRandomString(6));
				}while( get(id) ); // ... until an unused one is found.
				setId(obj,id);
			}
			return id;
		}
Exemple #7
0
		void setId(Util::Reference<Obj> obj,const Util::StringIdentifier & id){
			if(!id.empty()) // remove a obj possibly previously registered with the id
				removeId( id );
			if(obj.isNotNull()) // remove the obj's old id
				removeId( obj.get() ); 
			if(obj.isNotNull()&&!id.empty()){ // register the obj using the new id
				map_objToId.emplace(obj.get(),id);
				map_idToObj.emplace(id, std::move(obj));
			}
		}
Exemple #8
0
Util::Reference<CameraNode> PhotonRenderer::computePhotonCamera(){
  Util::Reference<CameraNode> camera = new CameraNode;

  float minDistance = 0.01f;
  float maxDistance = 500.f;

  camera->setViewport(Geometry::Rect_i(0, 0, _samplingWidth, _samplingHeight));
  camera->setNearFar(minDistance, maxDistance);
  camera->setAngles(-70, 70, -50, 50);
  
  return camera;
}
bool MultiAlgoGroupNode::doRemoveChild(Util::Reference<Node> child) {
	if(node.get() == child.get()) {
		WARN("MultiAlgoGroupNode::doRemoveChild: don't remove direct child of MultiAlgoGroupNode");
		return false;
	}
	return node->removeChild(child);
}
Exemple #10
0
void drawVector(RenderingContext & rc, const Geometry::Vec3 & from, const Geometry::Vec3 & to) {
	static Util::Reference<Mesh> mesh;
	if (mesh.isNull()) {
		VertexDescription vertexDescription;
		vertexDescription.appendPosition3D();
		mesh = new Mesh(vertexDescription, 2, 2);
		mesh->setDrawMode(Mesh::DRAW_LINES);

		MeshIndexData & id = mesh->openIndexData();
		uint32_t * indices = id.data();
		indices[0] = 0;
		indices[1] = 1;
		id.updateIndexRange();
		id.markAsChanged();
		mesh->setDataStrategy(SimpleMeshDataStrategy::getPureLocalStrategy());
	}

	MeshVertexData & vd = mesh->openVertexData();
	float * vertices = reinterpret_cast<float *> (vd.data());
	*vertices++ = from.getX(); // From
	*vertices++ = from.getY();
	*vertices++ = from.getZ();
	*vertices++ = to.getX(); // To
	*vertices++ = to.getY();
	*vertices++ = to.getZ();
	vd.updateBoundingBox();
	vd.markAsChanged();

	rc.displayMesh(mesh.get());
}
Exemple #11
0
void drawBox(RenderingContext & rc, const Geometry::Box & box) {
	static Util::Reference<Mesh> mesh;
	if (mesh.isNull()) {
		VertexDescription vertexDescription;
		vertexDescription.appendPosition3D();
		vertexDescription.appendNormalFloat();
		const Geometry::Box unitBox(Geometry::Vec3(-0.5f, -0.5f, -0.5f), Geometry::Vec3(0.5f, 0.5f, 0.5f));
		mesh = MeshUtils::MeshBuilder::createBox(vertexDescription, unitBox);
	}

	Geometry::Matrix4x4 matrix;
	matrix.translate(box.getCenter());
	matrix.scale(box.getExtentX(), box.getExtentY(), box.getExtentZ());
	rc.pushMatrix_modelToCamera();
	rc.multMatrix_modelToCamera(matrix);
	rc.displayMesh(mesh.get());
	rc.popMatrix_modelToCamera();
}
Exemple #12
0
void drawWireframeBox(RenderingContext & rc, const Geometry::Box & box) {
	static Util::Reference<Mesh> mesh;
	if (mesh.isNull()) {
		VertexDescription vertexDescription;
		vertexDescription.appendPosition3D();
		mesh = new Mesh(vertexDescription, 8, 16);
		mesh->setDataStrategy(SimpleMeshDataStrategy::getPureLocalStrategy());
		mesh->setDrawMode(Mesh::DRAW_LINE_STRIP);

		MeshIndexData & id = mesh->openIndexData();
		uint32_t * indices = id.data();
		/*
		 *  Corners:
		 *     6---------7
		 *    /|        /|
		 *   / |       / |
		 *  2---------3  |
		 *  |  |      |  |
		 *  |  4------|--5
		 *  | /       | /
		 *  |/        |/
		 *  0---------1
		 */
		indices[0] = 0;
		indices[1] = 2;
		indices[2] = 3;
		indices[3] = 1;
		indices[4] = 5;
		indices[5] = 7;
		indices[6] = 6;
		indices[7] = 4;
		indices[8] = 0;
		indices[9] = 1;
		indices[10] = 3;
		indices[11] = 7;
		indices[12] = 5;
		indices[13] = 4;
		indices[14] = 6;
		indices[15] = 2;
		id.updateIndexRange();
		id.markAsChanged();
	}

	MeshVertexData & vd = mesh->openVertexData();
	float * vertices = reinterpret_cast<float *>(vd.data());
	for (uint_fast8_t c = 0; c < 8; ++c) {
		const Geometry::Vec3 & corner = box.getCorner(static_cast<Geometry::corner_t> (c));
		*vertices++ = corner.getX();
		*vertices++ = corner.getY();
		*vertices++ = corner.getZ();
	}
	vd._setBoundingBox(box);
	vd.markAsChanged();

	rc.displayMesh(mesh.get());
}
OverviewTableRow::OverviewTableRow(util::Reference<const impl::Call> call)
    : call_{ call }
{
	id_ = call_->getId();
	idStr = QString::number(call_->getId());
	for (size_t i = 0; i < 2 && i < call->matrixCount(); i++)
	{
		QPixmap img;
		std::tie(std::ignore, img) =
		    qtutil::convertMatToQPixmap(call->matrixAt(i));
		imgs.push_back(std::move(img));
	}
	description_ = QString(call_->description());
	if (call_->metaData().isKnown)
	{
		const auto &data = call_->metaData();
		line_ = data.line;
		lineStr = QString::number(data.line);
		fileStr = data.file;
		functionStr = data.function;
	}
	typeStr = QString(call_->type());
}
void ParticlePointRenderer::operator()(ParticleSystemNode* psys, FrameContext & context, const RenderParam & rp /* = 0 */) {
	if ( (rp.getFlag(NO_GEOMETRY)) )
		return;

	// render particles
	std::vector<Particle> & particles = psys->getParticles();
	uint32_t count = psys->getParticleCount();

	Rendering::VertexDescription vertexDesc;
	const Rendering::VertexAttribute & posAttrib = vertexDesc.appendPosition3D();
	const Rendering::VertexAttribute & colorAttrib = vertexDesc.appendColorRGBAByte();
	// The usage of a cache for the mesh has been tested. Reusing a preallocated mesh is not faster.
	Util::Reference<Rendering::Mesh> mesh = new Rendering::Mesh(vertexDesc, count, count);
	mesh->setDataStrategy(Rendering::SimpleMeshDataStrategy::getPureLocalStrategy());
	mesh->setDrawMode(Rendering::Mesh::DRAW_POINTS);
//	mesh->setUseIndexData(false);
	Rendering::MeshIndexData & indexData = mesh->openIndexData();
	Rendering::MeshVertexData & vertexData = mesh->openVertexData();
	Util::Reference<Rendering::PositionAttributeAccessor> positionAccessor = Rendering::PositionAttributeAccessor::create(vertexData, posAttrib.getNameId());
	Util::Reference<Rendering::ColorAttributeAccessor> colorAccessor = Rendering::ColorAttributeAccessor::create(vertexData, colorAttrib.getNameId());
	uint32_t * indices = indexData.data();

	for(uint_fast32_t index = 0; index < count; ++index) {
		const Particle & p = particles[index];

		colorAccessor->setColor(index, p.color);
		positionAccessor->setPosition(index, p.position);

		*indices++ = index;
	}

	indexData.markAsChanged();
	indexData.updateIndexRange();
	vertexData.markAsChanged();
	vertexData.updateBoundingBox();
	context.displayMesh(mesh.get());
}
void drawGrid(RenderingContext & rc, float scale) {
	static Util::Reference<Mesh> mesh;
	if (mesh.isNull()) {
		VertexDescription vertexDescription;
		vertexDescription.appendPosition3D();
		mesh = new Mesh(vertexDescription, 4 * 101, 4 * 101);
		mesh->setDrawMode(Mesh::DRAW_LINES);
		
		MeshVertexData & vd = mesh->openVertexData();
		float * vertices = reinterpret_cast<float *> (vd.data());
		MeshIndexData & id = mesh->openIndexData();
		uint32_t * indices = id.data();
		uint32_t nextIndex = 0;
		const float step = 1.0f / 100.0f;
		for (uint_fast8_t line = 0; line < 101; ++line) {
			const float pos = -0.5f + static_cast<float> (line) * step;

			*vertices++ = -0.5f;
			*vertices++ = 0.0f;
			*vertices++ = pos;

			*vertices++ = 0.5f;
			*vertices++ = 0.0f;
			*vertices++ = pos;

			*indices++ = nextIndex++;
			*indices++ = nextIndex++;

			*vertices++ = pos;
			*vertices++ = 0.0f;
			*vertices++ = -0.5f;

			*vertices++ = pos;
			*vertices++ = 0.0f;
			*vertices++ = 0.5f;

			*indices++ = nextIndex++;
			*indices++ = nextIndex++;

		}
		vd.updateBoundingBox();
		vd.markAsChanged();
		id.updateIndexRange();
		id.markAsChanged();
	}

	Geometry::Matrix4x4 matrix;
	matrix.scale(scale);
	rc.pushMatrix_modelToCamera();
	rc.multMatrix_modelToCamera(matrix);
	rc.displayMesh(mesh.get());
	rc.popMatrix_modelToCamera();
}
void drawFrustum(RenderingContext & rc, const Geometry::Frustum & frustum, const Util::Color4f & color, float lineWidth) {
	static Util::Reference<Mesh> mesh;
	if (mesh.isNull()) {
		VertexDescription vertexDescription;
		vertexDescription.appendPosition3D();
		mesh = new Mesh(vertexDescription, 8, 16);
		mesh->setDrawMode(Mesh::DRAW_LINE_STRIP);

		MeshIndexData & id = mesh->openIndexData();
		uint32_t * indices = id.data();
		indices[0] = 0;
		indices[1] = 2;
		indices[2] = 3;
		indices[3] = 1;
		indices[4] = 5;
		indices[5] = 7;
		indices[6] = 6;
		indices[7] = 4;
		indices[8] = 0;
		indices[9] = 1;
		indices[10] = 3;
		indices[11] = 7;
		indices[12] = 5;
		indices[13] = 4;
		indices[14] = 6;
		indices[15] = 2;
		id.updateIndexRange();
	}

	MeshVertexData & vd = mesh->openVertexData();
	float * vertices = reinterpret_cast<float *>(vd.data());
	for (uint_fast8_t c = 0; c < 8; ++c) {
		const Geometry::Vec3 & corner = frustum[static_cast<Geometry::corner_t> (c)];
		*vertices++ = corner.getX();
		*vertices++ = corner.getY();
		*vertices++ = corner.getZ();
	}
	vd.updateBoundingBox();
	vd.markAsChanged();

	rc.pushAndSetLine(lineWidth);
	rc.pushAndSetLighting(LightingParameters(false));
	rc.pushAndSetColorMaterial(color);
	rc.displayMesh(mesh.get());
	rc.popMaterial();
	rc.popLighting();
	rc.popLine();
}
Exemple #17
0
void drawRect(RenderingContext & rc, const Geometry::Rect & rect) {
	static Util::Reference<Mesh> mesh;
	if (mesh.isNull()) {
		VertexDescription vertexDescription;
		vertexDescription.appendPosition2D();
		mesh = new Mesh(vertexDescription, 4, 6);
		mesh->setDrawMode(Mesh::DRAW_TRIANGLES);

		MeshVertexData & vd = mesh->openVertexData();
		float * vertices = reinterpret_cast<float *> (vd.data());
		*vertices++ = 0.0f; // Bottom left
		*vertices++ = 0.0f;
		*vertices++ = 1.0f; // Bottom right
		*vertices++ = 0.0f;
		*vertices++ = 1.0f; // Top right
		*vertices++ = 1.0f;
		*vertices++ = 0.0f; // Top left
		*vertices++ = 1.0f;
		vd.updateBoundingBox();
		vd.markAsChanged();

		MeshIndexData & id = mesh->openIndexData();
		uint32_t * indices = id.data();
		indices[0] = 0;
		indices[1] = 2;
		indices[2] = 1;
		indices[3] = 0;
		indices[4] = 3;
		indices[5] = 2;
		id.updateIndexRange();
		id.markAsChanged();
	}

	Geometry::Matrix4x4 matrix;
	matrix.translate(rect.getX(), rect.getY(), 0.0f);
	matrix.scale(rect.getWidth(), rect.getHeight(), 1.0f);
	rc.pushMatrix_modelToCamera();
	rc.multMatrix_modelToCamera(matrix);
	rc.displayMesh(mesh.get());
	rc.popMatrix_modelToCamera();
}
State::stateResult_t VisibilitySubdivisionRenderer::doEnableState(
																	FrameContext & context,
																	Node *,
																	const RenderParam & rp) {
	if (rp.getFlag(SKIP_RENDERER)) {
		return State::STATE_SKIPPED;
	}

	if (viSu == nullptr) {
		// Invalid information. => Fall back to standard rendering.
		return State::STATE_SKIPPED;
	}

	// [AccumRendering]
	if(accumRenderingEnabled){
		// camera moved? -> start new frame
		const Geometry::Matrix4x4 & newCamMat=context.getCamera()->getWorldTransformationMatrix();
		if(newCamMat!=lastCamMatrix){
			lastCamMatrix = newCamMat;
			startRuntime=0;
		}
	}else{
		startRuntime=0;
	}
	// ----

	uint32_t renderedTriangles = 0;
	if (hold) {
		for (const auto & object : holdObjects) {
			if (debugOutput) {
				debugDisplay(renderedTriangles, object, context, rp);
			} else {
				context.displayNode(object, rp);
			}
		}
		return State::STATE_SKIP_RENDERING;
	}

	Geometry::Vec3 pos = context.getCamera()->getWorldOrigin();
	bool refreshCache = false;
	// Check if cached cell can be used.
	if (currentCell == nullptr || !currentCell->getBB().contains(pos)) {
		currentCell = viSu->getNodeAtPosition(pos);
		refreshCache = true;
	}
	if (currentCell == nullptr || !currentCell->isLeaf()) {
		// Invalid information. => Fall back to standard rendering.
		return State::STATE_SKIPPED;
	}

	if (refreshCache) {
		try {
			const auto & vv = getVV(currentCell);

			const uint32_t maxIndex = vv.getIndexCount();
			objects.clear();
			objects.reserve(maxIndex);
			for(uint_fast32_t index = 0; index < maxIndex; ++index) {
				if(vv.getBenefits(index) == 0) {
					continue;
				}
				const VisibilityVector::costs_t costs = vv.getCosts(index);
				const VisibilityVector::benefits_t benefits = vv.getBenefits(index);
				const float score = static_cast<float>(costs) / static_cast<float>(benefits);
				objects.emplace_back(score, vv.getNode(index));
			}
		} catch(...) {
			// Invalid information. => Fall back to standard rendering.
			return State::STATE_SKIPPED;
		}

		if (displayTexturedDepthMeshes) {
#ifdef MINSG_EXT_OUTOFCORE
			for (const auto & depthMesh : depthMeshes) {
				OutOfCore::getCacheManager().setUserPriority(depthMesh.get(), 0);
			}
#endif /* MINSG_EXT_OUTOFCORE */
			depthMeshes.clear();
			depthMeshes.reserve(6);
			textures.clear();
			textures.reserve(6);

			const std::string dmDirectionStrings[6] = { "-dir_x1_y0_z0", "-dir_x-1_y0_z0",
														"-dir_x0_y1_z0", "-dir_x0_y-1_z0",
														"-dir_x0_y0_z1", "-dir_x0_y0_z-1" };
			for (auto & dmDirectionString : dmDirectionStrings) {
				Util::GenericAttribute * attrib = currentCell->getAttribute("DepthMesh" + dmDirectionString);
				if (attrib == nullptr) {
					continue;
				}
				Util::FileName dmMeshPath(attrib->toString());
				Util::Reference<Rendering::Mesh> dmMesh;
#ifdef MINSG_EXT_OUTOFCORE
				Util::GenericAttribute * bbAttrib = currentCell->getAttribute("DepthMesh" + dmDirectionString + "-bounds");
				if (bbAttrib == nullptr) {
					WARN("Found depth mesh with no bounding box.");
					continue;
				}

				std::vector<float> bbValues = Util::StringUtils::toFloats(bbAttrib->toString());
				FAIL_IF(bbValues.size() != 6);
				const Geometry::Box meshBB(Geometry::Vec3(bbValues[0], bbValues[1], bbValues[2]), bbValues[3], bbValues[4], bbValues[5]);

				dmMesh = OutOfCore::addMesh(dmMeshPath, meshBB);
#else /* MINSG_EXT_OUTOFCORE */
				dmMesh = Rendering::Serialization::loadMesh(dmMeshPath);
#endif /* MINSG_EXT_OUTOFCORE */
				depthMeshes.emplace_back(dmMesh);
				// Count the depth mesh here already.
				renderedTriangles += dmMesh->getPrimitiveCount();

				Util::GenericAttribute * texAttrib = currentCell->getAttribute("Texture" + dmDirectionString);
				if (texAttrib == nullptr) {
					continue;
				}
				Util::FileName texturePath(texAttrib->toString());
				Util::Reference<Rendering::Texture> texture = Rendering::Serialization::loadTexture(texturePath);
				if (texture.isNull()) {
					WARN("Loading texture for depth mesh failed.");
					continue;
				}
				textures.emplace_back(texture);
			}
		}
	}

	const Geometry::Frustum & frustum = context.getCamera()->getFrustum();
	holdObjects.clear();
	holdObjects.reserve(objects.size());

	std::sort(objects.begin(), objects.end());
	for(const auto & ratioObjectPair : objects) {
		object_ptr o = ratioObjectPair.second;
#ifdef MINSG_EXT_OUTOFCORE
		OutOfCore::getCacheManager().setUserPriority(o->getMesh(), 5);
#endif /* MINSG_EXT_OUTOFCORE */
		
		if (conditionalFrustumTest(frustum, o->getWorldBB(), rp)) {
			// [AccumRendering]
			// skip geometry rendered in the last frame
			if(renderedTriangles<startRuntime){
				renderedTriangles += o->getTriangleCount();
				continue;
			}
			// ----

			if (debugOutput) {
				debugDisplay(renderedTriangles, o, context, rp);
			} else {
				context.displayNode(o, rp);
				renderedTriangles += o->getTriangleCount();
			}
			holdObjects.push_back(o);
		}
		if (maxRuntime != 0 && renderedTriangles >= startRuntime+maxRuntime) {
			break;
		}
	}

	// Draw the textured depth meshes at the end.
	if (displayTexturedDepthMeshes) {
		context.getRenderingContext().pushAndSetPolygonOffset(Rendering::PolygonOffsetParameters(polygonOffsetFactor, polygonOffsetUnits));
		auto texIt = textures.cbegin();
		for (const auto & depthMesh : depthMeshes) {
			context.getRenderingContext().pushAndSetShader(getTDMShader());
			context.getRenderingContext().pushAndSetTexture(0,texIt->get());
			
			if (conditionalFrustumTest(frustum, depthMesh->getBoundingBox(), rp)) {
				context.displayMesh(depthMesh.get());
			}
			context.getRenderingContext().popTexture(0);
			context.getRenderingContext().popShader();
#ifdef MINSG_EXT_OUTOFCORE
			OutOfCore::getCacheManager().setUserPriority(depthMesh.get(), 2);
#endif /* MINSG_EXT_OUTOFCORE */
			++texIt;
		}
		context.getRenderingContext().popPolygonOffset();
	}
	// [AccumRendering]
	startRuntime=renderedTriangles;
	// ----
	return State::STATE_SKIP_RENDERING;
}
void drawCamera(RenderingContext & rc, const Util::Color4f & color) {
	static Util::Reference<Mesh> mesh;
	if (mesh.isNull()) {
		std::deque<Mesh *> meshes;
		std::deque<Geometry::Matrix4x4f> transformations;

		{
			VertexDescription vertexDescription;
			vertexDescription.appendPosition3D();
			vertexDescription.appendNormalFloat();
			Geometry::Box box(Geometry::Vec3f(0.0f, 0.0f, 0.1f), 0.2f, 0.5f, 0.8f);
			meshes.push_back(MeshUtils::MeshBuilder::createBox(vertexDescription, box));
			transformations.push_back(Geometry::Matrix4x4());
		}
		{
			// Lens
			meshes.push_back(MeshUtils::MeshBuilder::createConicalFrustum(0.1f, 0.25f, 0.2f, 16));
			Geometry::Matrix4x4f mat;
			mat.translate(0.0f, 0.0f, -0.3f);
			mat.rotate_deg(90.0f, 0.0f, 1.0f, 0.0f);
			transformations.push_back(mat);
		}
		{
			// Lens cap
			meshes.push_back(MeshUtils::MeshBuilder::createDiscSector(0.25f, 16));
			Geometry::Matrix4x4f mat;
			mat.translate(0.0f, 0.0f, -0.5f);
			mat.rotate_deg(-90.0f, 0.0f, 1.0f, 0.0f);
			transformations.push_back(mat);
		}

		{
			// First film reel
			meshes.push_back(MeshUtils::MeshBuilder::createConicalFrustum(0.2f, 0.2f, 0.1f, 16));
			Geometry::Matrix4x4f mat;
			mat.translate(-0.05f, 0.45f, -0.1f);
			transformations.push_back(mat);
		}
		{
			meshes.push_back(MeshUtils::MeshBuilder::createDiscSector(0.2f, 16));
			Geometry::Matrix4x4f mat;
			mat.translate(-0.05f, 0.45f, -0.1f);
			transformations.push_back(mat);
		}
		{
			meshes.push_back(MeshUtils::MeshBuilder::createDiscSector(0.2f, 16));
			Geometry::Matrix4x4f mat;
			mat.translate(0.05f, 0.45f, -0.1f);
			mat.rotate_deg(180.0f, 0.0f, 1.0f, 0.0f);
			transformations.push_back(mat);
		}

		{
			// Second film reel
			meshes.push_back(MeshUtils::MeshBuilder::createConicalFrustum(0.2f, 0.2f, 0.1f, 16));
			Geometry::Matrix4x4f mat;
			mat.translate(-0.05f, 0.45f, 0.3f);
			transformations.push_back(mat);
		}
		{
			meshes.push_back(MeshUtils::MeshBuilder::createDiscSector(0.2f, 16));
			Geometry::Matrix4x4f mat;
			mat.translate(-0.05f, 0.45f, 0.3f);
			transformations.push_back(mat);
		}
		{
			meshes.push_back(MeshUtils::MeshBuilder::createDiscSector(0.2f, 16));
			Geometry::Matrix4x4f mat;
			mat.translate(0.05f, 0.45f, 0.3f);
			mat.rotate_deg(180.0f, 0.0f, 1.0f, 0.0f);
			transformations.push_back(mat);
		}

		mesh = MeshUtils::combineMeshes(meshes, transformations);
	}

	rc.pushAndSetLighting(LightingParameters(false));
	rc.pushAndSetColorMaterial(Util::Color4f(color));
	rc.displayMesh(mesh.get());
	rc.popMaterial();
	rc.popLighting();
}
void ParticleBillboardRenderer::operator()(ParticleSystemNode * psys, FrameContext & context, const RenderParam & rp) {
	if(rp.getFlag(NO_GEOMETRY)) {
		return;
	}

	const auto & worldToCamera = context.getRenderingContext().getMatrix_worldToCamera();
	const auto cameraToWorld = worldToCamera.inverse();

	const auto halfRight = cameraToWorld.transformDirection(context.getWorldRightVector() * 0.5f);
	const auto halfUp = cameraToWorld.transformDirection(context.getWorldUpVector() * 0.5f);

	// 2. just update position for each particle and render
	// render particles
	const uint32_t count = psys->getParticleCount();

	Rendering::VertexDescription vertexDesc;
	const Rendering::VertexAttribute & posAttrib = vertexDesc.appendPosition3D();
	const Rendering::VertexAttribute & colorAttrib = vertexDesc.appendColorRGBAByte();
	const Rendering::VertexAttribute & texCoordAttrib = vertexDesc.appendTexCoord();
	// The usage of a cache for the mesh has been tested. Reusing a preallocated mesh is not faster.
	Util::Reference<Rendering::Mesh> mesh = new Rendering::Mesh(vertexDesc, 4 * count, 6 * count);
	mesh->setDataStrategy(Rendering::SimpleMeshDataStrategy::getPureLocalStrategy());
	Rendering::MeshIndexData & indexData = mesh->openIndexData();
	Rendering::MeshVertexData & vertexData = mesh->openVertexData();
	Util::Reference<Rendering::PositionAttributeAccessor> positionAccessor = Rendering::PositionAttributeAccessor::create(vertexData, posAttrib.getNameId());
	Util::Reference<Rendering::ColorAttributeAccessor> colorAccessor = Rendering::ColorAttributeAccessor::create(vertexData, colorAttrib.getNameId());
	Util::Reference<Rendering::TexCoordAttributeAccessor> texCoordAccessor = Rendering::TexCoordAttributeAccessor::create(vertexData, texCoordAttrib.getNameId());
	uint32_t * indices = indexData.data();

	uint_fast32_t index = 0;
	for(const auto & p : psys->getParticles()) {
		const Geometry::Vec3f upOffset = halfUp * p.size.getHeight();
		const Geometry::Vec3f rightOffset = halfRight * p.size.getWidth();

		colorAccessor->setColor(index + 0, p.color);
		texCoordAccessor->setCoordinate(index + 0, Geometry::Vec2f(0.0f, 0.0f));
		positionAccessor->setPosition(index + 0, p.position + upOffset - rightOffset);

		colorAccessor->setColor(index + 1, p.color);
		texCoordAccessor->setCoordinate(index + 1, Geometry::Vec2f(0.0f, 1.0f));
		positionAccessor->setPosition(index + 1, p.position - upOffset - rightOffset);

		colorAccessor->setColor(index + 2, p.color);
		texCoordAccessor->setCoordinate(index + 2, Geometry::Vec2f(1.0f, 1.0f));
		positionAccessor->setPosition(index + 2, p.position - upOffset + rightOffset);

		colorAccessor->setColor(index + 3, p.color);
		texCoordAccessor->setCoordinate(index + 3, Geometry::Vec2f(1.0f, 0.0f));
		positionAccessor->setPosition(index + 3, p.position + upOffset + rightOffset);

		*indices++ = index + 0;
		*indices++ = index + 1;
		*indices++ = index + 3;

		*indices++ = index + 1;
		*indices++ = index + 2;
		*indices++ = index + 3;

		index += 4;
	}

	indexData.markAsChanged();
	indexData.updateIndexRange();
	vertexData.markAsChanged();
	vertexData.updateBoundingBox();
	context.displayMesh(mesh.get());
}
void drawCoordSys(RenderingContext & rc, float scale) {
	static Util::Reference<Mesh> arrow;
	static Util::Reference<Mesh> sphere;
	static Util::Reference<Mesh> charX;
	static Util::Reference<Mesh> charY;
	static Util::Reference<Mesh> charZ;
	const float radius = 0.025f;
	if (arrow.isNull()) {
		std::deque<Mesh *> meshes;
		std::deque<Geometry::Matrix4x4> transformations;

		Geometry::Matrix4x4 transform;

		meshes.push_back(MeshUtils::MeshBuilder::createConicalFrustum(radius, radius, 0.7f, 16));
		transformations.push_back(transform);

		meshes.push_back(MeshUtils::MeshBuilder::createConicalFrustum(radius, 2.0f * radius, 0.01f, 16));
		transform.translate(0.7f, 0.0f, 0.0f);
		transformations.push_back(transform);

		meshes.push_back(MeshUtils::MeshBuilder::createCone(2.0f * radius, 0.29f, 16));
		transform.translate(0.01f, 0.0f, 0.0f);
		transformations.push_back(transform);

		arrow = MeshUtils::combineMeshes(meshes, transformations);
		MeshUtils::optimizeIndices(arrow.get());

		while (!meshes.empty()) {
			delete meshes.back();
			meshes.pop_back();
		}
	}
	if (sphere.isNull()) {
		Util::Reference<Mesh> icosahedron = MeshUtils::PlatonicSolids::createIcosahedron();
		sphere = MeshUtils::PlatonicSolids::createEdgeSubdivisionSphere(icosahedron.get(), 2);
		Geometry::Matrix4x4 transform;
		transform.scale(1.1f * radius);
		MeshUtils::transform(sphere.get()->openVertexData(), transform);
	}
	if(charX.isNull()) {
		std::deque<Mesh *> meshes;
		std::deque<Geometry::Matrix4x4> transformations;

		VertexDescription vertexDescription;
		vertexDescription.appendPosition3D();
		vertexDescription.appendNormalFloat();

		const Geometry::Box box(Geometry::Vec3f(0.0f, 0.0f, 0.0f), 0.02f, 0.2f, 0.05f);
		{
			meshes.push_back(MeshUtils::MeshBuilder::createBox(vertexDescription, box));
			Geometry::Matrix4x4 transform;
			transform.translate(1.2f, 0.0f, 0.0f);
			transform.rotate_deg(30.0f, 0.0f, 0.0f, -1.0f);
			transformations.push_back(transform);
		}
		{
			meshes.push_back(MeshUtils::MeshBuilder::createBox(vertexDescription, box));
			Geometry::Matrix4x4 transform;
			transform.translate(1.2f, 0.0f, 0.0f);
			transform.rotate_deg(-30.0f, 0.0f, 0.0f, -1.0f);
			transformations.push_back(transform);
		}
		charX = MeshUtils::combineMeshes(meshes, transformations);
		MeshUtils::optimizeIndices(charX.get());

		while(!meshes.empty()) {
			delete meshes.back();
			meshes.pop_back();
		}
	}
	if(charY.isNull()) {
		std::deque<Mesh *> meshes;
		std::deque<Geometry::Matrix4x4> transformations;

		VertexDescription vertexDescription;
		vertexDescription.appendPosition3D();
		vertexDescription.appendNormalFloat();

		const Geometry::Box box(Geometry::Vec3f(0.0f, 0.0f, 0.0f), 0.02f, 0.1f, 0.05f);
		{
			meshes.push_back(MeshUtils::MeshBuilder::createBox(vertexDescription, box));
			Geometry::Matrix4x4 transform;
			transform.translate(0.025f, 0.045f, 0.0f);
			transform.rotate_deg(30.0f, 0.0f, 0.0f, -1.0f);
			transformations.push_back(transform);
		}
		{
			meshes.push_back(MeshUtils::MeshBuilder::createBox(vertexDescription, box));
			Geometry::Matrix4x4 transform;
			transform.translate(-0.025f, 0.045f, 0.0f);
			transform.rotate_deg(-30.0f, 0.0f, 0.0f, -1.0f);
			transformations.push_back(transform);
		}
		{
			meshes.push_back(MeshUtils::MeshBuilder::createBox(vertexDescription, box));
			Geometry::Matrix4x4 transform;
			transform.translate(0.0f, -0.045f, 0.0f);
			transformations.push_back(transform);
		}
		charY = MeshUtils::combineMeshes(meshes, transformations);
		Geometry::Matrix4x4 transform;
		transform.translate(1.2f, 0.0f, 0.0f);
		transform.rotate_deg(90.0f, 0.0f, 0.0f, -1.0f);
		MeshUtils::transform(charY->openVertexData(), transform);
		MeshUtils::optimizeIndices(charY.get());

		while(!meshes.empty()) {
			delete meshes.back();
			meshes.pop_back();
		}
	}
	if(charZ.isNull()) {
		std::deque<Mesh *> meshes;
		std::deque<Geometry::Matrix4x4> transformations;

		VertexDescription vertexDescription;
		vertexDescription.appendPosition3D();
		vertexDescription.appendNormalFloat();

		const Geometry::Box box(Geometry::Vec3f(0.0f, 0.0f, 0.0f), 0.02f, 0.1f, 0.05f);
		{
			meshes.push_back(MeshUtils::MeshBuilder::createBox(vertexDescription, box));
			Geometry::Matrix4x4 transform;
			transform.translate(1.2f, 0.075f, 0.0f);
			transform.rotate_deg(90.0f, 0.0f, 0.0f, -1.0f);
			transformations.push_back(transform);
		}
		{
			meshes.push_back(MeshUtils::MeshBuilder::createBox(vertexDescription, box));
			Geometry::Matrix4x4 transform;
			transform.translate(1.2f, 0.0f, 0.0f);
			transform.rotate_deg(-30.0f, 0.0f, 0.0f, -1.0f);
			transform.scale(1.0f, 1.6f, 1.0f);
			transformations.push_back(transform);
		}
		{
			meshes.push_back(MeshUtils::MeshBuilder::createBox(vertexDescription, box));
			Geometry::Matrix4x4 transform;
			transform.translate(1.2f, -0.075f, 0.0f);
			transform.rotate_deg(-90.0f, 0.0f, 0.0f, -1.0f);
			transformations.push_back(transform);
		}
		charZ = MeshUtils::combineMeshes(meshes, transformations);
		MeshUtils::optimizeIndices(charZ.get());

		while(!meshes.empty()) {
			delete meshes.back();
			meshes.pop_back();
		}
	}
	// Origin
	rc.pushAndSetColorMaterial(Util::ColorLibrary::WHITE);
	rc.displayMesh(sphere.get());
	rc.popMaterial();

	// X axis
	Geometry::Matrix4x4 transform;
	transform.scale(scale, 1.0f, 1.0f);
	rc.pushMatrix_modelToCamera();
	rc.multMatrix_modelToCamera(transform);
	rc.pushAndSetColorMaterial(Util::ColorLibrary::RED);
	rc.displayMesh(arrow.get());
	rc.displayMesh(charX.get());
	rc.popMaterial();
	rc.popMatrix_modelToCamera();
	// Y axis
	transform.setIdentity();
	transform.scale(1.0f, scale, 1.0f);
	transform.rotate_deg(90.0f, 0.0f, 0.0f, 1.0f);
	rc.pushMatrix_modelToCamera();
	rc.multMatrix_modelToCamera(transform);
	rc.pushAndSetColorMaterial(Util::ColorLibrary::GREEN);
	rc.displayMesh(arrow.get());
	rc.displayMesh(charY.get());
	rc.popMaterial();
	rc.popMatrix_modelToCamera();
	// Z axis
	transform.setIdentity();
	transform.scale(1.0f, 1.0f, scale);
	transform.rotate_deg(90.0f, 0.0f, -1.0f, 0.0f);
	rc.pushMatrix_modelToCamera();
	rc.multMatrix_modelToCamera(transform);
	rc.pushAndSetColorMaterial(Util::ColorLibrary::BLUE);
	rc.displayMesh(arrow.get());
	rc.displayMesh(charZ.get());
	rc.popMaterial();
	rc.popMatrix_modelToCamera();
}
void QuadtreeMeshBuilder::createDebugOutput(const std::deque<QuadtreeMeshBuilder::QuadTree *> & leaves, Util::PixelAccessor * sourceDepth, Util::PixelAccessor * sourceColor) {
	const uint32_t bitmapWidth = static_cast<uint32_t> (sourceDepth->getWidth());
	const uint32_t bitmapHeight = static_cast<uint32_t> (sourceDepth->getHeight());
	Util::Reference<Util::Bitmap> depthDebugBitmap = new Util::Bitmap(bitmapWidth, bitmapHeight, Util::PixelFormat::MONO_FLOAT);
	Util::Reference<Util::Bitmap> quadTreeDebugBitmap = new Util::Bitmap(bitmapWidth, bitmapHeight, Util::PixelFormat::RGBA);
	Util::Reference<Util::PixelAccessor> destQuadTree(Util::PixelAccessor::create(quadTreeDebugBitmap.get()));
	float depthMin = std::numeric_limits<float>::max();
	float depthMax = std::numeric_limits<float>::lowest();
	{
		for (uint_fast32_t y = 0; y < bitmapHeight; ++y) {
			for (uint_fast32_t x = 0; x < bitmapWidth; ++x) {
				const float depthValue = sourceDepth->readSingleValueFloat(x, y);
				if (depthValue < depthMin) {
					depthMin = depthValue;
				}
				if (depthValue > depthMax) {
					depthMax = depthValue;
				}
			}
		}
		Util::Reference<Util::PixelAccessor> destDepth(Util::PixelAccessor::create(depthDebugBitmap.get()));
		const float depthScale = depthMax - depthMin;
		for (uint_fast32_t y = 0; y < bitmapHeight; ++y) {
			for (uint_fast32_t x = 0; x < bitmapWidth; ++x) {
				const float depthValue = sourceDepth->readSingleValueFloat(x, y);
				destDepth->writeColor(x, bitmapHeight - y - 1, Util::Color4f((depthValue - depthMin) / depthScale, 0.0f, 0.0f, 0.0f));
				destQuadTree->writeColor(x, bitmapHeight - y - 1, Util::Color4ub(0, 0, 0, 0));
			}
		}
	}
	for (const auto & leaf : leaves) {
		const uint16_t xMin = leaf->getX();
		const uint16_t yMin = leaf->getY();
		const uint16_t xMax = leaf->getWidth() + xMin;
		const uint16_t yMax = leaf->getHeight() + yMin;
		for (uint_fast32_t x = xMin; x < xMax; ++x) {
			destQuadTree->writeColor(x, bitmapHeight - yMin - 1, Util::Color4ub(255, 255, 255, 127));
		}
		for (uint_fast32_t y = yMin; y < yMax; ++y) {
			destQuadTree->writeColor(xMin, bitmapHeight - y - 1, Util::Color4ub(255, 255, 255, 127));
		}
		const uint16_t xHalf = xMin + leaf->getWidth() / 2;
		const uint16_t yHalf = yMin + leaf->getHeight() / 2;

		const Util::Color4ub errorColor(255, 0, 255, 255);

		Util::Color4ub drawColor(255, 0, 0, 127);
		const QuadtreeMeshBuilder::QuadTree * west = leaf->getWestNeighbor();
		if(west != nullptr) {
			const uint16_t westXHalf = west->getX() + west->getWidth() / 2;
			const uint16_t westYHalf = west->getY() + west->getHeight() / 2;
			// Check if neighbor is correct.
			if(west->getHeight() < leaf->getHeight()) {
				drawColor = errorColor;
			}
			if(west->getX() + west->getWidth() != xMin) {
				drawColor = errorColor;
			}
			drawLine(destQuadTree.get(), drawColor, xHalf, bitmapHeight - yHalf - 1 - 1, westXHalf, bitmapHeight - westYHalf - 1 - 1);
		} else {
			// Check if neighbor should be missing.
			if(xMin != 0) {
				drawColor = errorColor;
			}
			drawLine(destQuadTree.get(), drawColor, xHalf, bitmapHeight - yHalf - 1 - 1, static_cast<int32_t>(0.75 * xMin + 0.25 * xMax), bitmapHeight - yHalf - 1 - 1);
		}

		drawColor = Util::Color4ub(255, 255, 0, 127);
		const QuadtreeMeshBuilder::QuadTree * east = leaf->getEastNeighbor();
		if(east != nullptr) {
			const uint16_t eastXHalf = east->getX() + east->getWidth() / 2;
			const uint16_t eastYHalf = east->getY() + east->getHeight() / 2;
			// Check if neighbor is correct.
			if(east->getHeight() < leaf->getHeight()) {
				drawColor = errorColor;
			}
			if(xMax != east->getX()) {
				drawColor = errorColor;
			}
			drawLine(destQuadTree.get(), drawColor, xHalf, bitmapHeight - yHalf - 1 + 1, eastXHalf, bitmapHeight - eastYHalf - 1 + 1);
		} else {
			// Check if neighbor should be missing.
			if(xMax != bitmapWidth - 1) {
				drawColor = errorColor; // Error
			}
			drawLine(destQuadTree.get(), drawColor, xHalf, bitmapHeight - yHalf - 1 + 1, static_cast<int32_t>(0.25 * xMin + 0.75 * xMax), bitmapHeight - yHalf - 1 + 1);
		}

		drawColor = Util::Color4ub(0, 0, 255, 127);
		const QuadtreeMeshBuilder::QuadTree * north = leaf->getNorthNeighbor();
		if(north != nullptr) {
			const uint16_t northXHalf = north->getX() + north->getWidth() / 2;
			const uint16_t northYHalf = north->getY() + north->getHeight() / 2;
			// Check if neighbor is correct.
			if(north->getWidth() < leaf->getWidth()) {
				drawColor = errorColor;
			}
			if(north->getY() + north->getHeight() != yMin) {
				drawColor = errorColor;
			}
			drawLine(destQuadTree.get(), drawColor, xHalf, bitmapHeight - yHalf - 1, northXHalf, bitmapHeight - northYHalf - 1);
		} else {
			// Check if neighbor should be missing.
			if(yMin != 0) {
				drawColor = errorColor; // Error
			}
			drawLine(destQuadTree.get(), drawColor, xHalf, bitmapHeight - yHalf - 1, xHalf, static_cast<int32_t>(bitmapHeight - (0.75 * yMin + 0.25 * yMax) - 1));
		}

		drawColor = Util::Color4ub(0, 255, 255, 127);
		const QuadtreeMeshBuilder::QuadTree * south = leaf->getSouthNeighbor();
		if(south != nullptr) {
			const uint16_t southXHalf = south->getX() + south->getWidth() / 2;
			const uint16_t southYHalf = south->getY() + south->getHeight() / 2;
			// Check if neighbor is correct.
			if(south->getWidth() < leaf->getWidth()) {
				drawColor = errorColor;
			}
			if(yMax != south->getY()) {
				drawColor = errorColor;
			}
			drawLine(destQuadTree.get(), drawColor, xHalf, bitmapHeight - yHalf - 1, southXHalf, bitmapHeight - southYHalf - 1);
		} else {
			// Check if neighbor should be missing.
			if(yMax != bitmapHeight - 1) {
				drawColor = errorColor; // Error
			}
			drawLine(destQuadTree.get(), drawColor, xHalf, bitmapHeight - yHalf - 1, xHalf, static_cast<int32_t>(bitmapHeight - (0.25 * yMin + 0.75 * yMax) - 1));
		}

		destQuadTree->writeColor(xHalf, bitmapHeight - yHalf - 1, Util::Color4ub(0, 0, 0, 127));
	}
	const std::string currentTime = Util::Utils::createTimeStamp();
	if(sourceColor != nullptr) {
		Util::Reference<Util::Bitmap> colorDebugBitmap = new Util::Bitmap(bitmapWidth, bitmapHeight, Util::PixelFormat::RGB);
		Util::Reference<Util::PixelAccessor> destColor(Util::PixelAccessor::create(colorDebugBitmap.get()));
		for (uint_fast32_t y = 0; y < bitmapHeight; ++y) {
			for (uint_fast32_t x = 0; x < bitmapWidth; ++x) {
				destColor->writeColor(x, bitmapHeight - y - 1, sourceColor->readColor4f(x, y));
			}
		}
		Util::Serialization::saveBitmap(*colorDebugBitmap.get(), Util::FileName("screens/QuadTreeMeshBuilder_" + currentTime + "_Color.png"));
	}
	Util::Serialization::saveBitmap(*depthDebugBitmap.get(), Util::FileName("screens/QuadTreeMeshBuilder_" + currentTime + "_Depth.png"));
	Util::Serialization::saveBitmap(*quadTreeDebugBitmap.get(), Util::FileName("screens/QuadTreeMeshBuilder_" + currentTime + "_QuadTree.png"));
	std::ofstream textDebug("screens/QuadTreeMeshBuilder_Information.txt", std::ios_base::out | std::ios_base::app);
	textDebug << currentTime << '\t' << leaves.size() << '\t' << depthMin << '\t' << depthMax << '\n';
//	sleep(1);
}
void AbstractOnGpuComparator::releaseTexture(const Util::Reference<Texture> & tex) {
	usedTextures.erase(tex);
	freeTextures[Geometry::Vec2i(tex->getWidth(), tex->getHeight())].push_back(tex);
}
int test_spherical_sampling_serialization() {
#ifdef MINSG_EXT_SVS
	std::cout << "Test serialization of SVS objects ... ";
	Util::Timer timer;
	timer.reset();

	using namespace MinSG::SVS;
	MinSG::SceneManagement::SceneManager sceneManager;

	const uint32_t count = 10;
	std::array<Util::Reference<MinSG::GeometryNode>, count> nodes;
	for(uint_fast32_t i = 0; i < count; ++i) {
		nodes[i] = new MinSG::GeometryNode;
		sceneManager.registerNode(std::string("Node") + Util::StringUtils::toString(i), nodes[i].get());
	}
	MinSG::VisibilitySubdivision::VisibilityVector vv;
	for(uint_fast32_t i = 0; i < count; ++i) {
		vv.setNode(nodes[i].get(), i);
	}

	std::vector<SamplePoint> samples;
	{
		using namespace Rendering::MeshUtils::PlatonicSolids;
		Util::Reference<Rendering::Mesh> mesh = createEdgeSubdivisionSphere(createIcosahedron(), 4);
		auto accessor = Rendering::PositionAttributeAccessor::create(mesh->openVertexData(), Rendering::VertexAttributeIds::POSITION);
		for(std::size_t i = 0; accessor->checkRange(i); ++i) {
			samples.emplace_back(accessor->getPosition(i));
		}
	}
	{
		std::stringstream stream;
		stream.precision(std::numeric_limits<long double>::digits10);
		// Serialize
		for(const auto & sample : samples) {
			stream << sample.getPosition() << ' ';
			sample.getValue().serialize(stream, sceneManager);
			stream << ' ';
		}
		// Unserialize
		std::vector<SamplePoint> newSamples;
		for(std::size_t s = 0; s < samples.size(); ++s) {
			Geometry::Vec3f pos;
			stream >> pos;
			SamplePoint sample(pos);
			sample.setValue(MinSG::VisibilitySubdivision::VisibilityVector::unserialize(stream, sceneManager));
			newSamples.push_back(sample);
		}
		for(std::size_t s = 0; s < samples.size(); ++s) {
			const SamplePoint & oldSample = samples[s];
			const SamplePoint & newSample = newSamples[s];
			if(oldSample.getPosition().distance(newSample.getPosition()) > std::numeric_limits<float>::epsilon()) {
				std::cout << "Serialization/unserialization failed." << std::endl;
				return EXIT_FAILURE;
			}
			const auto & oldVV = oldSample.getValue();
			const auto & newVV = newSample.getValue();
			for(uint_fast32_t n = 0; n < count; ++n) {
				if(oldVV.getBenefits(nodes[n].get()) != newVV.getBenefits(nodes[n].get())) {
					std::cout << "Serialization/unserialization failed." << std::endl;
					return EXIT_FAILURE;
				}
			}
		}
	}
	VisibilitySphere visibilitySphere(Geometry::Sphere_f(Geometry::Vec3f(1.0f, 2.0f, 3.0f), 17.0f), samples);
	{
		std::stringstream stream;
		stream.precision(std::numeric_limits<long double>::digits10);
		// Serialize
		stream << visibilitySphere.getSphere() << ' ' << samples.size();
		for(const auto & sample : samples) {
			stream << ' ' << sample.getPosition() << ' ';
			sample.getValue().serialize(stream, sceneManager);
			stream << ' ';
		}
		
		// Unserialize
		Geometry::Sphere_f sphere;
		stream >> sphere;
		std::size_t sampleCount;
		stream >> sampleCount;
		std::vector<SamplePoint> newSamples;
		for(std::size_t s = 0; s < sampleCount; ++s) {
			Geometry::Vec3f pos;
			stream >> pos;
			SamplePoint sample(pos);
			sample.setValue(MinSG::VisibilitySubdivision::VisibilityVector::unserialize(stream, sceneManager));
			newSamples.push_back(sample);
		}
		
		VisibilitySphere newVisibilitySphere(sphere, newSamples);
		if(!(visibilitySphere.getSphere() == newVisibilitySphere.getSphere())) {
			std::cout << "Serialization/unserialization failed." << std::endl;
			return EXIT_FAILURE;
		}
		for(std::size_t s = 0; s < samples.size(); ++s) {
			const SamplePoint & oldSample = visibilitySphere.getSamples()[s];
			const SamplePoint & newSample = newVisibilitySphere.getSamples()[s];
			if(oldSample.getPosition().distance(newSample.getPosition()) > std::numeric_limits<float>::epsilon()) {
				std::cout << "Serialization/unserialization failed." << std::endl;
				return EXIT_FAILURE;
			}
			const auto & oldVV = oldSample.getValue();
			const auto & newVV = newSample.getValue();
			for(uint_fast32_t n = 0; n < count; ++n) {
				if(oldVV.getBenefits(nodes[n].get()) != newVV.getBenefits(nodes[n].get())) {
					std::cout << "Serialization/unserialization failed." << std::endl;
					return EXIT_FAILURE;
				}
			}
		}
	}

	timer.stop();
	std::cout << "done (duration: " << timer.getSeconds() << " s).\n";
#endif /* MINSG_EXT_SVS */
	return EXIT_SUCCESS;
}
void OverdrawFactorEvaluator::measure(FrameContext & frameContext, Node & node, const Geometry::Rect & rect) {
	Rendering::RenderingContext & renderingContext = frameContext.getRenderingContext();

	// Set up FBO and texture
	Util::Reference<Rendering::FBO> fbo = new Rendering::FBO;
	renderingContext.pushAndSetFBO(fbo.get());
	Util::Reference<Rendering::Texture> depthStencilTexture = Rendering::TextureUtils::createDepthStencilTexture(rect.getWidth(), rect.getHeight());
	fbo->attachDepthStencilTexture(renderingContext, depthStencilTexture.get());

	// Disable color and depth writes
	renderingContext.pushAndSetColorBuffer(Rendering::ColorBufferParameters(false, false, false, false));
	renderingContext.pushAndSetDepthBuffer(Rendering::DepthBufferParameters(false, false, Rendering::Comparison::LESS));

	// Increase the stencil value for every rendered pixel
	Rendering::StencilParameters stencilParams;
	stencilParams.enable();
	stencilParams.setFunction(Rendering::Comparison::ALWAYS);
	stencilParams.setReferenceValue(0);
	stencilParams.setBitMask(0);
	stencilParams.setFailAction(Rendering::StencilParameters::INCR);
	stencilParams.setDepthTestFailAction(Rendering::StencilParameters::INCR);
	stencilParams.setDepthTestPassAction(Rendering::StencilParameters::INCR);
	renderingContext.pushAndSetStencil(stencilParams);

	// Render the node
	renderingContext.clearStencil(0);
	frameContext.displayNode(&node, 0);

	// Reset GL state
	renderingContext.popStencil();
	renderingContext.popDepthBuffer();
	renderingContext.popColorBuffer();

	// Fetch the texture.
	depthStencilTexture->downloadGLTexture(renderingContext);
	renderingContext.popFBO();

	Util::Reference<Util::PixelAccessor> stencilAccessor = Rendering::TextureUtils::createStencilPixelAccessor(renderingContext, *depthStencilTexture.get());

	std::vector<uint8_t> stencilValues;
	stencilValues.reserve(rect.getWidth() * rect.getHeight());
	for(uint_fast32_t y = 0; y < rect.getHeight(); ++y) {
		for(uint_fast32_t x = 0; x < rect.getWidth(); ++x) {
			const uint8_t stencilValue = stencilAccessor->readSingleValueByte(x, y);
			stencilValues.push_back(stencilValue);
		}
	}

// 	// Create and write debug image
// 	{
// 		Util::Reference<Rendering::Texture> colorTexture = Rendering::TextureUtils::createStdTexture(rect.getWidth(), rect.getHeight(), true);
// 		Util::Reference<Util::PixelAccessor> colorAccessor = Rendering::TextureUtils::createColorPixelAccessor(renderingContext, colorTexture.get());
// 		const auto stencilMinMax = std::minmax_element(stencilValues.cbegin(), stencilValues.cend());
// 		const auto stencilMin = *stencilMinMax.first;
// 		const auto stencilMax = *stencilMinMax.second;
// 		const double stencilRange = stencilMax - stencilMin;
// 		const double factor = 1.0 / stencilRange;
// 		// Color scheme RdYlBu with 5 of 8 colors from www.colorbrewer2.org
// 		const std::array<Util::Color4f, 5> gradient =	{
// 															Util::Color4ub(44, 123, 182, 255),
// 															Util::Color4ub(171, 217, 233, 255),
// 															Util::Color4ub(255, 255, 191, 255),
// 															Util::Color4ub(253, 174, 97, 255),
// 															Util::Color4ub(215, 25, 28, 255)
// 														};
// 		for(uint_fast32_t y = 0; y < rect.getHeight(); ++y) {
// 			for(uint_fast32_t x = 0; x < rect.getWidth(); ++x) {
// 				const uint8_t stencilValue = stencilValues[y * rect.getWidth() + x];
// 				if(stencilValue == 0) {
// 					colorAccessor->writeColor(x, y, Util::Color4f(1.0, 1.0, 1.0, 0.0));
// 				} else {
// 					const double normalizedValue = static_cast<double>(stencilValue - stencilMin) * factor;
// 					const double gradientPos = normalizedValue * (gradient.size() - 1);
// 					const size_t gradientIndex = std::floor(gradientPos);
// 					colorAccessor->writeColor(x, y, Util::Color4f(gradient[gradientIndex], gradient[gradientIndex + 1], gradientPos - gradientIndex));
// 				}
// 			}
// 		}
// 		Rendering::Serialization::saveTexture(renderingContext, colorTexture.get(), Util::FileName("stencil.png"));
// 	}

	if(resultRemoveZeroValues) {
		stencilValues.erase(std::remove(stencilValues.begin(), stencilValues.end(), 0),
							stencilValues.end());
	}
	uint8_t result = 0;
	if(!stencilValues.empty()) {
		if(resultQuantile >= 1.0) {
			result = *std::max_element(stencilValues.cbegin(), stencilValues.cend());
		} else if(resultQuantile <= 0.0) {
			result = *std::min_element(stencilValues.cbegin(), stencilValues.cend());
		} else {
			const std::size_t quantilePos = resultQuantile * stencilValues.size();
			std::nth_element(stencilValues.begin(),
							 std::next(stencilValues.begin(), static_cast<std::ptrdiff_t>(quantilePos)),
							 stencilValues.end());
			result = stencilValues[quantilePos];
		}
	}

	values->push_back(Util::GenericAttribute::createNumber(result));
	setMaxValue_i(result);
}
Exemple #26
0
void drawQuad(RenderingContext & rc, const Geometry::Vec3 & lowerLeft, const Geometry::Vec3 & lowerRight, const Geometry::Vec3 & upperRight,
				const Geometry::Vec3 & upperLeft) {
	static Util::Reference<Mesh> mesh;
	if (mesh.isNull()) {
		VertexDescription vertexDescription;
		vertexDescription.appendPosition3D();
		vertexDescription.appendNormalFloat();
		vertexDescription.appendTexCoord();
		mesh = new Mesh(vertexDescription, 4, 6);

		MeshIndexData & id = mesh->openIndexData();
		uint32_t * indices = id.data();
		indices[0] = 0;
		indices[1] = 1;
		indices[2] = 2;
		indices[3] = 0;
		indices[4] = 2;
		indices[5] = 3;
		id.updateIndexRange();
		id.markAsChanged();
	}
	const Geometry::Vec3 edgeA = lowerRight - lowerLeft;
	const Geometry::Vec3 edgeB = upperLeft - lowerLeft;
	Geometry::Vec3 normal = edgeA.cross(edgeB);
	normal.normalize();

	MeshVertexData & vd = mesh->openVertexData();
	float * vertices = reinterpret_cast<float *> (vd.data());
	// Lower left
	*vertices++ = lowerLeft.getX();
	*vertices++ = lowerLeft.getY();
	*vertices++ = lowerLeft.getZ();
	*vertices++ = normal.getX();
	*vertices++ = normal.getY();
	*vertices++ = normal.getZ();
	*vertices++ = 0.0f;
	*vertices++ = 0.0f;
	// Lower right
	*vertices++ = lowerRight.getX();
	*vertices++ = lowerRight.getY();
	*vertices++ = lowerRight.getZ();
	*vertices++ = normal.getX();
	*vertices++ = normal.getY();
	*vertices++ = normal.getZ();
	*vertices++ = 1.0f;
	*vertices++ = 0.0f;
	// Upper right
	*vertices++ = upperRight.getX();
	*vertices++ = upperRight.getY();
	*vertices++ = upperRight.getZ();
	*vertices++ = normal.getX();
	*vertices++ = normal.getY();
	*vertices++ = normal.getZ();
	*vertices++ = 1.0f;
	*vertices++ = 1.0f;
	// Upper left
	*vertices++ = upperLeft.getX();
	*vertices++ = upperLeft.getY();
	*vertices++ = upperLeft.getZ();
	*vertices++ = normal.getX();
	*vertices++ = normal.getY();
	*vertices++ = normal.getZ();
	*vertices++ = 0.0f;
	*vertices++ = 1.0f;
	vd.updateBoundingBox();
	vd.markAsChanged();

	rc.displayMesh(mesh.get());
}
Exemple #27
0
int test_OutOfCore() {
#ifdef MINSG_EXT_OUTOFCORE
	const bool verbose = true;

	// Tests for MinSG::OutOfCore::CacheObjectPriority
	if(sizeof(MinSG::OutOfCore::CacheObjectPriority) != 8) {
		return EXIT_FAILURE;
	}
	if(!(MinSG::OutOfCore::CacheObjectPriority(1, 2, 3) == MinSG::OutOfCore::CacheObjectPriority(1, 2, 3))) {
		return EXIT_FAILURE;
	}
	if(!(MinSG::OutOfCore::CacheObjectPriority(1, 100, 100) < MinSG::OutOfCore::CacheObjectPriority(2, 0, 0))) {
		return EXIT_FAILURE;
	}
	if(!(MinSG::OutOfCore::CacheObjectPriority(2, 1, 100) < MinSG::OutOfCore::CacheObjectPriority(2, 2, 0))) {
		return EXIT_FAILURE;
	}
	if(!(MinSG::OutOfCore::CacheObjectPriority(2, 2, 1) < MinSG::OutOfCore::CacheObjectPriority(2, 2, 2))) {
		return EXIT_FAILURE;
	}

	std::default_random_engine engine;
	std::uniform_int_distribution<std::size_t> vertexCountDist(10, 1000);
	const uint32_t numMeshes = 30000;
	const Util::TemporaryDirectory tempDir("MinSGTest_OutOfCore");
	
	// Create empty meshes and save them into a subdirectory.
	{
		Rendering::VertexDescription vertexDesc;
		vertexDesc.appendPosition3D();
		
		for(uint_fast32_t i = 0; i < numMeshes; ++i) {
			Util::Reference<Rendering::Mesh> mesh = new Rendering::Mesh(vertexDesc, vertexCountDist(engine), 64);
			Rendering::MeshVertexData & vertexData = mesh->openVertexData();
			std::fill_n(vertexData.data(), vertexData.dataSize(), 0);
			vertexData.markAsChanged();
			Rendering::MeshIndexData & indexData = mesh->openIndexData();
			std::fill_n(indexData.data(), indexData.getIndexCount(), 0);
			indexData.markAsChanged();
			const std::string numberString = Util::StringUtils::toString<uint32_t>(i);
			Rendering::Serialization::saveMesh(mesh.get(), Util::FileName(tempDir.getPath().getDir() + numberString + ".mmf"));
		}
	}
	
	// Set up the OutOfCore system.
	MinSG::FrameContext frameContext;
	
	MinSG::OutOfCore::setUp(frameContext);

	MinSG::OutOfCore::CacheManager & manager = MinSG::OutOfCore::getCacheManager();
	manager.addCacheLevel(MinSG::OutOfCore::CacheLevelType::FILE_SYSTEM, 0);
	manager.addCacheLevel(MinSG::OutOfCore::CacheLevelType::FILES, 512 * kibibyte);
	manager.addCacheLevel(MinSG::OutOfCore::CacheLevelType::MAIN_MEMORY, 256 * kibibyte);
	
	Util::Timer addTimer;
	addTimer.reset();
	std::cout << "Adding meshes ..." << std::flush;
	
	// Add the meshes to the OutOfCore system.
	std::vector<Util::Reference<Rendering::Mesh> > meshes;
	meshes.reserve(numMeshes);
	static const Geometry::Box boundingBox(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
	for(uint_fast32_t i = 0; i < numMeshes; ++i) {
		const std::string numberString = Util::StringUtils::toString<uint32_t>(i);
		meshes.push_back(MinSG::OutOfCore::addMesh(Util::FileName(tempDir.getPath().getDir() + numberString + ".mmf"), boundingBox));
	}
	
	manager.trigger();
	
	addTimer.stop();
	std::cout << " done (" << addTimer.getSeconds() << " s)" << std::endl;
	
	Util::Timer displayTimer;
	Util::Timer assureLocalTimer;
	Util::Timer overallTimer;
	overallTimer.reset();

	uint32_t frame = 0;

	{
		// Simulate frames to get the OutOfCore system working.
		std::uniform_int_distribution<std::size_t> indexDist(0, meshes.size() - 1);
		for(; frame < 10; ++frame) {
			std::cout << "Executing frame " << frame << " ..." << std::flush;
			frameContext.beginFrame();
			displayTimer.reset();
			// Simulate display of meshes to change the priorities of the system.
			for(uint32_t i = 0; i < meshes.size() / 2; ++i) {
				const uint32_t meshIndex = indexDist(engine);
				Rendering::Mesh * mesh = meshes[meshIndex].get();
				manager.meshDisplay(mesh);
			}
			manager.trigger();
			displayTimer.stop();
			assureLocalTimer.reset();
			for(uint32_t i = 0; i < 10; ++i) {
				const uint32_t meshIndex = indexDist(engine);
				
				Rendering::Mesh * mesh = meshes[meshIndex].get();
				const Rendering::MeshVertexData & vd = mesh->openVertexData();
				const Rendering::MeshIndexData & id = mesh->openIndexData();
				
				if (!vd.hasLocalData() || !id.hasLocalData()) {
					std::cout << "Error: Mesh has no local data." << std::endl;
					return EXIT_FAILURE;
				}
			}
			assureLocalTimer.stop();
			frameContext.endFrame();
			std::cout << " done (display: " << displayTimer.getSeconds() << " s, assureLocal: " << assureLocalTimer.getSeconds() << " s)" << std::endl;

			if(verbose) {
				outputCacheLevelInformation();
			}
		}
	}

	for(uint32_t round = 0; round < 10; ++round) {
		Util::Timer addAgainTimer;
		addAgainTimer.reset();
		std::cout << "Adding additional meshes ..." << std::flush;
		
		// Simulate loading a second scene by adding meshes again.
		meshes.reserve(meshes.size() + 3 * numMeshes);
		for(uint_fast32_t i = 0; i < numMeshes; ++i) {
			const std::string numberString = Util::StringUtils::toString<uint32_t>(i);
			meshes.push_back(MinSG::OutOfCore::addMesh(Util::FileName(tempDir.getPath().getDir() + numberString + ".mmf"), boundingBox));
			meshes.push_back(MinSG::OutOfCore::addMesh(Util::FileName(tempDir.getPath().getDir() + numberString + ".mmf"), boundingBox));
			meshes.push_back(MinSG::OutOfCore::addMesh(Util::FileName(tempDir.getPath().getDir() + numberString + ".mmf"), boundingBox));
		}
		
		manager.trigger();
		
		addAgainTimer.stop();
		std::cout << " done (" << addAgainTimer.getSeconds() << " s)" << std::endl;

		// Simulate frames to get the OutOfCore system working.
		std::normal_distribution<double> indexDist(meshes.size() / 2, std::sqrt(meshes.size() / 2));
		const auto untilFrame = frame + 5;
		for(; frame < untilFrame; ++frame) {
			std::cout << "Executing frame " << frame << " ..." << std::flush;
			frameContext.beginFrame();
			displayTimer.reset();
			// Simulate display of meshes to change the priorities of the system.
			for(uint32_t i = 0; i < meshes.size() / 10; ++i) {
				const std::size_t meshIndex = std::max(static_cast<std::size_t>(0), std::min(static_cast<std::size_t>(indexDist(engine)), meshes.size() - 1));
				Rendering::Mesh * mesh = meshes[meshIndex].get();
				manager.meshDisplay(mesh);
			}
			manager.trigger();
			displayTimer.stop();
			frameContext.endFrame();
			std::cout << " done (display: " << displayTimer.getSeconds() << " s)" << std::endl;

			if(verbose) {
				outputCacheLevelInformation();
			}
		}
	}

	overallTimer.stop();
	std::cout << "Overall duration: " << overallTimer.getSeconds() << " s" << std::endl;
	
	MinSG::OutOfCore::shutDown();
	
	return EXIT_SUCCESS;
#else /* MINSG_EXT_OUTOFCORE */
	return EXIT_FAILURE;
#endif /* MINSG_EXT_OUTOFCORE */
}
int test_large_scene(Util::UI::Window * window, Util::UI::EventContext & eventContext) {
	// texture registry
	std::map<std::string, Util::Reference<Rendering::Texture> > textures;

	std::cout << "Create FrameContext...\n";
	FrameContext fc;

	unsigned int renderingFlags = /*BOUNDING_BOXES|SHOW_META_OBJECTS|*/FRUSTUM_CULLING/*|SHOW_COORD_SYSTEM*/;//|SHOW_COORD_SYSTEM;


	std::cout << "Create scene graph...\n";
	Util::Reference<GroupNode> root = new MinSG::ListNode();


	/// Skybox
	SkyboxState * sb = SkyboxState::createSkybox("Data/texture/?.bmp");
	root->addState(sb);


	/// Some shperes...
	{
		std::default_random_engine engine;
		std::uniform_real_distribution<float> coordinateDist(0.0f, 200.0f);
		
		std::vector<Util::Reference<Rendering::Mesh> > spheres;
		Util::Reference<Rendering::Mesh> icosahedron = Rendering::MeshUtils::PlatonicSolids::createIcosahedron();
		for(int i=0;i<6;++i)
			spheres.push_back(Rendering::MeshUtils::PlatonicSolids::createEdgeSubdivisionSphere(icosahedron.get(), i)); // 6... 81920 triangles each

		for (int i = 0; i < 1000; i++) {
			// create a real clone inclusive internal data!
			MinSG::GeometryNode * gn = new GeometryNode(spheres[std::uniform_int_distribution<std::size_t>(0, spheres.size() - 1)(engine)]->clone());
			gn->moveRel(Geometry::Vec3(coordinateDist(engine), coordinateDist(engine), coordinateDist(engine)));
			root->addChild(gn);
			gn->scale(0.1 + std::uniform_real_distribution<float>(0.0f, 1000.0f)(engine) / 400.0);
		}
	}

	/// Camera
	Node * schwein = loadModel(Util::FileName("Data/model/Schwein.low.t.ply"), MESH_AUTO_CENTER | MESH_AUTO_SCALE);

	ListNode * camera = new ListNode();
	CameraNode * camNode = new CameraNode();
	camNode->setViewport(Geometry::Rect_i(0, 0, 1024, 768));
	camNode->setNearFar(0.1, 2000);
	camNode->applyVerticalAngle(80);
	camNode->moveRel(Geometry::Vec3(0, 4, 10));
	camera->addChild(camNode);
	camera->addChild(schwein);
	schwein->moveRel(Geometry::Vec3(0, 0, 0));
	schwein->rotateLocal_deg(180, Geometry::Vec3(0, 1, 0));

	LightNode * myHeadLight = LightNode::createPointLight();
	myHeadLight->scale(1);
	myHeadLight->moveRel(Geometry::Vec3(0, 0, 0));
	camera->addChild(myHeadLight);
	LightingState * lightState = new LightingState;
	lightState->setLight(myHeadLight);
	root->addState(lightState);

	root->addChild(camera);


	/// Eventhandler
	MoveNodeHandler * eh = new MoveNodeHandler();
	MoveNodeHandler::initClaudius(eh, camera);


	// ---------------------------------------------------------------------------------------------

	Rendering::RenderingContext::clearScreen(Util::Color4f(0.5f, 0.5f, 0.5f, 0.5f));

	// ----
	GET_GL_ERROR();

	uint32_t fpsFrameCounter = 0;
	Util::Timer fpsTimer;

	std::cout << "\nEntering main loop...\n";


	// program main loop
	bool done = false;
	while (!done) {
		++fpsFrameCounter;
		double seconds = fpsTimer.getSeconds();
		if (seconds > 1.0) {
			double fps = static_cast<double> (fpsFrameCounter) / seconds;
			std::cout << "\r " << fps << " fps    ";
			std::cout.flush();
			fpsTimer.reset();
			fpsFrameCounter = 0;
		}

		// message processing loop
		eventContext.getEventQueue().process();
		while (eventContext.getEventQueue().getNumEventsAvailable() > 0) {
			Util::UI::Event event = eventContext.getEventQueue().popEvent();
			// check for messages
			switch (event.type) {
				// exit if the window is closed
				case Util::UI::EVENT_QUIT:
					done = true;
					break;


					// check for keypresses
				case Util::UI::EVENT_KEYBOARD: {
					if(event.keyboard.pressed && event.keyboard.key == Util::UI::KEY_ESCAPE) {
						done = true;
					}
					break;
				}

			} // end switch
		} // end of message processing

		// apply translation
		eh->execute();


		// clear screen
		Rendering::RenderingContext::clearScreen(Util::Color4f(0.0f, 0.0f, 0.0f, 1.0f));


		// enable Camera
		fc.setCamera(camNode);


		// render Scene
		root->display(fc, renderingFlags);

		window->swapBuffers();
		GET_GL_ERROR();
	} // end main loop


	// destroy scene graph
	MinSG::destroy(root.get());
	root = nullptr;

	// all is well ;)
	std::cout << "Exited cleanly\n";
	//system("pause");
	return EXIT_SUCCESS;
}
int main(int /*argc*/, char */*argv*/[]) {
	Util::init();

	Util::UI::Window::Properties properties;
	properties.positioned = true;
	properties.posX = 100;
	properties.posY = 100;
	properties.clientAreaWidth = 1024;
	properties.clientAreaHeight = 768;
	properties.title = "GUI Textfield and Buttons";
	properties.compatibilityProfile = true;
	auto window = Util::UI::createWindow(properties);

	Util::UI::EventContext eventContext;
	eventContext.getEventQueue().registerEventGenerator(std::bind(&Util::UI::Window::fetchEvents, window.get()));
	
	GUI::GUI_Manager guiManager(&eventContext);
	guiManager.setWindow(window.get());

	Util::Reference<GUI::Window> guiWin = guiManager.createWindow(Geometry::Rect_f(10, 10, 200, 200), "Window");

	Util::Reference<GUI::Textfield> guiText = guiManager.createTextfield("Text");
	guiText->setRect(Geometry::Rect_f(0, 0, 40, 20));
	guiWin->addContent(guiText.get());

	Util::Reference<GUI::Button> guiButton = guiManager.createButton("Clear");
	guiButton->setActionListener(	[&guiText](GUI::Component *, const Util::StringIdentifier &) {
										guiText->setText("");
										return true;
									});
	guiButton->setRect(Geometry::Rect_f(0, 25, 40, 20));
	guiWin->addContent(guiButton.get());

	bool done = false;
	while(!done) {
		eventContext.getEventQueue().process();
		while(eventContext.getEventQueue().getNumEventsAvailable() > 0) {
			auto event = eventContext.getEventQueue().popEvent();
			if(event.type == Util::UI::EVENT_QUIT ||
						(event.type == Util::UI::EVENT_KEYBOARD &&
						 event.keyboard.pressed &&
						 event.keyboard.key == Util::UI::KEY_ESCAPE)) {
				done = true;
			} else {
				guiManager.handleEvent(event);
			}
		}
		guiManager.display();
		window->swapBuffers();
	}
	return EXIT_SUCCESS;
}