// ------------------------------------------------------------------------------------------------
// read an array of uints
void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el)
{
    out.resize( 0 );
    const TokenList& tok = el.Tokens();
    if(tok.empty()) {
        ParseError("unexpected empty element",&el);
    }

    if(tok[0]->IsBinary()) {
        const char* data = tok[0]->begin(), *end = tok[0]->end();

        char type;
        uint32_t count;
        ReadBinaryDataArrayHead(data, end, type, count, el);

        if(!count) {
            return;
        }

        if (type != 'i') {
            ParseError("expected (u)int array (binary)",&el);
        }

        std::vector<char> buff;
        ReadBinaryDataArray(type, count, data, end, buff, el);

        ai_assert(data == end);
        ai_assert(buff.size() == count * 4);

        out.reserve(count);

        const int32_t* ip = reinterpret_cast<const int32_t*>(&buff[0]);
        for (unsigned int i = 0; i < count; ++i, ++ip) {
            BE_NCONST int32_t val = *ip;
            if(val < 0) {
                ParseError("encountered negative integer index (binary)");
            }

            AI_SWAP4(val);
            out.push_back(val);
        }

        return;
    }

    const size_t dim = ParseTokenAsDim(*tok[0]);

    // see notes in ParseVectorDataArray()
    out.reserve(dim);

    const Scope& scope = GetRequiredScope(el);
    const Element& a = GetRequiredElement(scope,"a",&el);

    for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
        const int ival = ParseTokenAsInt(**it++);
        if(ival < 0) {
            ParseError("encountered negative integer index");
        }
        out.push_back(static_cast<unsigned int>(ival));
    }
}
// ------------------------------------------------------------------------------------------------
// read an array of float3 tuples
void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
{
    out.resize( 0 );

    const TokenList& tok = el.Tokens();
    if(tok.empty()) {
        ParseError("unexpected empty element",&el);
    }

    if(tok[0]->IsBinary()) {
        const char* data = tok[0]->begin(), *end = tok[0]->end();

        char type;
        uint32_t count;
        ReadBinaryDataArrayHead(data, end, type, count, el);

        if(count % 3 != 0) {
            ParseError("number of floats is not a multiple of three (3) (binary)",&el);
        }

        if(!count) {
            return;
        }

        if (type != 'd' && type != 'f') {
            ParseError("expected float or double array (binary)",&el);
        }

        std::vector<char> buff;
        ReadBinaryDataArray(type, count, data, end, buff, el);

        ai_assert(data == end);
        ai_assert(buff.size() == count * (type == 'd' ? 8 : 4));

        const uint32_t count3 = count / 3;
        out.reserve(count3);

        if (type == 'd') {
            const double* d = reinterpret_cast<const double*>(&buff[0]);
            for (unsigned int i = 0; i < count3; ++i, d += 3) {
                out.push_back(aiVector3D(static_cast<float>(d[0]),
                    static_cast<float>(d[1]),
                    static_cast<float>(d[2])));
            }
            // for debugging
            /*for ( size_t i = 0; i < out.size(); i++ ) {
                aiVector3D vec3( out[ i ] );
                std::stringstream stream;
                stream << " vec3.x = " << vec3.x << " vec3.y = " << vec3.y << " vec3.z = " << vec3.z << std::endl;
                DefaultLogger::get()->info( stream.str() );
            }*/
        }
        else if (type == 'f') {
            const float* f = reinterpret_cast<const float*>(&buff[0]);
            for (unsigned int i = 0; i < count3; ++i, f += 3) {
                out.push_back(aiVector3D(f[0],f[1],f[2]));
            }
        }

        return;
    }

    const size_t dim = ParseTokenAsDim(*tok[0]);

    // may throw bad_alloc if the input is rubbish, but this need
    // not to be prevented - importing would fail but we wouldn't
    // crash since assimp handles this case properly.
    out.reserve(dim);

    const Scope& scope = GetRequiredScope(el);
    const Element& a = GetRequiredElement(scope,"a",&el);

    if (a.Tokens().size() % 3 != 0) {
        ParseError("number of floats is not a multiple of three (3)",&el);
    }
    for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
        aiVector3D v;
        v.x = ParseTokenAsFloat(**it++);
        v.y = ParseTokenAsFloat(**it++);
        v.z = ParseTokenAsFloat(**it++);

        out.push_back(v);
    }
}
// ------------------------------------------------------------------------------------------------
// read an array of float2 tuples
void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el)
{
    out.resize( 0 );
    const TokenList& tok = el.Tokens();
    if(tok.empty()) {
        ParseError("unexpected empty element",&el);
    }

    if(tok[0]->IsBinary()) {
        const char* data = tok[0]->begin(), *end = tok[0]->end();

        char type;
        uint32_t count;
        ReadBinaryDataArrayHead(data, end, type, count, el);

        if(count % 2 != 0) {
            ParseError("number of floats is not a multiple of two (2) (binary)",&el);
        }

        if(!count) {
            return;
        }

        if (type != 'd' && type != 'f') {
            ParseError("expected float or double array (binary)",&el);
        }

        std::vector<char> buff;
        ReadBinaryDataArray(type, count, data, end, buff, el);

        ai_assert(data == end);
        ai_assert(buff.size() == count * (type == 'd' ? 8 : 4));

        const uint32_t count2 = count / 2;
        out.reserve(count2);

        if (type == 'd') {
            const double* d = reinterpret_cast<const double*>(&buff[0]);
            for (unsigned int i = 0; i < count2; ++i, d += 2) {
                out.push_back(aiVector2D(static_cast<float>(d[0]),
                    static_cast<float>(d[1])));
            }
        }
        else if (type == 'f') {
            const float* f = reinterpret_cast<const float*>(&buff[0]);
            for (unsigned int i = 0; i < count2; ++i, f += 2) {
                out.push_back(aiVector2D(f[0],f[1]));
            }
        }

        return;
    }

    const size_t dim = ParseTokenAsDim(*tok[0]);

    // see notes in ParseVectorDataArray() above
    out.reserve(dim);

    const Scope& scope = GetRequiredScope(el);
    const Element& a = GetRequiredElement(scope,"a",&el);

    if (a.Tokens().size() % 2 != 0) {
        ParseError("number of floats is not a multiple of two (2)",&el);
    }
    for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
        aiVector2D v;
        v.x = ParseTokenAsFloat(**it++);
        v.y = ParseTokenAsFloat(**it++);

        out.push_back(v);
    }
}
Exemple #4
0
// ------------------------------------------------------------------------------------------------
void Tokenize(TokenList& output_tokens, const char* input)
{
    ai_assert(input);

    // line and column numbers numbers are one-based
    unsigned int line = 1;
    unsigned int column = 1;

    bool comment = false;
    bool in_double_quotes = false;
    bool pending_data_token = false;

    const char* token_begin = NULL, *token_end = NULL;
    for (const char* cur = input;*cur;column += (*cur == '\t' ? ASSIMP_FBX_TAB_WIDTH : 1), ++cur) {
        const char c = *cur;

        if (IsLineEnd(c)) {
            comment = false;

            column = 0;
            ++line;
        }

        if(comment) {
            continue;
        }

        if(in_double_quotes) {
            if (c == '\"') {
                in_double_quotes = false;
                token_end = cur;

                ProcessDataToken(output_tokens,token_begin,token_end,line,column);
                pending_data_token = false;
            }
            continue;
        }

        switch(c)
        {
        case '\"':
            if (token_begin) {
                TokenizeError("unexpected double-quote", line, column);
            }
            token_begin = cur;
            in_double_quotes = true;
            continue;

        case ';':
            ProcessDataToken(output_tokens,token_begin,token_end,line,column);
            comment = true;
            continue;

        case '{':
            ProcessDataToken(output_tokens,token_begin,token_end, line, column);
            output_tokens.push_back(new_Token(cur,cur+1,TokenType_OPEN_BRACKET,line,column));
            continue;

        case '}':
            ProcessDataToken(output_tokens,token_begin,token_end,line,column);
            output_tokens.push_back(new_Token(cur,cur+1,TokenType_CLOSE_BRACKET,line,column));
            continue;

        case ',':
            if (pending_data_token) {
                ProcessDataToken(output_tokens,token_begin,token_end,line,column,TokenType_DATA,true);
            }
            output_tokens.push_back(new_Token(cur,cur+1,TokenType_COMMA,line,column));
            continue;

        case ':':
            if (pending_data_token) {
                ProcessDataToken(output_tokens,token_begin,token_end,line,column,TokenType_KEY,true);
            }
            else {
                TokenizeError("unexpected colon", line, column);
            }
            continue;
        }

        if (IsSpaceOrNewLine(c)) {

            if (token_begin) {
                // peek ahead and check if the next token is a colon in which
                // case this counts as KEY token.
                TokenType type = TokenType_DATA;
                for (const char* peek = cur;  *peek && IsSpaceOrNewLine(*peek); ++peek) {
                    if (*peek == ':') {
                        type = TokenType_KEY;
                        cur = peek;
                        break;
                    }
                }

                ProcessDataToken(output_tokens,token_begin,token_end,line,column,type);
            }

            pending_data_token = false;
        }
        else {
            token_end = cur;
            if (!token_begin) {
                token_begin = cur;
            }

            pending_data_token = true;
        }
    }
}
Exemple #5
0
// -------------------------------------------------------------------------------
aiMesh* MakeSubmesh(const aiMesh *pMesh, const std::vector<unsigned int> &subMeshFaces, unsigned int subFlags)
{		
	aiMesh *oMesh = new aiMesh(); 
	std::vector<unsigned int> vMap(pMesh->mNumVertices,UINT_MAX);

	size_t numSubVerts = 0; 
	size_t numSubFaces = subMeshFaces.size();

	for(unsigned int i=0;i<numSubFaces;i++)	{
		const aiFace &f = pMesh->mFaces[subMeshFaces[i]];

		for(unsigned int j=0;j<f.mNumIndices;j++)	{
			if(vMap[f.mIndices[j]]==UINT_MAX)	{
				vMap[f.mIndices[j]] = numSubVerts++;
			}
		}		
	} 

	oMesh->mName = pMesh->mName;
		
	oMesh->mMaterialIndex = pMesh->mMaterialIndex;
	oMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes;
	
	// create all the arrays for this mesh if the old mesh contained them
		
	oMesh->mNumFaces = subMeshFaces.size();
	oMesh->mNumVertices = numSubVerts;
	oMesh->mVertices = new aiVector3D[numSubVerts];
	if( pMesh->HasNormals() ) {
		oMesh->mNormals = new aiVector3D[numSubVerts];
	}

	if( pMesh->HasTangentsAndBitangents() )	{
		oMesh->mTangents = new aiVector3D[numSubVerts];
		oMesh->mBitangents = new aiVector3D[numSubVerts];
	}

	for( size_t a = 0;  pMesh->HasTextureCoords( a) ; ++a )	{
		oMesh->mTextureCoords[a] = new aiVector3D[numSubVerts];
		oMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a];
	}

	for( size_t a = 0; pMesh->HasVertexColors( a); ++a )	{
		oMesh->mColors[a] = new aiColor4D[numSubVerts];
	}

	// and copy over the data, generating faces with linear indices along the way
	oMesh->mFaces = new aiFace[numSubFaces];
	
	for(unsigned int a = 0; a < numSubFaces; ++a )	{

		const aiFace& srcFace = pMesh->mFaces[subMeshFaces[a]];
		aiFace& dstFace = oMesh->mFaces[a];
		dstFace.mNumIndices = srcFace.mNumIndices;
		dstFace.mIndices = new unsigned int[dstFace.mNumIndices];

		// accumulate linearly all the vertices of the source face
		for( size_t b = 0; b < dstFace.mNumIndices; ++b )	{
			dstFace.mIndices[b] = vMap[srcFace.mIndices[b]];
		}
	}

	for(unsigned int srcIndex = 0; srcIndex < pMesh->mNumVertices; ++srcIndex ) {
		unsigned int nvi = vMap[srcIndex]; 
		if(nvi==UINT_MAX) {
			continue;
		}

		oMesh->mVertices[nvi] = pMesh->mVertices[srcIndex];
		if( pMesh->HasNormals() ) {
			oMesh->mNormals[nvi] = pMesh->mNormals[srcIndex];
		}
		
		if( pMesh->HasTangentsAndBitangents() )	{
			oMesh->mTangents[nvi] = pMesh->mTangents[srcIndex];
			oMesh->mBitangents[nvi] = pMesh->mBitangents[srcIndex];
		}
		for( size_t c = 0, cc = pMesh->GetNumUVChannels(); c < cc; ++c )	{
				oMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex];
		}
		for( size_t c = 0, cc = pMesh->GetNumColorChannels(); c < cc; ++c )	{
			oMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex];
		}
	}

	if(~subFlags&AI_SUBMESH_FLAGS_SANS_BONES)	{			
		std::vector<unsigned int> subBones(pMesh->mNumBones,0);

		for(unsigned int a=0;a<pMesh->mNumBones;++a)	{
			const aiBone* bone = pMesh->mBones[a];

			for(unsigned int b=0;b<bone->mNumWeights;b++)	{
				unsigned int v = vMap[bone->mWeights[b].mVertexId];

				if(v!=UINT_MAX) {
					subBones[a]++;
				}
			}
		}

		for(unsigned int a=0;a<pMesh->mNumBones;++a)	{
			if(subBones[a]>0) {
				oMesh->mNumBones++;
			}
		}

		if(oMesh->mNumBones) {
			oMesh->mBones = new aiBone*[oMesh->mNumBones]();
			unsigned int nbParanoia = oMesh->mNumBones;

			oMesh->mNumBones = 0; //rewind

			for(unsigned int a=0;a<pMesh->mNumBones;++a)	{
				if(subBones[a]==0) {
					continue; 
				}
				aiBone *newBone = new aiBone;
				oMesh->mBones[oMesh->mNumBones++] = newBone;

				const aiBone* bone = pMesh->mBones[a];

				newBone->mName = bone->mName;
				newBone->mOffsetMatrix = bone->mOffsetMatrix;
				newBone->mWeights = new aiVertexWeight[subBones[a]];

				for(unsigned int b=0;b<bone->mNumWeights;b++)	{
					const unsigned int v = vMap[bone->mWeights[b].mVertexId];

					if(v!=UINT_MAX)	{	
						aiVertexWeight w(v,bone->mWeights[b].mWeight);
						newBone->mWeights[newBone->mNumWeights++] = w;
					}
				}
			}

			ai_assert(nbParanoia==oMesh->mNumBones);
			(void)nbParanoia; // remove compiler warning on release build
		}
	}					 

	return oMesh;
}
Exemple #6
0
// ------------------------------------------------------------------------------------------------
void M3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler )
{
	ai_assert( !pFile.empty() );

	const std::string mode = "rb";
	boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode ) );
	if ( NULL == file.get() ) {
		throw DeadlyImportError( "Failed to open file " + pFile + ".");
	}

	// Get the file-size and validate it, throwing an exception when it fails
	const size_t filesize = file->FileSize();
	if( filesize  < 1 ) {
		throw DeadlyImportError( "M3-file is too small.");
	}

	m_Buffer.resize( filesize );
	file->Read( &m_Buffer[ 0 ], sizeof( unsigned char ), filesize );

	m_pHead = reinterpret_cast<MD33*>( &m_Buffer[ 0 ] );
	m_pRefs = reinterpret_cast<ReferenceEntry*>( &m_Buffer[ 0 ] + m_pHead->ofsRefs );

	MODL20* pMODL20( NULL );
	MODL23* pMODL23( NULL );

	VertexExt* pVerts1( NULL );
	Vertex* pVerts2( NULL );

	DIV *pViews( NULL );
	Region* regions( NULL );
	uint16* faces( NULL );

	uint32 nVertices = 0;

	bool ok = true;
	switch( m_pRefs[ m_pHead->MODL.ref ].type )	{
	case 20:
		pMODL20 = GetEntries<MODL20>( m_pHead->MODL );
		if ( ( pMODL20->flags & 0x20000) != 0 ) { // Has vertices
			if( (pMODL20->flags & 0x40000) != 0 ) { // Has extra 4 byte
				pVerts1 = GetEntries<VertexExt>( pMODL20->vertexData );
				nVertices = pMODL20->vertexData.nEntries/sizeof(VertexExt);
			}
			else {
				pVerts2 = GetEntries<Vertex>( pMODL20->vertexData );
				nVertices = pMODL20->vertexData.nEntries / sizeof( Vertex );
			}
		}
		pViews = GetEntries<DIV>( pMODL20->views );
		break;

	case 23:
		pMODL23 = GetEntries<MODL23>(m_pHead->MODL );
		if( (pMODL23->flags & 0x20000) != 0 ) { // Has vertices
			if( (pMODL23->flags & 0x40000) != 0 ) { // Has extra 4 byte
				pVerts1 = GetEntries<VertexExt>( pMODL23->vertexData );
				nVertices = pMODL23->vertexData.nEntries/sizeof( VertexExt );
			}
			else {
				pVerts2 = GetEntries<Vertex>( pMODL23->vertexData );
				nVertices = pMODL23->vertexData.nEntries/sizeof( Vertex );
			}
		}
		pViews = GetEntries<DIV>( pMODL23->views );
		break;

	default:
		ok = false;
		break;
	}
	
	// Everything ok, if not throw an exception
	if ( !ok ) {
		throw DeadlyImportError( "Failed to open file " + pFile + ".");
	}

	// Get all region data
	regions = GetEntries<Region>( pViews->regions );
	
	// Get the face data
	faces = GetEntries<uint16>( pViews->faces );

	// Convert the vertices
	std::vector<aiVector3D> vertices;
	vertices.resize( nVertices );
	unsigned int offset = 0;
	for ( unsigned int i = 0; i < nVertices; i++ ) {
		if ( pVerts1 ) {
			vertices[ offset ].Set( pVerts1[ i ].pos.x, pVerts1[ i ].pos.y, pVerts1[ i ].pos.z );
			++offset;
		}

		if ( pVerts2 ) {
			vertices[ offset ].Set( pVerts2[ i ].pos.x, pVerts2[ i ].pos.y, pVerts2[ i ].pos.z );
			++offset;
		}
	}

	// Write the UV coordinates
	offset = 0;
	std::vector<aiVector3D> uvCoords;
	uvCoords.resize( nVertices );
	for( unsigned int i = 0; i < nVertices; ++i ) {
		if( pVerts1 ) {
			float u = (float) pVerts1[ i ].uv[ 0 ] / 2048;
			float v = (float) pVerts1[ i ].uv[ 1 ] / 2048;
			uvCoords[ offset ].Set( u, v, 0.0f );
			++offset;
		}

		if( pVerts2 ) {
			float u = (float) pVerts2[ i ].uv[ 0 ] / 2048;
			float v = (float) pVerts2[ i ].uv[ 1 ] / 2048;
			uvCoords[ offset ].Set( u, v, 0.0f );
			++offset;
		}
	}

	// Compute the normals  
	std::vector<aiVector3D> normals;
	normals.resize( nVertices );
	float w = 0.0f;
	Vec3D norm;
	offset = 0;
	for( unsigned int i = 0; i < nVertices; i++ ) {
		w = 0.0f;
		if( pVerts1 ) {
			norm.x = (float) 2*pVerts1[ i ].normal[ 0 ]/255.0f - 1;
			norm.y = (float) 2*pVerts1[ i ].normal[ 1 ]/255.0f - 1;
			norm.z = (float) 2*pVerts1[ i ].normal[ 2 ]/255.0f - 1;
			w = (float) pVerts1[ i ].normal[ 3 ]/255.0f;
		}

		if( pVerts2 ) {
			norm.x = (float) 2*pVerts2[ i ].normal[ 0 ]/255.0f - 1;
			norm.y = (float) 2*pVerts2[ i ].normal[ 1 ]/255.0f - 1;
			norm.z = (float) 2*pVerts2[ i ].normal[ 2 ]/255.0f - 1;
			w = (float) pVerts2[ i ].normal[ 3 ] / 255.0f;
		}

		if ( w ) {
			const float invW = 1.0f / w;
			norm.x = norm.x * invW;
			norm.y = norm.y * invW;
			norm.z = norm.z * invW;
			normals[ offset ].Set( norm.x, norm.y, norm.z );
			++offset;
		}
	}

	// Convert the data into the assimp specific data structures
	convertToAssimp( pFile, pScene, pViews, regions, faces, vertices, uvCoords, normals );
}
// ------------------------------------------------------------------------------------------------
void ReadData(const char*& sbegin_out, const char*& send_out, const char* input, const char*& cursor, const char* end)
{
    if(Offset(cursor, end) < 1) {
        TokenizeError("cannot ReadData, out of bounds reading length",input, cursor);
    }

    const char type = *cursor;
    sbegin_out = cursor++;

    switch(type)
    {
        // 16 bit int
    case 'Y':
        cursor += 2;
        break;

        // 1 bit bool flag (yes/no)
    case 'C':
        cursor += 1;
        break;

        // 32 bit int
    case 'I':
        // <- fall through

        // float
    case 'F':
        cursor += 4;
        break;

        // double
    case 'D':
        cursor += 8;
        break;

        // 64 bit int
    case 'L':
        cursor += 8;
        break;

        // note: do not write cursor += ReadWord(...cursor) as this would be UB

        // raw binary data
    case 'R':
    {
        const uint32_t length = ReadWord(input, cursor, end);
        cursor += length;
        break;
    }

    case 'b':
        // TODO: what is the 'b' type code? Right now we just skip over it /
        // take the full range we could get
        cursor = end;
        break;

        // array of *
    case 'f':
    case 'd':
    case 'l':
    case 'i':   {

        const uint32_t length = ReadWord(input, cursor, end);
        const uint32_t encoding = ReadWord(input, cursor, end);

        const uint32_t comp_len = ReadWord(input, cursor, end);

        // compute length based on type and check against the stored value
        if(encoding == 0) {
            uint32_t stride = 0;
            switch(type)
            {
            case 'f':
            case 'i':
                stride = 4;
                break;

            case 'd':
            case 'l':
                stride = 8;
                break;

            default:
                ai_assert(false);
            };
            ai_assert(stride > 0);
            if(length * stride != comp_len) {
                TokenizeError("cannot ReadData, calculated data stride differs from what the file claims",input, cursor);
            }
        }
        // zip/deflate algorithm (encoding==1)? take given length. anything else? die
        else if (encoding != 1) {
            TokenizeError("cannot ReadData, unknown encoding",input, cursor);
        }
        cursor += comp_len;
        break;
    }

        // string
    case 'S': {
        const char* sb, *se;
        // 0 characters can legally happen in such strings
        ReadString(sb, se, input, cursor, end, true, true);
        break;
    }
    default:
        TokenizeError("cannot ReadData, unexpected type code: " + std::string(&type, 1),input, cursor);
    }

    if(cursor > end) {
        TokenizeError("cannot ReadData, the remaining size is too small for the data type: " + std::string(&type, 1),input, cursor);
    }

    // the type code is contained in the returned range
    send_out = cursor;
}
// ------------------------------------------------------------------------------------------------
//	Close a filestream.
void Q3BSPZipArchive::Close(IOStream *pFile) {
	ai_assert(pFile != NULL);

	// We don't do anything in case the file would be opened again in the future
}
Exemple #9
0
// ------------------------------------------------------------------------------------------------
void TempMesh::RemoveAdjacentDuplicates() 
{

	bool drop = false;
	std::vector<IfcVector3>::iterator base = verts.begin();
	BOOST_FOREACH(unsigned int& cnt, vertcnt) {
		if (cnt < 2){
			base += cnt;
			continue;
		}

		IfcVector3 vmin,vmax;
		ArrayBounds(&*base, cnt ,vmin,vmax);


		const IfcFloat epsilon = (vmax-vmin).SquareLength() / static_cast<IfcFloat>(1e9);
		//const IfcFloat dotepsilon = 1e-9;

		//// look for vertices that lie directly on the line between their predecessor and their 
		//// successor and replace them with either of them.

		//for(size_t i = 0; i < cnt; ++i) {
		//	IfcVector3& v1 = *(base+i), &v0 = *(base+(i?i-1:cnt-1)), &v2 = *(base+(i+1)%cnt);
		//	const IfcVector3& d0 = (v1-v0), &d1 = (v2-v1);
		//	const IfcFloat l0 = d0.SquareLength(), l1 = d1.SquareLength();
		//	if (!l0 || !l1) {
		//		continue;
		//	}

		//	const IfcFloat d = (d0/sqrt(l0))*(d1/sqrt(l1));

		//	if ( d >= 1.f-dotepsilon ) {
		//		v1 = v0;
		//	}
		//	else if ( d < -1.f+dotepsilon ) {
		//		v2 = v1;
		//		continue;
		//	}
		//}

		// drop any identical, adjacent vertices. this pass will collect the dropouts
		// of the previous pass as a side-effect.
		FuzzyVectorCompare fz(epsilon);
		std::vector<IfcVector3>::iterator end = base+cnt, e = std::unique( base, end, fz );
		if (e != end) {
			cnt -= static_cast<unsigned int>(std::distance(e, end));
			verts.erase(e,end);
			drop  = true;
		}

		// check front and back vertices for this polygon
		if (cnt > 1 && fz(*base,*(base+cnt-1))) {
			verts.erase(base+ --cnt);
			drop  = true;
		}

		// removing adjacent duplicates shouldn't erase everything :-)
		ai_assert(cnt>0);
		base += cnt;
	}
	if(drop) {
		IFCImporter::LogDebug("removing duplicate vertices");
	}
}
Exemple #10
0
//! Hax function... not mine.
int ModelImporter::FindValidPath(aiString* p_szString)
{
	ai_assert(NULL != p_szString);
	aiString pcpy = *p_szString;
	if ('*' ==  p_szString->data[0])	{
		// '*' as first character indicates an embedded file
		return 5;
	}

	// first check whether we can directly load the file
	FILE* pFile = fopen(p_szString->data,"rb");
	if (pFile)fclose(pFile);
	else
	{
		// check whether we can use the directory of  the asset as relative base
		char szTemp[MAX_PATH*2], tmp2[MAX_PATH*2];
		strcpy(szTemp, mFilename.c_str());
		strcpy(tmp2,szTemp);

		char* szData = p_szString->data;
		if (*szData == '\\' || *szData == '/')++szData;

		char* szEnd = strrchr(szTemp,'\\');
		if (!szEnd)
		{
			szEnd = strrchr(szTemp,'/');
			if (!szEnd)szEnd = szTemp;
		}
		szEnd++;
		*szEnd = 0;
		strcat(szEnd,szData);


		pFile = fopen(szTemp,"rb");
		if (!pFile)
		{
			// convert the string to lower case
			for (unsigned int i = 0;;++i)
			{
				if ('\0' == szTemp[i])break;
				szTemp[i] = (char)tolower(szTemp[i]);
			}

			if(TryLongerPath(szTemp,p_szString))return 1;
			*szEnd = 0;

			// search common sub directories
			strcat(szEnd,"tex\\");
			strcat(szEnd,szData);

			pFile = fopen(szTemp,"rb");
			if (!pFile)
			{
				if(TryLongerPath(szTemp,p_szString))return 1;

				*szEnd = 0;

				strcat(szEnd,"textures\\");
				strcat(szEnd,szData);

				pFile = fopen(szTemp,"rb");
				if (!pFile)
				{
					if(TryLongerPath(szTemp, p_szString))return 1;
				}

				// patch by mark sibly to look for textures files in the asset's base directory.
				const char *path=pcpy.data; 
				const char *p=strrchr( path,'/' ); 
				if( !p ) p=strrchr( path,'\\' ); 
				if( p ){ 
					char *q=strrchr( tmp2,'/' ); 
					if( !q ) q=strrchr( tmp2,'\\' ); 
					if( q ){ 
						strcpy( q+1,p+1 ); 
						if(pFile=fopen( tmp2,"r" ) ){ 
							fclose( pFile ); 
							strcpy(p_szString->data,tmp2);
							p_szString->length = strlen(tmp2);
							return 1;
						} 
					} 
				}
				return 0;
			}
		}
		fclose(pFile);

		// copy the result string back to the aiString
		const size_t iLen = strlen(szTemp);
		size_t iLen2 = iLen+1;
		iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
		memcpy(p_szString->data,szTemp,iLen2);
		p_szString->length = iLen;

	}
	return 1;
}
// ------------------------------------------------------------------------------------------------
ZipFile::ZipFile(size_t size) : m_Size(size) {
	ai_assert(m_Size != 0);

	m_Buffer = malloc(m_Size);
}
Exemple #12
0
//-------------------------------------------------------------------------------
int CMaterialManager::CreateMaterial(
	AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource)
{
	ai_assert(NULL != pcMesh);
	ai_assert(NULL != pcSource);

	ID3DXBuffer* piBuffer;

	D3DXMACRO sMacro[64];

	// extract all properties from the ASSIMP material structure
	const aiMaterial* pcMat = g_pcAsset->pcScene->mMaterials[pcSource->mMaterialIndex];

	//
	// DIFFUSE COLOR --------------------------------------------------
	//
	if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_DIFFUSE,
		(aiColor4D*)&pcMesh->vDiffuseColor))
	{
		pcMesh->vDiffuseColor.x = 1.0f;
		pcMesh->vDiffuseColor.y = 1.0f;
		pcMesh->vDiffuseColor.z = 1.0f;
		pcMesh->vDiffuseColor.w = 1.0f;
	}
	//
	// SPECULAR COLOR --------------------------------------------------
	//
	if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_SPECULAR,
		(aiColor4D*)&pcMesh->vSpecularColor))
	{
		pcMesh->vSpecularColor.x = 1.0f;
		pcMesh->vSpecularColor.y = 1.0f;
		pcMesh->vSpecularColor.z = 1.0f;
		pcMesh->vSpecularColor.w = 1.0f;
	}
	//
	// AMBIENT COLOR --------------------------------------------------
	//
	if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_AMBIENT,
		(aiColor4D*)&pcMesh->vAmbientColor))
	{
		pcMesh->vAmbientColor.x = 0.0f;
		pcMesh->vAmbientColor.y = 0.0f;
		pcMesh->vAmbientColor.z = 0.0f;
		pcMesh->vAmbientColor.w = 1.0f;
	}
	//
	// EMISSIVE COLOR -------------------------------------------------
	//
	if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_EMISSIVE,
		(aiColor4D*)&pcMesh->vEmissiveColor))
	{
		pcMesh->vEmissiveColor.x = 0.0f;
		pcMesh->vEmissiveColor.y = 0.0f;
		pcMesh->vEmissiveColor.z = 0.0f;
		pcMesh->vEmissiveColor.w = 1.0f;
	}

	//
	// Opacity --------------------------------------------------------
	//
	if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_OPACITY,&pcMesh->fOpacity))
	{
		pcMesh->fOpacity = 1.0f;
	}

	//
	// Shading Model --------------------------------------------------
	//
	bool bDefault = false;
	if(AI_SUCCESS != aiGetMaterialInteger(pcMat,AI_MATKEY_SHADING_MODEL,(int*)&pcMesh->eShadingMode ))
	{
		bDefault = true;
		pcMesh->eShadingMode = aiShadingMode_Gouraud;
	}


	//
	// Shininess ------------------------------------------------------
	//
	if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_SHININESS,&pcMesh->fShininess))
	{
		// assume 15 as default shininess
		pcMesh->fShininess = 15.0f;
	}
	else if (bDefault)pcMesh->eShadingMode  = aiShadingMode_Phong;


	//
	// Shininess strength ------------------------------------------------------
	//
	if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_SHININESS_STRENGTH,&pcMesh->fSpecularStrength))
	{
		// assume 1.0 as default shininess strength
		pcMesh->fSpecularStrength = 1.0f;
	}

	aiString szPath;

	aiTextureMapMode mapU(aiTextureMapMode_Wrap),mapV(aiTextureMapMode_Wrap);

	bool bib =false;
	if (pcSource->mTextureCoords[0])
	{

		//
		// DIFFUSE TEXTURE ------------------------------------------------
		//
		if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_DIFFUSE(0),&szPath))
		{
			LoadTexture(&pcMesh->piDiffuseTexture,&szPath);

			aiGetMaterialInteger(pcMat,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0),(int*)&mapU);
			aiGetMaterialInteger(pcMat,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0),(int*)&mapV);
		}

		//
		// SPECULAR TEXTURE ------------------------------------------------
		//
		if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SPECULAR(0),&szPath))
		{
			LoadTexture(&pcMesh->piSpecularTexture,&szPath);
		}

		//
		// OPACITY TEXTURE ------------------------------------------------
		//
		if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_OPACITY(0),&szPath))
		{
			LoadTexture(&pcMesh->piOpacityTexture,&szPath);
		}
		else
		{
			int flags = 0;
			aiGetMaterialInteger(pcMat,AI_MATKEY_TEXFLAGS_DIFFUSE(0),&flags);

			// try to find out whether the diffuse texture has any
			// non-opaque pixels. If we find a few, use it as opacity texture
			if (pcMesh->piDiffuseTexture && !(flags & aiTextureFlags_IgnoreAlpha) && HasAlphaPixels(pcMesh->piDiffuseTexture))
			{
				int iVal;

				// NOTE: This special value is set by the tree view if the user
				// manually removes the alpha texture from the view ...
				if (AI_SUCCESS != aiGetMaterialInteger(pcMat,"no_a_from_d",0,0,&iVal))
				{
					pcMesh->piOpacityTexture = pcMesh->piDiffuseTexture;
					pcMesh->piOpacityTexture->AddRef();
				}
			}
		}

		//
		// AMBIENT TEXTURE ------------------------------------------------
		//
		if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_AMBIENT(0),&szPath))
		{
			LoadTexture(&pcMesh->piAmbientTexture,&szPath);
		}

		//
		// EMISSIVE TEXTURE ------------------------------------------------
		//
		if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_EMISSIVE(0),&szPath))
		{
			LoadTexture(&pcMesh->piEmissiveTexture,&szPath);
		}

		//
		// Shininess TEXTURE ------------------------------------------------
		//
		if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SHININESS(0),&szPath))
		{
			LoadTexture(&pcMesh->piShininessTexture,&szPath);
		}

		//
		// Lightmap TEXTURE ------------------------------------------------
		//
		if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_LIGHTMAP(0),&szPath))
		{
			LoadTexture(&pcMesh->piLightmapTexture,&szPath);
		}


		//
		// NORMAL/HEIGHT MAP ------------------------------------------------
		//
		bool bHM = false;
		if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_NORMALS(0),&szPath))
		{
			LoadTexture(&pcMesh->piNormalTexture,&szPath);
		}
		else
		{
			if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_HEIGHT(0),&szPath))
			{
				LoadTexture(&pcMesh->piNormalTexture,&szPath);
			}
			else bib = true;
			bHM = true;
		}

		// normal/height maps are sometimes mixed up. Try to detect the type
		// of the texture automatically
		if (pcMesh->piNormalTexture)
		{
			HMtoNMIfNecessary(pcMesh->piNormalTexture, &pcMesh->piNormalTexture,bHM);
		}
	}

	// check whether a global background texture is contained
	// in this material. Some loaders set this value ...
	if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_GLOBAL_BACKGROUND_IMAGE,&szPath))
	{
		CBackgroundPainter::Instance().SetTextureBG(szPath.data);
	}

	// BUGFIX: If the shininess is 0.0f disable phong lighting
	// This is a workaround for some meshes in the DX SDK (e.g. tiny.x)
	// FIX: Added this check to the x-loader, but the line remains to
	// catch other loader doing the same ...
	if (0.0f == pcMesh->fShininess){
		pcMesh->eShadingMode = aiShadingMode_Gouraud;
	}

	int two_sided = 0;
	aiGetMaterialInteger(pcMat,AI_MATKEY_TWOSIDED,&two_sided);
	pcMesh->twosided = (two_sided != 0);

	// check whether we have already a material using the same
	// shader. This will decrease loading time rapidly ...
	for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
	{
		if (g_pcAsset->pcScene->mMeshes[i] == pcSource)
		{
			break;
		}
		AssetHelper::MeshHelper* pc = g_pcAsset->apcMeshes[i];

		if  ((pcMesh->piDiffuseTexture != NULL ? true : false) != 
			(pc->piDiffuseTexture != NULL ? true : false))
			continue;
		if  ((pcMesh->piSpecularTexture != NULL ? true : false) != 
			(pc->piSpecularTexture != NULL ? true : false))
			continue;
		if  ((pcMesh->piAmbientTexture != NULL ? true : false) != 
			(pc->piAmbientTexture != NULL ? true : false))
			continue;
		if  ((pcMesh->piEmissiveTexture != NULL ? true : false) != 
			(pc->piEmissiveTexture != NULL ? true : false))
			continue;
		if  ((pcMesh->piNormalTexture != NULL ? true : false) != 
			(pc->piNormalTexture != NULL ? true : false))
			continue;
		if  ((pcMesh->piOpacityTexture != NULL ? true : false) != 
			(pc->piOpacityTexture != NULL ? true : false))
			continue;
		if  ((pcMesh->piShininessTexture != NULL ? true : false) != 
			(pc->piShininessTexture != NULL ? true : false))
			continue;
		if  ((pcMesh->piLightmapTexture != NULL ? true : false) != 
			(pc->piLightmapTexture != NULL ? true : false))
			continue;
		if ((pcMesh->eShadingMode != aiShadingMode_Gouraud ? true : false) != 
			(pc->eShadingMode != aiShadingMode_Gouraud ? true : false))
			continue;

		if ((pcMesh->fOpacity != 1.0f ? true : false) != (pc->fOpacity != 1.0f ? true : false))
			continue;

		if (pcSource->HasBones() != g_pcAsset->pcScene->mMeshes[i]->HasBones())
			continue;

		// we can reuse this material
		if (pc->piEffect)
		{
			pcMesh->piEffect = pc->piEffect;
			pc->bSharedFX = pcMesh->bSharedFX = true;
			pcMesh->piEffect->AddRef();
			return 2;
		}
	}
	m_iShaderCount++;

	// build macros for the HLSL compiler
	unsigned int iCurrent = 0;
	if (pcMesh->piDiffuseTexture)
	{
		sMacro[iCurrent].Name = "AV_DIFFUSE_TEXTURE";
		sMacro[iCurrent].Definition = "1";
		++iCurrent;

		if (mapU == aiTextureMapMode_Wrap)
			sMacro[iCurrent].Name = "AV_WRAPU";
		else if (mapU == aiTextureMapMode_Mirror)
			sMacro[iCurrent].Name = "AV_MIRRORU";
		else // if (mapU == aiTextureMapMode_Clamp)
			sMacro[iCurrent].Name = "AV_CLAMPU";

		sMacro[iCurrent].Definition = "1";
		++iCurrent;


		if (mapV == aiTextureMapMode_Wrap)
			sMacro[iCurrent].Name = "AV_WRAPV";
		else if (mapV == aiTextureMapMode_Mirror)
			sMacro[iCurrent].Name = "AV_MIRRORV";
		else // if (mapV == aiTextureMapMode_Clamp)
			sMacro[iCurrent].Name = "AV_CLAMPV";

		sMacro[iCurrent].Definition = "1";
		++iCurrent;
	}
	if (pcMesh->piSpecularTexture)
	{
		sMacro[iCurrent].Name = "AV_SPECULAR_TEXTURE";
		sMacro[iCurrent].Definition = "1";
		++iCurrent;
	}
	if (pcMesh->piAmbientTexture)
	{
		sMacro[iCurrent].Name = "AV_AMBIENT_TEXTURE";
		sMacro[iCurrent].Definition = "1";
		++iCurrent;
	}
	if (pcMesh->piEmissiveTexture)
	{
		sMacro[iCurrent].Name = "AV_EMISSIVE_TEXTURE";
		sMacro[iCurrent].Definition = "1";
		++iCurrent;
	}
	char buff[32];
	if (pcMesh->piLightmapTexture)
	{
		sMacro[iCurrent].Name = "AV_LIGHTMAP_TEXTURE";
		sMacro[iCurrent].Definition = "1";
		++iCurrent;

		int idx;
		if(AI_SUCCESS == aiGetMaterialInteger(pcMat,AI_MATKEY_UVWSRC_LIGHTMAP(0),&idx) && idx >= 1 && pcSource->mTextureCoords[idx])	{
			sMacro[iCurrent].Name = "AV_TWO_UV";
			sMacro[iCurrent].Definition = "1";
			++iCurrent;

			sMacro[iCurrent].Definition = "IN.TexCoord1";
		}
		else sMacro[iCurrent].Definition = "IN.TexCoord0";
		sMacro[iCurrent].Name = "AV_LIGHTMAP_TEXTURE_UV_COORD";

		++iCurrent;float f= 1.f;
		aiGetMaterialFloat(pcMat,AI_MATKEY_TEXBLEND_LIGHTMAP(0),&f);
		sprintf(buff,"%f",f);

		sMacro[iCurrent].Name = "LM_STRENGTH";
		sMacro[iCurrent].Definition = buff;
		++iCurrent;
	}
	if (pcMesh->piNormalTexture && !bib)
	{
		sMacro[iCurrent].Name = "AV_NORMAL_TEXTURE";
		sMacro[iCurrent].Definition = "1";
		++iCurrent;
	}
	if (pcMesh->piOpacityTexture)
	{
		sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE";
		sMacro[iCurrent].Definition = "1";
		++iCurrent;

		if (pcMesh->piOpacityTexture == pcMesh->piDiffuseTexture)
		{
			sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE_REGISTER_MASK";
			sMacro[iCurrent].Definition = "a";
			++iCurrent;
		}
		else
		{
			sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE_REGISTER_MASK";
			sMacro[iCurrent].Definition = "r";
			++iCurrent;
		}
	}

	if (pcMesh->eShadingMode  != aiShadingMode_Gouraud  && !g_sOptions.bNoSpecular)
	{
		sMacro[iCurrent].Name = "AV_SPECULAR_COMPONENT";
		sMacro[iCurrent].Definition = "1";
		++iCurrent;

		if (pcMesh->piShininessTexture)
		{
			sMacro[iCurrent].Name = "AV_SHININESS_TEXTURE";
			sMacro[iCurrent].Definition = "1";
			++iCurrent;
		}
	}
	if (1.0f != pcMesh->fOpacity)
	{
		sMacro[iCurrent].Name = "AV_OPACITY";
		sMacro[iCurrent].Definition = "1";
		++iCurrent;
	}

	if( pcSource->HasBones())
	{
		sMacro[iCurrent].Name = "AV_SKINNING";
		sMacro[iCurrent].Definition = "1";
		++iCurrent;
	}

	// If a cubemap is active, we'll need to lookup it for calculating
	// a physically correct reflection
	if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
	{
		sMacro[iCurrent].Name = "AV_SKYBOX_LOOKUP";
		sMacro[iCurrent].Definition = "1";
		++iCurrent;
	}
	sMacro[iCurrent].Name = NULL;
	sMacro[iCurrent].Definition = NULL;

	// compile the shader
	if(FAILED( D3DXCreateEffect(g_piDevice,
		g_szMaterialShader.c_str(),(UINT)g_szMaterialShader.length(),
		(const D3DXMACRO*)sMacro,NULL,0,NULL,&pcMesh->piEffect,&piBuffer)))
	{
		// failed to compile the shader
		if( piBuffer) 
		{
			MessageBox(g_hDlg,(LPCSTR)piBuffer->GetBufferPointer(),"HLSL",MB_OK);
			piBuffer->Release();
		}
		// use the default material instead
		if (g_piDefaultEffect)
		{
			pcMesh->piEffect = g_piDefaultEffect;
			g_piDefaultEffect->AddRef();
		}

		// get the name of the material and use it in the log message
		if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_NAME,&szPath) &&
			'\0' != szPath.data[0])
		{
			std::string sz = "[ERROR] Unable to load material: ";
			sz.append(szPath.data);
			CLogDisplay::Instance().AddEntry(sz);
		}
		else
		{
			CLogDisplay::Instance().AddEntry("Unable to load material: UNNAMED");
		}
		return 0;
	} else
	{
		// use Fixed Function effect when working with shaderless cards
		if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0))
			pcMesh->piEffect->SetTechnique( "MaterialFX_FF");
	}

	if( piBuffer) piBuffer->Release();


	// now commit all constants to the shader
	//
	// This is not necessary for shared shader. Shader constants for
	// shared shaders are automatically recommited before the shader
	// is being used for a particular mesh

	if (1.0f != pcMesh->fOpacity)
		pcMesh->piEffect->SetFloat("TRANSPARENCY",pcMesh->fOpacity);
	if (pcMesh->eShadingMode  != aiShadingMode_Gouraud && !g_sOptions.bNoSpecular)
	{
		pcMesh->piEffect->SetFloat("SPECULARITY",pcMesh->fShininess);
		pcMesh->piEffect->SetFloat("SPECULAR_STRENGTH",pcMesh->fSpecularStrength);
	}

	pcMesh->piEffect->SetVector("DIFFUSE_COLOR",&pcMesh->vDiffuseColor);
	pcMesh->piEffect->SetVector("SPECULAR_COLOR",&pcMesh->vSpecularColor);
	pcMesh->piEffect->SetVector("AMBIENT_COLOR",&pcMesh->vAmbientColor);
	pcMesh->piEffect->SetVector("EMISSIVE_COLOR",&pcMesh->vEmissiveColor);

	if (pcMesh->piDiffuseTexture)
		pcMesh->piEffect->SetTexture("DIFFUSE_TEXTURE",pcMesh->piDiffuseTexture);
	if (pcMesh->piOpacityTexture)
		pcMesh->piEffect->SetTexture("OPACITY_TEXTURE",pcMesh->piOpacityTexture);
	if (pcMesh->piSpecularTexture)
		pcMesh->piEffect->SetTexture("SPECULAR_TEXTURE",pcMesh->piSpecularTexture);
	if (pcMesh->piAmbientTexture)
		pcMesh->piEffect->SetTexture("AMBIENT_TEXTURE",pcMesh->piAmbientTexture);
	if (pcMesh->piEmissiveTexture)
		pcMesh->piEffect->SetTexture("EMISSIVE_TEXTURE",pcMesh->piEmissiveTexture);
	if (pcMesh->piNormalTexture)
		pcMesh->piEffect->SetTexture("NORMAL_TEXTURE",pcMesh->piNormalTexture);
	if (pcMesh->piShininessTexture)
		pcMesh->piEffect->SetTexture("SHININESS_TEXTURE",pcMesh->piShininessTexture);
	if (pcMesh->piLightmapTexture)
		pcMesh->piEffect->SetTexture("LIGHTMAP_TEXTURE",pcMesh->piLightmapTexture);

	if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode()){
		pcMesh->piEffect->SetTexture("lw_tex_envmap",CBackgroundPainter::Instance().GetTexture());
	}

	return 1;
}
Exemple #13
0
//-------------------------------------------------------------------------------
void CMaterialManager::HMtoNMIfNecessary(
	IDirect3DTexture9* piTexture,
	IDirect3DTexture9** piTextureOut,
	bool bWasOriginallyHM)
{
	ai_assert(NULL != piTexture);
	ai_assert(NULL != piTextureOut);

	bool bMustConvert = false;
	uintptr_t iElement = 3;

	*piTextureOut = piTexture;

	// Lock the input texture and try to determine its type.
	// Criterias:
	// - If r,g,b channel are identical it MUST be a height map
	// - If one of the rgb channels is used and the others are empty it
	//   must be a height map, too.
	// - If the average color of the whole image is something inside the
	//   purple range we can be sure it is a normal map
	//
	// - Otherwise we assume it is a normal map
	// To increase performance we take not every pixel

	D3DLOCKED_RECT sRect;
	D3DSURFACE_DESC sDesc;
	piTexture->GetLevelDesc(0,&sDesc);
	if (FAILED(piTexture->LockRect(0,&sRect,NULL,D3DLOCK_READONLY)))
	{
		return;
	}
	const int iPitchDiff = (int)sRect.Pitch - (int)(sDesc.Width * 4);

	struct SColor
	{
		union
		{
			struct {unsigned char b,g,r,a;};
			char _array[4];
		};
	};
	const SColor* pcData = (const SColor*)sRect.pBits;

	union
	{
		const SColor* pcPointer;
		const unsigned char* pcCharPointer;
	};
	pcPointer = pcData;

	// 1. If r,g,b channel are identical it MUST be a height map
	bool bIsEqual = true;
	for (unsigned int y = 0; y <  sDesc.Height;++y)
	{
		for (unsigned int x = 0; x <  sDesc.Width;++x)
		{
			if (pcPointer->b != pcPointer->r || pcPointer->b != pcPointer->g)
			{
				bIsEqual = false;
				break;
			}
			pcPointer++;
		}
		pcCharPointer += iPitchDiff;
	}
	if (bIsEqual)bMustConvert = true;
	else
	{
		// 2. If one of the rgb channels is used and the others are empty it
		//    must be a height map, too.
		pcPointer = pcData;
		while (*pcCharPointer == 0)pcCharPointer++;

		iElement = (uintptr_t)(pcCharPointer - (unsigned char*)pcData) % 4;
		unsigned int aiIndex[3] = {0,1,2};
		if (3 != iElement)aiIndex[iElement] = 3;

		pcPointer = pcData;

		bIsEqual = true;
		if (3 != iElement)
		{
			for (unsigned int y = 0; y <  sDesc.Height;++y)
			{
				for (unsigned int x = 0; x <  sDesc.Width;++x)
				{
					for (unsigned int ii = 0; ii < 3;++ii)
					{
						// don't take the alpha channel into account.
						// if the texture was stored n RGB888 format D3DX has
						// converted it to ARGB8888 format with a fixed alpha channel
						if (aiIndex[ii] != 3 && pcPointer->_array[aiIndex[ii]] != 0)
						{
							bIsEqual = false;
							break;
						}
					}
					pcPointer++;
				}
				pcCharPointer += iPitchDiff;
			}
			if (bIsEqual)bMustConvert = true;
			else
			{
				// If the average color of the whole image is something inside the
				// purple range we can be sure it is a normal map

				// (calculate the average color line per line to prevent overflows!)
				pcPointer = pcData;
				aiColor3D clrColor;
				for (unsigned int y = 0; y <  sDesc.Height;++y)
				{
					aiColor3D clrColorLine;
					for (unsigned int x = 0; x <  sDesc.Width;++x)
					{
						clrColorLine.r += pcPointer->r;
						clrColorLine.g += pcPointer->g;
						clrColorLine.b += pcPointer->b;
						pcPointer++;
					}
					clrColor.r += clrColorLine.r /= (float)sDesc.Width;
					clrColor.g += clrColorLine.g /= (float)sDesc.Width;
					clrColor.b += clrColorLine.b /= (float)sDesc.Width;
					pcCharPointer += iPitchDiff;
				}
				clrColor.r /= (float)sDesc.Height;
				clrColor.g /= (float)sDesc.Height;
				clrColor.b /= (float)sDesc.Height;

				if (!(clrColor.b > 215 && 
					clrColor.r > 100 && clrColor.r < 140 && 
					clrColor.g > 100 && clrColor.g < 140))
				{
					// Unable to detect. Believe the original value obtained from the loader
					if (bWasOriginallyHM)
					{
						bMustConvert = true;
					}
				}
			}
		}
	}

	piTexture->UnlockRect(0);

	// if the input data is assumed to be a height map we'll
	// need to convert it NOW
	if (bMustConvert)
	{
		D3DSURFACE_DESC sDesc;
		piTexture->GetLevelDesc(0, &sDesc);

		IDirect3DTexture9* piTempTexture;
		if(FAILED(g_piDevice->CreateTexture(
			sDesc.Width,
			sDesc.Height,
			piTexture->GetLevelCount(),
			sDesc.Usage,
			sDesc.Format,
			sDesc.Pool, &piTempTexture, NULL)))
		{
			CLogDisplay::Instance().AddEntry(
				"[ERROR] Unable to create normal map texture",
				D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0));
			return;
		}

		DWORD dwFlags;
		if (3 == iElement)dwFlags = D3DX_CHANNEL_LUMINANCE;
		else if (2 == iElement)dwFlags = D3DX_CHANNEL_RED;
		else if (1 == iElement)dwFlags = D3DX_CHANNEL_GREEN;
		else /*if (0 == iElement)*/dwFlags = D3DX_CHANNEL_BLUE;

		if(FAILED(D3DXComputeNormalMap(piTempTexture,
			piTexture,NULL,0,dwFlags,1.0f)))
		{
			CLogDisplay::Instance().AddEntry(
				"[ERROR] Unable to compute normal map from height map",
				D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0));

			piTempTexture->Release();
			return;
		}
		*piTextureOut = piTempTexture;
		piTexture->Release();
	}
}
Exemple #14
0
//-------------------------------------------------------------------------------
int CMaterialManager::LoadTexture(IDirect3DTexture9** p_ppiOut,aiString* szPath)
{
	ai_assert(NULL != p_ppiOut);
	ai_assert(NULL != szPath);

	*p_ppiOut = NULL;

	const std::string s = szPath->data;
	TextureCache::iterator ff;
	if ((ff = sCachedTextures.find(s)) != sCachedTextures.end()) {
		*p_ppiOut = (*ff).second;
		(*p_ppiOut)->AddRef();
		return 1;
	}

	// first get a valid path to the texture
	if( 5 == FindValidPath(szPath))
	{
		// embedded file. Find its index
		unsigned int iIndex = atoi(szPath->data+1);
		if (iIndex < g_pcAsset->pcScene->mNumTextures)
		{
			if (0 == g_pcAsset->pcScene->mTextures[iIndex]->mHeight)
			{
				// it is an embedded file ... don't need the file format hint,
				// simply let D3DX load the file
				D3DXIMAGE_INFO info;
				if (FAILED(D3DXCreateTextureFromFileInMemoryEx(g_piDevice,
					g_pcAsset->pcScene->mTextures[iIndex]->pcData,
					g_pcAsset->pcScene->mTextures[iIndex]->mWidth,
					D3DX_DEFAULT,
					D3DX_DEFAULT,
					1,
					D3DUSAGE_AUTOGENMIPMAP,
					D3DFMT_UNKNOWN,
					D3DPOOL_MANAGED,
					D3DX_DEFAULT,
					D3DX_DEFAULT,
					0,
					&info,
					NULL,
					p_ppiOut)))
				{
					std::string sz = "[ERROR] Unable to load embedded texture (#1): ";
					sz.append(szPath->data);
					CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0));

					this->SetDefaultTexture(p_ppiOut);
					return 1;
				}
			}
			else
			{
				// fill a new texture ...
				if(FAILED(g_piDevice->CreateTexture(
					g_pcAsset->pcScene->mTextures[iIndex]->mWidth,
					g_pcAsset->pcScene->mTextures[iIndex]->mHeight,
					0,D3DUSAGE_AUTOGENMIPMAP,D3DFMT_A8R8G8B8,D3DPOOL_MANAGED,p_ppiOut,NULL)))
				{
					std::string sz = "[ERROR] Unable to load embedded texture (#2): ";
					sz.append(szPath->data);
					CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0));

					this->SetDefaultTexture(p_ppiOut);
					return 1;
				}

				// now copy the data to it ... (assume non pow2 to be supported)
				D3DLOCKED_RECT sLock;
				(*p_ppiOut)->LockRect(0,&sLock,NULL,0);

				const aiTexel* pcData = g_pcAsset->pcScene->mTextures[iIndex]->pcData;

				for (unsigned int y = 0; y < g_pcAsset->pcScene->mTextures[iIndex]->mHeight;++y)
				{
					memcpy(sLock.pBits,pcData,g_pcAsset->pcScene->mTextures[iIndex]->
						mWidth *sizeof(aiTexel));
					sLock.pBits = (char*)sLock.pBits + sLock.Pitch;
					pcData += g_pcAsset->pcScene->mTextures[iIndex]->mWidth;
				}
				(*p_ppiOut)->UnlockRect(0);
				(*p_ppiOut)->GenerateMipSubLevels();
			}
			sCachedTextures[s] = *p_ppiOut;
			(*p_ppiOut)->AddRef();
			return 1;
		}
		else
		{
			std::string sz = "[ERROR] Invalid index for embedded texture: ";
			sz.append(szPath->data);
			CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0));

			SetDefaultTexture(p_ppiOut);
			return 1;
		}
	}

	// then call D3DX to load the texture
	if (FAILED(D3DXCreateTextureFromFileEx(
		g_piDevice,
		szPath->data,
		D3DX_DEFAULT,
		D3DX_DEFAULT,
		0,
		0,
		D3DFMT_A8R8G8B8,
		D3DPOOL_MANAGED,
		D3DX_DEFAULT,
		D3DX_DEFAULT,
		0,
		NULL,
		NULL,
		p_ppiOut)))
	{
		// error ... use the default texture instead
		std::string sz = "[ERROR] Unable to load texture: ";
		sz.append(szPath->data);
		CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0));

		this->SetDefaultTexture(p_ppiOut);
	}
	sCachedTextures[s] = *p_ppiOut;
	(*p_ppiOut)->AddRef();

	return 1;
}
Exemple #15
0
//-------------------------------------------------------------------------------
int CMeshRenderer::DrawSorted(unsigned int iIndex,const aiMatrix4x4& mWorld) {
    ai_assert(iIndex < g_pcAsset->pcScene->mNumMeshes);

    AssetHelper::MeshHelper* pcHelper = g_pcAsset->apcMeshes[iIndex];
    const aiMesh* pcMesh = g_pcAsset->pcScene->mMeshes[iIndex];

    if (!pcHelper || !pcMesh || !pcHelper->piIB)
        return -5;

    if (pcMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE || pcMesh->HasBones() || g_sOptions.bNoAlphaBlending)
        return DrawUnsorted(iIndex);


    // compute the position of the camera in worldspace
    aiMatrix4x4 mWorldInverse = mWorld;
    mWorldInverse.Inverse();
    mWorldInverse.Transpose();
    const aiVector3D vLocalCamera = mWorldInverse * g_sCamera.vPos;

    // well ... this is really funny now. We must compute their distance
    // from the camera. We take the average distance of a face and add it
    // to a map which sorts it
    std::map<float,unsigned int, std::greater<float> > smap;

    for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace)
    {
        const aiFace* pcFace = &pcMesh->mFaces[iFace];
        float fDist = 0.0f;
        for (unsigned int c = 0; c < 3;++c)
        {
            aiVector3D vPos = pcMesh->mVertices[pcFace->mIndices[c]];
            vPos -= vLocalCamera;
            fDist += vPos.SquareLength();
        }
        smap.insert(std::pair<float, unsigned int>(fDist,iFace));
    }

    // now we can lock the index buffer and rebuild it
    D3DINDEXBUFFER_DESC sDesc;
    pcHelper->piIB->GetDesc(&sDesc);

    if (D3DFMT_INDEX16 == sDesc.Format)
    {
        uint16_t* aiIndices;
        pcHelper->piIB->Lock(0,0,(void**)&aiIndices,D3DLOCK_DISCARD);

        for (std::map<float,unsigned int, std::greater<float> >::const_iterator
            i =  smap.begin();
            i != smap.end();++i)
        {
            const aiFace* pcFace =  &pcMesh->mFaces[(*i).second];
            *aiIndices++ = (uint16_t)pcFace->mIndices[0];
            *aiIndices++ = (uint16_t)pcFace->mIndices[1];
            *aiIndices++ = (uint16_t)pcFace->mIndices[2];
        }
    }
    else if (D3DFMT_INDEX32 == sDesc.Format)
    {
        uint32_t* aiIndices;
        pcHelper->piIB->Lock(0,0,(void**)&aiIndices,D3DLOCK_DISCARD);

        for (std::map<float,unsigned int, std::greater<float> >::const_iterator
            i =  smap.begin();
            i != smap.end();++i)
        {
            const aiFace* pcFace =  &pcMesh->mFaces[(*i).second];
            *aiIndices++ = (uint32_t)pcFace->mIndices[0];
            *aiIndices++ = (uint32_t)pcFace->mIndices[1];
            *aiIndices++ = (uint32_t)pcFace->mIndices[2];
        }
    }
    pcHelper->piIB->Unlock();

    // set vertex and index buffer
    g_piDevice->SetStreamSource(0,pcHelper->piVB,0,sizeof(AssetHelper::Vertex));

    // and draw the mesh
    g_piDevice->SetIndices(pcHelper->piIB);
    g_piDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
        0,0,
        pcMesh->mNumVertices,0,
        pcMesh->mNumFaces);

    return 1;
}
Exemple #16
0
// ------------------------------------------------------------------------------------------------
//
void M3Importer::convertToAssimp( const std::string& pFile, aiScene* pScene, DIV *pViews, 
								 Region *pRegions, uint16 *pFaces, 
								 const std::vector<aiVector3D> &vertices,
								 const std::vector<aiVector3D> &normals )
{
	std::vector<aiMesh*> MeshArray;

	// Create the root node
	pScene->mRootNode = createNode( NULL );
	
	// Set the name of the scene
	ai_assert( !pFile.empty() );
	pScene->mRootNode->mName.Set( pFile );

	aiNode *pRootNode = pScene->mRootNode;
	aiNode *pCurrentNode = NULL;

	// Lets create the nodes
	pRootNode->mNumChildren = pViews->regions.nEntries;
	if ( pRootNode->mNumChildren > 0 )
		pRootNode->mChildren = new aiNode*[ pRootNode->mNumChildren ];

	for ( unsigned int i=0; i<pViews->regions.nEntries; ++i )
	{
		// Create a new node
		pCurrentNode = createNode( pRootNode );
		std::stringstream stream;
		stream << "Node_" << i;
		pCurrentNode->mName.Set( stream.str().c_str() );
		pRootNode->mChildren[ i ] = pCurrentNode;
		
		// Loop over the faces of the nodes
		unsigned int numFaces = ( pRegions[ i ].ofsIndices + pRegions[ i ].nIndices ) -  pRegions[ i ].ofsIndices;
		aiMesh *pMesh = new aiMesh;
		MeshArray.push_back( pMesh );

		pMesh->mNumFaces = numFaces;
		pMesh->mFaces = new aiFace[ pMesh->mNumFaces ];
		aiFace *pCurrentFace = NULL;
		unsigned int faceIdx = 0;
		for ( unsigned int j = pRegions[ i ].ofsIndices; j < ( pRegions[ i ].ofsIndices + pRegions[ i ].nIndices ); j += 3 )
		{
			pCurrentFace = &( pMesh->mFaces[ faceIdx ] );
			faceIdx++;
			pCurrentFace->mNumIndices = 3;
			pCurrentFace->mIndices = new unsigned int[ 3 ];
			pCurrentFace->mIndices[ 0 ] = pFaces[ j ]+1;
			pCurrentFace->mIndices[ 1 ] = pFaces[ j+1 ] + 1;
			pCurrentFace->mIndices[ 2 ] = pFaces[ j+2 ] + 1;
		}

		// Now we can create the vertex data itself
		pCurrentNode->mNumMeshes = 1;
		pCurrentNode->mMeshes = new unsigned int[ 1 ];
		pCurrentNode->mMeshes[ 0 ] = MeshArray.size() - 1;
		createVertexData( pMesh, vertices, normals );
	}

	// Copy the meshes into the scene
	pScene->mNumMeshes = MeshArray.size();
	pScene->mMeshes = new aiMesh*[ MeshArray.size() ];
	unsigned int pos = 0;
	for ( std::vector<aiMesh*>::iterator it = MeshArray.begin(); it != MeshArray.end(); ++it )
	{
		pScene->mMeshes[ pos ] = *it;
		pos++;
	}
}