Beispiel #1
0
Error CollisionResource::load(const ResourceFilename& filename)
{
	XmlElement el;
	XmlDocument doc;
	ANKI_CHECK(openFileParseXml(filename, doc));

	XmlElement collEl;
	ANKI_CHECK(doc.getChildElement("collisionShape", collEl));

	ANKI_CHECK(collEl.getChildElement("type", el));
	CString type;
	ANKI_CHECK(el.getText(type));

	XmlElement valEl;
	ANKI_CHECK(collEl.getChildElement("value", valEl));

	PhysicsWorld& physics = getManager().getPhysicsWorld();
	PhysicsCollisionShapeInitInfo csInit;

	if(type == "sphere")
	{
		F64 tmp;
		ANKI_CHECK(valEl.getF64(tmp));
		m_physicsShape = physics.newInstance<PhysicsSphere>(csInit, tmp);
	}
	else if(type == "box")
	{
		Vec3 extend;
		ANKI_CHECK(valEl.getVec3(extend));
		m_physicsShape = physics.newInstance<PhysicsBox>(csInit, extend);
	}
	else if(type == "staticMesh")
	{
		CString meshfname;
		ANKI_CHECK(valEl.getText(meshfname));

		MeshLoader loader(&getManager());
		ANKI_CHECK(loader.load(meshfname));

		m_physicsShape = physics.newInstance<PhysicsTriangleSoup>(csInit,
			reinterpret_cast<const Vec3*>(loader.getVertexData()),
			loader.getVertexSize(),
			reinterpret_cast<const U16*>(loader.getIndexData()),
			loader.getHeader().m_totalIndicesCount);
	}
	else
	{
		ANKI_LOGE("Incorrect collision type");
		return ErrorCode::USER_DATA;
	}

	return ErrorCode::NONE;
}
Beispiel #2
0
THIS::THIS(XmlElement* h):Element(h){

  /* attributes */
  createAttribute(attrib_sid,"sid");

  /** children**/

  /* data */
  XmlElement* element = handle;
  if(element){
    Utils::fromString(value,element->getText());
  }
}
Beispiel #3
0
THIS::THIS(XmlElement* h):Element(h){

  /* attributes */

  /* children */

  /* data */
  XmlElement* element = handle;
  if(element){
      Utils::fromString(indices,element->getText());
  }

}
Beispiel #4
0
THIS::THIS(XmlElement* h):Element(h){

  /* attributes */
  createAttribute(attrib_count,"count");
  createAttribute(attrib_id,"id");
  createAttribute(attrib_name,"name");

  /* children */
  XmlElement* element = handle;
  if(element){
    Utils::fromString(values,element->getText());
  }

}
Beispiel #5
0
THIS::THIS(XmlElement* h):Element(h){

  /* attributes */

  /* children */
  buildChildren(Types());

  /* data */
  XmlElement* element = handle;
  if(element){
    Utils::fromString(data,element->getText());
  }

}
Beispiel #6
0
Error Skeleton::load(const ResourceFilename& filename)
{
	XmlDocument doc;
	ANKI_CHECK(openFileParseXml(filename, doc));

	XmlElement rootEl;
	ANKI_CHECK(doc.getChildElement("skeleton", rootEl));
	XmlElement bonesEl;
	ANKI_CHECK(rootEl.getChildElement("bones", bonesEl));

	// count the bones count
	XmlElement boneEl;
	U32 bonesCount = 0;

	ANKI_CHECK(bonesEl.getChildElement("bone", boneEl));
	ANKI_CHECK(boneEl.getSiblingElementsCount(bonesCount));
	++bonesCount;

	m_bones.create(getAllocator(), bonesCount);

	// Load every bone
	bonesCount = 0;
	do
	{
		Bone& bone = m_bones[bonesCount++];

		// <name>
		XmlElement nameEl;
		ANKI_CHECK(boneEl.getChildElement("name", nameEl));
		CString tmp;
		ANKI_CHECK(nameEl.getText(tmp));
		bone.m_name.create(getAllocator(), tmp);

		// <transform>
		XmlElement trfEl;
		ANKI_CHECK(boneEl.getChildElement("transform", trfEl));
		ANKI_CHECK(trfEl.getMat4(bone.m_transform));

		// Advance
		ANKI_CHECK(boneEl.getNextSiblingElement("bone", boneEl));
	} while(boneEl);

	return ErrorCode::NONE;
}
Beispiel #7
0
//==============================================================================
void Skeleton::load(const CString& filename, ResourceInitializer& init)
{
	XmlDocument doc;
	doc.loadFile(filename, init.m_tempAlloc);

	XmlElement rootEl = doc.getChildElement("skeleton");
	XmlElement bonesEl = rootEl.getChildElement("bones");

	// count the bones count
	U bonesCount = 0;

	XmlElement boneEl = bonesEl.getChildElement("bone");

	do
	{
		++bonesCount;
		boneEl = boneEl.getNextSiblingElement("bone");
	} while(boneEl);

	// Alloc the vector
	m_bones = std::move(ResourceVector<Bone>(init.m_alloc));
	m_bones.resize(bonesCount, Bone(init.m_alloc));

	// Load every bone
	boneEl = bonesEl.getChildElement("bone");
	bonesCount = 0;
	do
	{
		Bone& bone = m_bones[bonesCount++];

		// <name>
		XmlElement nameEl = boneEl.getChildElement("name");
		bone.m_name = nameEl.getText();

		// <transform>
		XmlElement trfEl = boneEl.getChildElement("transform");
		bone.m_transform = trfEl.getMat4();

		// Advance 
		boneEl = boneEl.getNextSiblingElement("bone");
	} while(boneEl);
}
Beispiel #8
0
THIS::THIS(XmlElement* h):Element(h){

  /* attributes */
  createAttribute(attrib_count,"count");
  createAttribute(attrib_id,"id");
  createAttribute(attrib_name,"name");

  /* data */
  XmlElement* element = handle;
  if(element){
    std::vector<std::string> strings;
    Utils::fromString(strings,element->getText());
    std::vector<std::string>::iterator iter;
    for(iter = strings.begin(); iter != strings.end(); iter++){
      values.push_back((*iter) == "true" ? true : false);
    }
    
  }

}
Beispiel #9
0
THIS::THIS(XmlElement* h):Element(h){

  /* attributes */

  /* children */
  buildChildren(Types());

  /* data */
  XmlElement* element = handle;
  if(element){
    std::string str = element->getText();
    /*remove spaces*/
    while(str.find(" ") != std::string::npos)
    {
      str.replace(str.find(" "), 1, "");
    }
    /*default*/
    data = Enum::LINEAR;
    if(str == "NEAREST"){
      data = Enum::NEAREST;
    }
  }

}
//==============================================================================
void MaterialProgramCreator::parseOperationTag(
	const XmlElement& operationTag, GLenum glshader, GLbitfield glshaderbit,
	MPString& out)
{
	static const char OUT[] = {"out"};

	// <id></id>
	I id = operationTag.getChildElement("id").getInt();
	
	// <returnType></returnType>
	XmlElement retTypeEl = operationTag.getChildElement("returnType");
	MPString retType(retTypeEl.getText(), m_alloc);
	MPString operationOut(m_alloc);
	if(retType != "void")
	{
		MPString tmp(MPString::toString(id, m_alloc));
		operationOut = ANKI_STRL(OUT) + tmp;
	}
	
	// <function>functionName</function>
	MPString funcName(
		operationTag.getChildElement("function").getText(), m_alloc);
	
	// <arguments></arguments>
	XmlElement argsEl = operationTag.getChildElementOptional("arguments");
	MPStringList argsList(m_alloc);
	
	if(argsEl)
	{
		// Get all arguments
		XmlElement argEl = argsEl.getChildElement("argument");
		do
		{
			MPString arg(argEl.getText(), m_alloc);

			// Search for all the inputs and mark the appropriate
			Input* input = nullptr;
			for(Input& in : m_inputs)
			{
				// Check that the first part of the string is equal to the 
				// variable and the following char is '['
				if(in.m_name == arg)
				{
					input = &in;
					in.m_shaderReferencedMask = glshaderbit;
					break;
				}
			}

			// The argument should be an input variable or an outXX
			if(!(input != nullptr 
				|| std::strncmp(&arg[0], OUT, sizeof(OUT) - 1) == 0))
			{
				throw ANKI_EXCEPTION("Incorrect argument: %s", &arg[0]);
			}

			// Add to a list and do something special if instanced
			if(input && input->m_instanced)
			{
				if(glshader == GL_VERTEX_SHADER)
				{
					argsList.push_back(ANKI_STRL(argEl.getText()) 
						+ "[gl_InstanceID]");

					m_instanceIdMask |= glshaderbit;
				}
				else if(glshader == GL_TESS_CONTROL_SHADER)
				{
					argsList.push_back(ANKI_STRL(argEl.getText()) 
						+ "[vInstanceId[0]]");

					m_instanceIdMask |= glshaderbit;
				}
				else if(glshader == GL_TESS_EVALUATION_SHADER)
				{
					argsList.push_back(ANKI_STRL(argEl.getText()) 
						+ "[commonPatch.instanceId]");
					
					m_instanceIdMask |= glshaderbit;
				}
				else if(glshader == GL_FRAGMENT_SHADER)
				{
					argsList.push_back(ANKI_STRL(argEl.getText()) 
						+ "[vInstanceId]");
					
					m_instanceIdMask |= glshaderbit;
				}
				else
				{
					throw ANKI_EXCEPTION(
						"Cannot access the instance ID in all shaders");
				}
			}
			else
			{
				argsList.push_back(MPString(argEl.getText(), m_alloc));
			}

			// Advance
			argEl = argEl.getNextSiblingElement("argument");
		} while(argEl);
	}

	// Now write everything
	MPString lines(m_alloc);
	lines.reserve(256);
	lines += "#if defined(" + funcName + "_DEFINED)";

	// Write the defines for the operationOuts
	for(const MPString& arg : argsList)
	{
		if(arg.find(OUT) == 0)
		{
			lines += " && defined(" + arg + "_DEFINED)";
		}
	}
	lines += "\n";

	if(retType != "void")
	{
		lines += "#\tdefine " + operationOut + "_DEFINED\n\t"
			+ retTypeEl.getText() + " " + operationOut + " = ";
	}
	else
	{
		lines += "\t";
	}
	
	// write the blah = func(args...)
	lines += funcName + "(";
	lines += argsList.join(", ");
	lines += ");\n";
	lines += "#endif";

	// Done
	out = std::move(lines);
}
Beispiel #11
0
std::string
XmlElement::getSubElementText( const std::string& name ) const
{
    XmlElement* e = getSubElement( name );
    return e? e->getText() : EMPTY_VALUE;
}
Beispiel #12
0
//==============================================================================
Error Material::parseMaterialTag(const XmlElement& materialEl,
	ResourceInitializer& rinit)
{
	Error err = ErrorCode::NONE;
	XmlElement el;

	// levelsOfDetail
	//
	XmlElement lodEl;
	ANKI_CHECK(materialEl.getChildElementOptional("levelsOfDetail", lodEl));

	if(lodEl)
	{
		I64 tmp;
		ANKI_CHECK(lodEl.getI64(tmp));
		m_lodsCount = (tmp < 1) ? 1 : tmp;
	}
	else
	{
		m_lodsCount = 1;
	}

	// shadow
	//
	XmlElement shadowEl;
	ANKI_CHECK(materialEl.getChildElementOptional("shadow", shadowEl));

	if(shadowEl)
	{
		I64 tmp;
		ANKI_CHECK(shadowEl.getI64(tmp));
		m_shadow = tmp;
	}

	// blendFunctions
	//
	XmlElement blendFunctionsEl;
	ANKI_CHECK(
		materialEl.getChildElementOptional("blendFunctions", blendFunctionsEl));

	if(blendFunctionsEl)
	{
		CString cstr;

		// sFactor
		ANKI_CHECK(blendFunctionsEl.getChildElement("sFactor", el));
		ANKI_CHECK(el.getText(cstr));
		m_blendingSfactor = blendToEnum(cstr);
		if(m_blendingSfactor == 0)
		{
			return ErrorCode::USER_DATA;
		}

		// dFactor
		ANKI_CHECK(blendFunctionsEl.getChildElement("dFactor", el));
		ANKI_CHECK(el.getText(cstr));
		m_blendingDfactor = blendToEnum(cstr);
		if(m_blendingDfactor == 0)
		{
			return ErrorCode::USER_DATA;
		}
	}
	else
	{
		m_passesCount = 2;
	}

	// depthTesting
	//
	XmlElement depthTestingEl;
	ANKI_CHECK(
		materialEl.getChildElementOptional("depthTesting", depthTestingEl));

	if(depthTestingEl)
	{
		I64 tmp;
		ANKI_CHECK(depthTestingEl.getI64(tmp));
		m_depthTesting = tmp;
	}

	// wireframe
	//
	XmlElement wireframeEl;
	ANKI_CHECK(materialEl.getChildElementOptional("wireframe", wireframeEl));

	if(wireframeEl)
	{
		I64 tmp;
		ANKI_CHECK(wireframeEl.getI64(tmp));
		m_wireframe = tmp;
	}

	// shaderProgram
	//
	ANKI_CHECK(materialEl.getChildElement("programs", el));
	MaterialProgramCreator loader(rinit.m_tempAlloc);
	ANKI_CHECK(loader.parseProgramsTag(el));

	m_tessellation = loader.hasTessellation();
	U tessCount = m_tessellation ? 2 : 1;

	// Alloc program vector
	ANKI_CHECK(m_progs.create(rinit.m_alloc,
		countShaders(ShaderType::VERTEX) 
		+ countShaders(ShaderType::TESSELLATION_CONTROL)
		+ countShaders(ShaderType::TESSELLATION_EVALUATION)
		+ countShaders(ShaderType::GEOMETRY)
		+ countShaders(ShaderType::FRAGMENT)));

	// Aloc progam descriptors
	m_pplines.resize(m_passesCount * m_lodsCount * tessCount);

	m_hash = 0;
	for(ShaderType shader = ShaderType::VERTEX; 
		shader <= ShaderType::FRAGMENT; 
		++shader)
	{
		Bool isTessellationShader = shader == ShaderType::TESSELLATION_CONTROL 
			|| shader == ShaderType::TESSELLATION_EVALUATION;

		if(!m_tessellation && isTessellationShader)
		{
			// Skip tessellation if not enabled
			continue;
		}

		if(shader == ShaderType::GEOMETRY)
		{
			// Skip geometry for now
			continue;
		}

		for(U level = 0; level < m_lodsCount; ++level)
		{
			if(level > 0 && isTessellationShader)
			{
				continue;
			}

			for(U pid = 0; pid < m_passesCount; ++pid)
			{
				for(U tess = 0; tess < tessCount; ++tess)
				{
					if(tess == 0 && isTessellationShader)
					{
						continue;
					}

					if(tess > 0 && shader == ShaderType::FRAGMENT)
					{
						continue;
					}

					TempResourceString src;
					TempResourceString::ScopeDestroyer srcd(
						&src, rinit.m_tempAlloc);

					ANKI_CHECK(src.sprintf(
						rinit.m_tempAlloc,
						"%s\n"
						"#define LOD %u\n"
						"#define PASS %u\n"
						"#define TESSELLATION %u\n"
						"%s\n",
						&rinit.m_resources._getShadersPrependedSource()[0],
						level, pid, tess, &loader.getProgramSource(shader)[0]));

					TempResourceString filename;
					TempResourceString::ScopeDestroyer filenamed(
						&filename, rinit.m_tempAlloc);

					ANKI_CHECK(createProgramSourceToCache(src, filename));

					RenderingKey key((Pass)pid, level, tess);
					ProgramResourcePointer& progr = getProgram(key, shader);
					ANKI_CHECK(
						progr.load(filename.toCString(), &rinit.m_resources));

					// Update the hash
					m_hash ^= computeHash(&src[0], src.getLength());
				}
			}
		}
	}

	ANKI_CHECK(populateVariables(loader));

	// Get uniform block size
	ANKI_ASSERT(m_progs.getSize() > 0);
	m_shaderBlockSize = loader.getUniformBlockSize();

	return err;
}
//==============================================================================
Error ParticleEmitterResource::load(const CString& filename)
{
	U32 tmp;

	XmlDocument doc;
	ANKI_CHECK(doc.loadFile(filename, getTempAllocator()));
	XmlElement rel; // Root element
	ANKI_CHECK(doc.getChildElement("particleEmitter", rel));

	// XML load
	//
	ANKI_CHECK(xmlF32(rel, "life", m_particle.m_life));
	ANKI_CHECK(xmlF32(rel, "lifeDeviation", m_particle.m_lifeDeviation));

	ANKI_CHECK(xmlF32(rel, "mass", m_particle.m_mass));
	ANKI_CHECK(xmlF32(rel, "massDeviation", m_particle.m_massDeviation));

	ANKI_CHECK(xmlF32(rel, "size", m_particle.m_size));
	ANKI_CHECK(xmlF32(rel, "sizeDeviation", m_particle.m_sizeDeviation));
	ANKI_CHECK(xmlF32(rel, "sizeAnimation", m_particle.m_sizeAnimation));

	ANKI_CHECK(xmlF32(rel, "alpha", m_particle.m_alpha));
	ANKI_CHECK(xmlF32(rel, "alphaDeviation", m_particle.m_alphaDeviation));

	tmp = m_particle.m_alphaAnimation;
	ANKI_CHECK(xmlU32(rel, "alphaAnimationEnabled", tmp));
	m_particle.m_alphaAnimation = tmp;

	ANKI_CHECK(xmlVec3(rel, "forceDirection", m_particle.m_forceDirection));
	ANKI_CHECK(xmlVec3(rel, "forceDirectionDeviation",
		m_particle.m_forceDirectionDeviation));
	ANKI_CHECK(xmlF32(rel, "forceMagnitude", m_particle.m_forceMagnitude));
	ANKI_CHECK(xmlF32(rel, "forceMagnitudeDeviation",
		m_particle.m_forceMagnitudeDeviation));

	ANKI_CHECK(xmlVec3(rel, "gravity", m_particle.m_gravity));
	ANKI_CHECK(xmlVec3(rel, "gravityDeviation", m_particle.m_gravityDeviation));

	ANKI_CHECK(xmlVec3(rel, "startingPosition", m_particle.m_startingPos));
	ANKI_CHECK(xmlVec3(rel, "startingPositionDeviation",
		m_particle.m_startingPosDeviation));

	ANKI_CHECK(xmlU32(rel, "maxNumberOfParticles", m_maxNumOfParticles));

	ANKI_CHECK(xmlF32(rel, "emissionPeriod", m_emissionPeriod));
	ANKI_CHECK(xmlU32(rel, "particlesPerEmittion", m_particlesPerEmittion));
	tmp = m_usePhysicsEngine;
	ANKI_CHECK(xmlU32(rel, "usePhysicsEngine", tmp));
	m_usePhysicsEngine = tmp;

	XmlElement el;
	CString cstr;
	ANKI_CHECK(rel.getChildElement("material", el));
	ANKI_CHECK(el.getText(cstr));
	ANKI_CHECK(m_material.load(cstr, &getManager()));

	// sanity checks
	//

	static const char* ERROR = "Particle emmiter: "
		"Incorrect or missing value %s";

	if(m_particle.m_life <= 0.0)
	{
		ANKI_LOGE(ERROR, "life");
		return ErrorCode::USER_DATA;
	}

	if(m_particle.m_life - m_particle.m_lifeDeviation <= 0.0)
	{
		ANKI_LOGE(ERROR, "lifeDeviation");
		return ErrorCode::USER_DATA;
	}

	if(m_particle.m_size <= 0.0)
	{
		ANKI_LOGE(ERROR, "size");
		return ErrorCode::USER_DATA;
	}

	if(m_maxNumOfParticles < 1)
	{
		ANKI_LOGE(ERROR, "maxNumOfParticles");
		return ErrorCode::USER_DATA;
	}

	if(m_emissionPeriod <= 0.0)
	{
		ANKI_LOGE(ERROR, "emissionPeriod");
		return ErrorCode::USER_DATA;
	}

	if(m_particlesPerEmittion < 1)
	{
		ANKI_LOGE(ERROR, "particlesPerEmission");
		return ErrorCode::USER_DATA;
	}

	// Calc some stuff
	//
	updateFlags();

	return ErrorCode::NONE;
}
Beispiel #14
0
Test::Test(XmlElement *xe,bool &ok, ProductionUnit* unit_) :
	input (-1),
	output (-1),
	num_channels(1),
    glitchThreshold(4.0f),
	unit(unit_),
    requiredTestAdapterProductId(0) // Most tests do not require a specific product ID
{
	XmlElement *temp;

	temp = xe->getFirstChildElement();
    if (temp && temp->isTextElement())
	{
		title = temp->getText();
		title = title.trim();
	}

	if (application->testManager->getNumLoops())
	{
        int currentLoop = application->testManager->currentLoop;
		if (title.isNotEmpty())
		{
			title += String::formatted(" - loop %d/%d", currentLoop + 1, application->testManager->getNumLoops());
		}
	}

	getIntValue(xe, "input", input);
	getIntValue(xe, "output", output);
	getIntValue(xe, "num_channels", num_channels);
	ok = getIntValue(xe, "sample_rate_check", sample_rate_check);
	if (!ok)
		sample_rate_check = 0;
	ok = getIntValue(xe, "sample_rate", sample_rate);
	ok &= getFloatValue(xe, "output_amplitude_db", output_amplitude_db);

	if (sample_rate_check != 0)
	{
		minSampleRate = sample_rate_check * 0.80f;
		maxSampleRate = sample_rate_check * 1.20f;
	}
	else
	{
		minSampleRate = sample_rate * 0.94f;
		maxSampleRate = sample_rate * 1.06f;
	}
	getFloatValue(xe, "min_sample_rate", minSampleRate);
	getFloatValue(xe, "max_sample_rate", maxSampleRate);
    
    getHexValue(xe, "required_test_adapter_product_id", requiredTestAdapterProductId); // Not required
    
    if (ECHOAIO_INTERFACE_MODULE_REV1 == unit_->getAIORevision())
    {
        if (minSampleRate > 144000.0)
            minSampleRate *= 0.5f;
        if (maxSampleRate > 144000.0)
            maxSampleRate *= 0.5f;
        if (sample_rate > 144000.0)
            sample_rate *= 0.5f;
    }

	output_frequency = 1000.0f;
}
//==============================================================================
void MaterialProgramCreator::parseInputsTag(const XmlElement& programEl)
{
	XmlElement inputsEl = programEl.getChildElementOptional("inputs");
	if(!inputsEl)
	{
		return;
	}

	// Get shader type
	GLbitfield glshaderbit;
	GLenum glshader;
	U shaderidx;
	getShaderInfo(
		programEl.getChildElement("type").getText(), 
		glshader, glshaderbit, shaderidx);

	XmlElement inputEl = inputsEl.getChildElement("input");
	do
	{
		Input inpvar(m_alloc);

		// <name>
		inpvar.m_name = inputEl.getChildElement("name").getText();

		// <type>
		inpvar.m_type = inputEl.getChildElement("type").getText();

		// <value>
		XmlElement valueEl = inputEl.getChildElement("value");
		if(valueEl.getText())
		{
			inpvar.m_value = MPStringList::splitString(
				valueEl.getText(), ' ', m_alloc);
		}

		// <const>
		XmlElement constEl = inputEl.getChildElementOptional("const");
		inpvar.m_constant = (constEl) ? constEl.getInt() : false;

		// <arraySize>
		XmlElement arrSizeEl = inputEl.getChildElementOptional("arraySize");
		inpvar.m_arraySize = (arrSizeEl) ? arrSizeEl.getInt() : 0;

		// <instanced>
		if(inpvar.m_arraySize == 0)
		{
			XmlElement instancedEl = 
				inputEl.getChildElementOptional("instanced");

			inpvar.m_instanced = (instancedEl) ? instancedEl.getInt() : 0;

			// If one input var is instanced notify the whole program that 
			// it's instanced
			if(inpvar.m_instanced)
			{
				m_instanced = true;
			}
		}

		// Now you have the info to check if duplicate
		Input* duplicateInp = nullptr;
		for(Input& in : m_inputs)
		{
			if(in.m_name == inpvar.m_name)
			{
				duplicateInp = &in;
				break;
			}
		}

		if(duplicateInp != nullptr)
		{
			// Duplicate. Make sure it's the same as the other shader
			Bool same = duplicateInp->m_type == inpvar.m_type
				|| duplicateInp->m_value == inpvar.m_value
				|| duplicateInp->m_constant == inpvar.m_constant
				|| duplicateInp->m_arraySize == inpvar.m_arraySize
				|| duplicateInp->m_instanced == inpvar.m_instanced;

			if(!same)
			{
				throw ANKI_EXCEPTION("Variable defined differently between "
					"shaders: %s", &inpvar.m_name[0]);
			}

			duplicateInp->m_shaderDefinedMask |= glshaderbit;

			goto advance;
		}

		if(inpvar.m_constant == false)
		{
			// Handle NON-consts

			inpvar.m_line = inpvar.m_type + " " + inpvar.m_name;
				
			if(inpvar.m_arraySize > 1)
			{
				MPString tmp(MPString::toString(inpvar.m_arraySize, m_alloc));
				inpvar.m_line += "[" + tmp + "U]";
			}

			if(inpvar.m_instanced)
			{
				MPString tmp(
					MPString::toString(ANKI_GL_MAX_INSTANCES, m_alloc));
				inpvar.m_line += "[" +  tmp + "U]";
			}

			inpvar.m_line += ";";

			// Can put it block
			if(inpvar.m_type == "sampler2D" || inpvar.m_type == "samplerCube")
			{
				MPString tmp(
					MPString::toString(m_texBinding++, m_alloc));

				inpvar.m_line = ANKI_STRL("layout(binding = ") 
					+ tmp + ") uniform " + inpvar.m_line;
		
				inpvar.m_inBlock = false;
			}
			else
			{
				inpvar.m_inBlock = true;

				m_uniformBlock.push_back(inpvar.m_line);
				m_uniformBlockReferencedMask |= glshaderbit;
			}
		}
		else
		{
			// Handle consts

			if(inpvar.m_value.size() == 0)
			{
				throw ANKI_EXCEPTION("Empty value and const is illogical");
			}

			if(inpvar.m_arraySize > 0)
			{
				throw ANKI_EXCEPTION("Const arrays currently cannot "
					"be handled");
			}

			inpvar.m_inBlock = false;

			inpvar.m_line = ANKI_STRL("const ") 
				+ inpvar.m_type + " " + inpvar.m_name 
				+ " = " + inpvar.m_type + "(" + inpvar.m_value.join(", ") 
				+  ");";
		}

		inpvar.m_shaderDefinedMask = glshaderbit;
		m_inputs.push_back(inpvar);

advance:
		// Advance
		inputEl = inputEl.getNextSiblingElement("input");
	} while(inputEl);
}
//==============================================================================
void MaterialProgramCreator::parseProgramTag(
	const XmlElement& programEl)
{
	// <type>
	CString type = programEl.getChildElement("type"_cstr).getText();
	GLbitfield glshaderbit;
	GLenum glshader;
	U shaderidx;
	getShaderInfo(type, glshader, glshaderbit, shaderidx);

	m_source[shaderidx] = MPStringList(m_alloc);
	auto& lines = m_source[shaderidx];
	lines.push_back(ANKI_STRL("#pragma anki type "_cstr) + type);

	if(glshader == GL_TESS_CONTROL_SHADER 
		|| glshader == GL_TESS_EVALUATION_SHADER)
	{
		m_tessellation = true;
	}

	// <includes></includes>
	XmlElement includesEl = programEl.getChildElement("includes"_cstr);
	XmlElement includeEl = includesEl.getChildElement("include"_cstr);

	do
	{
		MPString fname(includeEl.getText(), m_alloc);
		lines.push_back(
			ANKI_STRL("#pragma anki include \""_cstr) + fname + "\""_cstr);

		includeEl = includeEl.getNextSiblingElement("include"_cstr);
	} while(includeEl);

	// Inputs

	// Block
	if(m_uniformBlock.size() > 0 
		&& (m_uniformBlockReferencedMask | glshaderbit))
	{
		// TODO Make block SSB when driver bug is fixed
		lines.push_back(ANKI_STRL(
			"\nlayout(binding = 0, std140) uniform bDefaultBlock\n{"_cstr));

		lines.insert(
			lines.end(), m_uniformBlock.begin(), m_uniformBlock.end());

		lines.push_back(ANKI_STRL("};"));
	}

	// Other variables
	for(Input& in : m_inputs)
	{
		if(!in.m_inBlock && (in.m_shaderDefinedMask | glshaderbit))
		{
			lines.push_back(in.m_line);
		}
	}

	// <operations></operations>
	lines.push_back(ANKI_STRL("\nvoid main()\n{"));

	XmlElement opsEl = programEl.getChildElement("operations");
	XmlElement opEl = opsEl.getChildElement("operation");
	do
	{
		MPString out(m_alloc);
		parseOperationTag(opEl, glshader, glshaderbit, out);
		lines.push_back(out);

		// Advance
		opEl = opEl.getNextSiblingElement("operation");
	} while(opEl);

	lines.push_back(ANKI_STRL("}\n"));
}
Beispiel #17
0
//==============================================================================
Error Animation::load(const ResourceFilename& filename)
{
	XmlElement el;
	I64 tmp;
	F64 ftmp;

	m_startTime = MAX_F32;
	F32 maxTime = MIN_F32;

	// Document
	XmlDocument doc;
	ANKI_CHECK(openFileParseXml(filename, doc));
	XmlElement rootel;
	ANKI_CHECK(doc.getChildElement("animation", rootel));

	// Count the number of identity keys. If all of the keys are identities
	// drop a vector
	U identPosCount = 0;
	U identRotCount = 0;
	U identScaleCount = 0;

	// <repeat>
	XmlElement repel;
	ANKI_CHECK(rootel.getChildElementOptional("repeat", repel));
	if(repel)
	{
		ANKI_CHECK(repel.getI64(tmp));
		m_repeat = tmp;
	}
	else
	{
		m_repeat = false;
	}

	// <channels>
	XmlElement channelsEl;
	ANKI_CHECK(rootel.getChildElement("channels", channelsEl));
	XmlElement chEl;
	ANKI_CHECK(channelsEl.getChildElement("channel", chEl));

	U32 channelCount = 0;
	ANKI_CHECK(chEl.getSiblingElementsCount(channelCount));
	if(channelCount == 0)
	{
		ANKI_LOGE("Didn't found any channels");
		return ErrorCode::USER_DATA;
	}
	m_channels.create(getAllocator(), channelCount);

	// For all channels
	channelCount = 0;
	do
	{
		AnimationChannel& ch = m_channels[channelCount];

		// <name>
		ANKI_CHECK(chEl.getChildElement("name", el));
		CString strtmp;
		ANKI_CHECK(el.getText(strtmp));
		ch.m_name.create(getAllocator(), strtmp);

		XmlElement keysEl, keyEl;

		// <positionKeys>
		ANKI_CHECK(chEl.getChildElementOptional("positionKeys", keysEl));
		if(keysEl)
		{
			ANKI_CHECK(keysEl.getChildElement("key", keyEl));

			U32 count = 0;
			ANKI_CHECK(keyEl.getSiblingElementsCount(count));
			ch.m_positions.create(getAllocator(), count);

			count = 0;
			do
			{
				Key<Vec3>& key = ch.m_positions[count++];

				// <time>
				ANKI_CHECK(keyEl.getChildElement("time", el));
				ANKI_CHECK(el.getF64(ftmp));
				key.m_time = ftmp;
				m_startTime = std::min(m_startTime, key.m_time);
				maxTime = std::max(maxTime, key.m_time);

				// <value>
				ANKI_CHECK(keyEl.getChildElement("value", el));
				ANKI_CHECK(el.getVec3(key.m_value));

				// Check ident
				if(key.m_value == Vec3(0.0))
				{
					++identPosCount;
				}

				// Move to next
				ANKI_CHECK(keyEl.getNextSiblingElement("key", keyEl));
			} while(keyEl);
		}

		// <rotationKeys>
		ANKI_CHECK(chEl.getChildElement("rotationKeys", keysEl));
		if(keysEl)
		{
			ANKI_CHECK(keysEl.getChildElement("key", keyEl));

			U32 count = 0;
			ANKI_CHECK(keysEl.getSiblingElementsCount(count));
			ch.m_rotations.create(getAllocator(), count);

			count = 0;
			do
			{
				Key<Quat>& key = ch.m_rotations[count++];

				// <time>
				ANKI_CHECK(keyEl.getChildElement("time", el));
				ANKI_CHECK(el.getF64(ftmp));
				key.m_time = ftmp;
				m_startTime = std::min(m_startTime, key.m_time);
				maxTime = std::max(maxTime, key.m_time);

				// <value>
				Vec4 tmp2;
				ANKI_CHECK(keyEl.getChildElement("value", el));
				ANKI_CHECK(el.getVec4(tmp2));
				key.m_value = Quat(tmp2);

				// Check ident
				if(key.m_value == Quat::getIdentity())
				{
					++identRotCount;
				}

				// Move to next
				ANKI_CHECK(keyEl.getNextSiblingElement("key", keyEl));
			} while(keyEl);
		}

		// <scalingKeys>
		ANKI_CHECK(chEl.getChildElementOptional("scalingKeys", keysEl));
		if(keysEl)
		{
			ANKI_CHECK(keysEl.getChildElement("key", keyEl));

			U32 count = 0;
			ANKI_CHECK(keyEl.getSiblingElementsCount(count));
			ch.m_scales.create(getAllocator(), count);

			count = 0;
			do
			{
				Key<F32>& key = ch.m_scales[count++];

				// <time>
				ANKI_CHECK(keyEl.getChildElement("time", el));
				ANKI_CHECK(el.getF64(ftmp));
				key.m_time = ftmp;
				m_startTime = std::min(m_startTime, key.m_time);
				maxTime = std::max(maxTime, key.m_time);

				// <value>
				ANKI_CHECK(keyEl.getChildElement("value", el));
				ANKI_CHECK(el.getF64(ftmp));
				key.m_value = ftmp;

				// Check ident
				if(isZero(key.m_value - 1.0))
				{
					++identScaleCount;
				}

				// Move to next
				ANKI_CHECK(keyEl.getNextSiblingElement("key", keyEl));
			} while(keyEl);
		}

		// Remove identity vectors
		if(identPosCount == ch.m_positions.getSize())
		{
			ch.m_positions.destroy(getAllocator());
		}

		if(identRotCount == ch.m_rotations.getSize())
		{
			ch.m_rotations.destroy(getAllocator());
		}

		if(identScaleCount == ch.m_scales.getSize())
		{
			ch.m_scales.destroy(getAllocator());
		}

		// Move to next channel
		++channelCount;
		ANKI_CHECK(chEl.getNextSiblingElement("channel", chEl));
	} while(chEl);

	m_duration = maxTime - m_startTime;

	return ErrorCode::NONE;
}