示例#1
0
void CMesh::generateFlatNormals()
{
	if (hasNormals())
		return;
	
	// for each face...
	for (vector<SPolygonFace>::iterator itFace = m_faceVector.begin(); itFace != m_faceVector.end(); ++itFace)
	{
		const SVertex& v1 = m_vertVector[(*itFace).v[0]];
		const SVertex& v2 = m_vertVector[(*itFace).v[1]];
		const SVertex& v3 = m_vertVector[(*itFace).v[2]];
		SVertex v(v2.x - v1.x, v2.y - v1.y, v2.z - v1.z);
		SVertex w(v3.x - v1.x, v3.y - v1.y, v3.z - v1.z);
		SVertex vn(v.y*w.z - v.z*w.y, v.z*w.x - v.x*w.z, v.x*w.y - v.y*w.x);
		float length = sqrtf(vn.x*vn.x+vn.y*vn.y+vn.z*vn.z);
		if (0 < length) {
			const float a = 1/length;
			vn.x *= a;
			vn.y *= a;
			vn.z *= a;
		}
		m_normVector.push_back(vn);
		//	register the generated normal through the face
		fill((*itFace).vn.begin(), (*itFace).vn.end(), m_normVector.size()-1);
	}
}
示例#2
0
void ccDrawableObject::getDrawingParameters(glDrawParams& params) const
{
 	//color override
	if (isColorOverriden())
	{
		params.showColors=true;
		params.showNorms=hasNormals() && normalsShown()/*false*/;
		params.showSF=false;
	}
	else
	{
        params.showNorms = hasNormals() && normalsShown();
        params.showSF = hasDisplayedScalarField() && sfShown();
        //colors are not displayed if scalar field is displayed
        params.showColors = !params.showSF && hasColors() && colorsShown();
	}
}
示例#3
0
void ofxMesh::toMesh(ofMesh & mesh){
    mesh.clear();
    if (hasVertices()) {
        mesh.getVertices()=getVertices();
    }
    if (hasColors()) {
        mesh.getColors()=getColors();
    }
    if (hasNormals()) {
        mesh.getNormals()=getNormals();
    }
    if (hasTexCoords()) {
        mesh.getTexCoords()=getTexCoords();
    }
    if (hasIndices()) {
        mesh.getIndices()=getIndices();
    }
}
示例#4
0
ccPointCloud* ccGenericMesh::samplePoints(	bool densityBased,
											double samplingParameter,
											bool withNormals,
											bool withRGB,
											bool withTexture,
											CCLib::GenericProgressCallback* pDlg/*=0*/)
{
	bool withFeatures = (withNormals || withRGB || withTexture);

	GenericChunkedArray<1,unsigned>* triIndices = (withFeatures ? new GenericChunkedArray<1,unsigned> : 0);

	CCLib::SimpleCloud* sampledCloud = 0;
	if (densityBased)
	{
		sampledCloud = CCLib::MeshSamplingTools::samplePointsOnMesh(this,samplingParameter,pDlg,triIndices);
	}
	else
	{
		sampledCloud = CCLib::MeshSamplingTools::samplePointsOnMesh(this,static_cast<unsigned>(samplingParameter),pDlg,triIndices);
	}

	//convert to real point cloud
	ccPointCloud* cloud = 0;
	
	if (sampledCloud)
	{
		cloud = ccPointCloud::From(sampledCloud);
		delete sampledCloud;
		sampledCloud = 0;
	}

	if (!cloud)
	{
		if (triIndices)
			triIndices->release();

		ccLog::Warning("[ccGenericMesh::samplePoints] Not enough memory!");
		return 0;
	}

	if (withFeatures && triIndices && triIndices->currentSize() >= cloud->size())
	{
		//generate normals
		if (withNormals && hasNormals())
		{
			if (cloud->reserveTheNormsTable())
			{
				for (unsigned i=0; i<cloud->size(); ++i)
				{
					unsigned triIndex = triIndices->getValue(i);
					const CCVector3* P = cloud->getPoint(i);

					CCVector3 N(0,0,1);
					interpolateNormals(triIndex,*P,N);
					cloud->addNorm(N);
				}

				cloud->showNormals(true);
			}
			else
			{
				ccLog::Warning("[ccGenericMesh::samplePoints] Failed to interpolate normals (not enough memory?)");
			}
		}

		//generate colors
		if (withTexture && hasMaterials())
		{
			if (cloud->reserveTheRGBTable())
			{
				for (unsigned i=0; i<cloud->size(); ++i)
				{
					unsigned triIndex = triIndices->getValue(i);
					const CCVector3* P = cloud->getPoint(i);

					colorType C[3]={MAX_COLOR_COMP,MAX_COLOR_COMP,MAX_COLOR_COMP};
					getColorFromMaterial(triIndex,*P,C,withRGB);
					cloud->addRGBColor(C);
				}

				cloud->showColors(true);
			}
			else
			{
				ccLog::Warning("[ccGenericMesh::samplePoints] Failed to export texture colors (not enough memory?)");
			}
		}
		else if (withRGB && hasColors())
		{
			if (cloud->reserveTheRGBTable())
			{
				for (unsigned i=0; i<cloud->size(); ++i)
				{
					unsigned triIndex = triIndices->getValue(i);
					const CCVector3* P = cloud->getPoint(i);

					colorType C[3] = { MAX_COLOR_COMP, MAX_COLOR_COMP, MAX_COLOR_COMP };
					interpolateColors(triIndex,*P,C);
					cloud->addRGBColor(C);
				}

				cloud->showColors(true);
			}
			else
			{
				ccLog::Warning("[ccGenericMesh::samplePoints] Failed to interpolate colors (not enough memory?)");
			}
		}
	}

	//we rename the resulting cloud
	cloud->setName(getName()+QString(".sampled"));
	cloud->setDisplay(getDisplay());
	cloud->prepareDisplayForRefresh();
	
	//copy 'shift on load' information
	if (getAssociatedCloud())
	{
		const CCVector3d& shift = getAssociatedCloud()->getGlobalShift();
		cloud->setGlobalShift(shift);
		double scale = getAssociatedCloud()->getGlobalScale();
		cloud->setGlobalScale(scale);
	}

	if (triIndices)
		triIndices->release();

	return cloud;
}
示例#5
0
QGeometry *ObjLoader::geometry() const
{
    QByteArray bufferBytes;
    const int count = m_points.size();
    const quint32 elementSize = 3 + (hasTextureCoordinates() ? 2 : 0)
            + (hasNormals() ? 3 : 0)
            + (hasTangents() ? 4 : 0);
    const quint32 stride = elementSize * sizeof(float);
    bufferBytes.resize(stride * count);
    float* fptr = reinterpret_cast<float*>(bufferBytes.data());

    for (int index = 0; index < count; ++index) {
        *fptr++ = m_points.at(index).x();
        *fptr++ = m_points.at(index).y();
        *fptr++ = m_points.at(index).z();

        if (hasTextureCoordinates()) {
            *fptr++ = m_texCoords.at(index).x();
            *fptr++ = m_texCoords.at(index).y();
        }

        if (hasNormals()) {
            *fptr++ = m_normals.at(index).x();
            *fptr++ = m_normals.at(index).y();
            *fptr++ = m_normals.at(index).z();
        }

        if (hasTangents()) {
            *fptr++ = m_tangents.at(index).x();
            *fptr++ = m_tangents.at(index).y();
            *fptr++ = m_tangents.at(index).z();
            *fptr++ = m_tangents.at(index).w();
        }
    } // of buffer filling loop

    QBuffer *buf(new QBuffer(QBuffer::VertexBuffer));
    buf->setData(bufferBytes);

    QGeometry *geometry = new QGeometry();
    QAttribute *positionAttribute = new QAttribute(buf, QAttribute::defaultPositionAttributeName(), QAttribute::Float, 3, count, 0, stride);
    geometry->addAttribute(positionAttribute);
    quint32 offset = sizeof(float) * 3;

    if (hasTextureCoordinates()) {
        QAttribute *texCoordAttribute = new QAttribute(buf, QAttribute::defaultTextureCoordinateAttributeName(),  QAttribute::Float, 2, count, offset, stride);
        geometry->addAttribute(texCoordAttribute);
        offset += sizeof(float) * 2;
    }

    if (hasNormals()) {
        QAttribute *normalAttribute = new QAttribute(buf, QAttribute::defaultNormalAttributeName(), QAttribute::Float, 3, count, offset, stride);
        geometry->addAttribute(normalAttribute);
        offset += sizeof(float) * 3;
    }

    if (hasTangents()) {
        QAttribute *tangentAttribute = new QAttribute(buf, QAttribute::defaultTangentAttributeName(),QAttribute::Float, 4, count, offset, stride);
        geometry->addAttribute(tangentAttribute);
        offset += sizeof(float) * 4;
    }

    QByteArray indexBytes;
    QAttribute::DataType ty;
    if (m_indices.size() < 65536) {
        // we can use USHORT
        ty = QAttribute::UnsignedShort;
        indexBytes.resize(m_indices.size() * sizeof(quint16));
        quint16* usptr = reinterpret_cast<quint16*>(indexBytes.data());
        for (int i=0; i<m_indices.size(); ++i)
            *usptr++ = static_cast<quint16>(m_indices.at(i));
    } else {
        // use UINT - no conversion needed, but let's ensure int is 32-bit!
        ty = QAttribute::UnsignedInt;
        Q_ASSERT(sizeof(int) == sizeof(quint32));
        indexBytes.resize(m_indices.size() * sizeof(quint32));
        memcpy(indexBytes.data(), reinterpret_cast<const char*>(m_indices.data()), indexBytes.size());
    }

    QBuffer *indexBuffer(new QBuffer(QBuffer::IndexBuffer));
    indexBuffer->setData(indexBytes);
    QAttribute *indexAttribute = new QAttribute(indexBuffer, ty, 1, m_indices.size());
    indexAttribute->setAttributeType(QAttribute::IndexAttribute);
    geometry->addAttribute(indexAttribute);

    return geometry;
}
bool ModelOBJ::import(const char *pszFilename, bool rebuildNormals)
{
    FILE *pFile = fopen(pszFilename, "r");

    if (!pFile)
        return false;

    // Extract the directory the OBJ file is in from the file name.
    // This directory path will be used to load the OBJ's associated MTL file.

    m_directoryPath.clear();

    std::string filename = pszFilename;
    std::string::size_type offset = filename.find_last_of('\\');

    if (offset != std::string::npos)
    {
        m_directoryPath = filename.substr(0, ++offset);
    }
    else
    {
        offset = filename.find_last_of('/');

        if (offset != std::string::npos)
            m_directoryPath = filename.substr(0, ++offset);
    }

    // Import the OBJ file.

    importGeometryFirstPass(pFile);
    rewind(pFile);
    importGeometrySecondPass(pFile);
    fclose(pFile);

    // Perform post import tasks.

    buildMeshes();
    bounds(m_center, m_width, m_height, m_length, m_radius);

    // Build vertex normals if required.

    if (rebuildNormals)
    {
        generateNormals();
    }
    else
    {
        if (!hasNormals())
            generateNormals();
    }

    // Build tangents is required.

    for (int i = 0; i < m_numberOfMaterials; ++i)
    {
        if (!m_materials[i].bumpMapFilename.empty())
        {
            generateTangents();
            break;
        }
    }

    return true;
}
示例#7
0
bool ccGenericMesh::laplacianSmooth(unsigned nbIteration, float factor, CCLib::GenericProgressCallback* progressCb/*=0*/)
{
    if (!m_associatedCloud)
        return false;

    //vertices
    unsigned vertCount = m_associatedCloud->size();
    //triangles
    unsigned faceCount = size();
    if (!vertCount || !faceCount)
        return false;

    GenericChunkedArray<3,PointCoordinateType>* verticesDisplacement = new GenericChunkedArray<3,PointCoordinateType>;
    if (!verticesDisplacement->resize(vertCount))
    {
        //not enough memory
        verticesDisplacement->release();
        return false;
    }

    //compute the number of edges to which belong each vertex
    unsigned* edgesCount = new unsigned[vertCount];
    if (!edgesCount)
    {
        //not enough memory
        verticesDisplacement->release();
        return false;
    }
    memset(edgesCount, 0, sizeof(unsigned)*vertCount);
    placeIteratorAtBegining();
    for(unsigned j=0; j<faceCount; j++)
    {
        const CCLib::TriangleSummitsIndexes* tri = getNextTriangleIndexes();
        edgesCount[tri->i1]+=2;
        edgesCount[tri->i2]+=2;
        edgesCount[tri->i3]+=2;
    }

    //progress dialog
    CCLib::NormalizedProgress* nProgress = 0;
    if (progressCb)
    {
        unsigned totalSteps = nbIteration;
        nProgress = new CCLib::NormalizedProgress(progressCb,totalSteps);
        progressCb->setMethodTitle("Laplacian smooth");
        progressCb->setInfo(qPrintable(QString("Iterations: %1\nVertices: %2\nFaces: %3").arg(nbIteration).arg(vertCount).arg(faceCount)));
        progressCb->start();
    }

    //repeat Laplacian smoothing iterations
    for(unsigned iter = 0; iter < nbIteration; iter++)
    {
        verticesDisplacement->fill(0);

        //for each triangle
        placeIteratorAtBegining();
        for(unsigned j=0; j<faceCount; j++)
        {
            const CCLib::TriangleSummitsIndexes* tri = getNextTriangleIndexes();

            const CCVector3* A = m_associatedCloud->getPoint(tri->i1);
            const CCVector3* B = m_associatedCloud->getPoint(tri->i2);
            const CCVector3* C = m_associatedCloud->getPoint(tri->i3);

            CCVector3 dAB = (*B-*A);
            CCVector3 dAC = (*C-*A);
            CCVector3 dBC = (*C-*B);

            CCVector3* dA = (CCVector3*)verticesDisplacement->getValue(tri->i1);
            (*dA) += dAB+dAC;
            CCVector3* dB = (CCVector3*)verticesDisplacement->getValue(tri->i2);
            (*dB) += dBC-dAB;
            CCVector3* dC = (CCVector3*)verticesDisplacement->getValue(tri->i3);
            (*dC) -= dAC+dBC;
        }

        if (nProgress && !nProgress->oneStep())
        {
            //cancelled by user
            break;
        }

        //apply displacement
        verticesDisplacement->placeIteratorAtBegining();
        for (unsigned i=0; i<vertCount; i++)
        {
            //this is a "persistent" pointer and we know what type of cloud is behind ;)
            CCVector3* P = const_cast<CCVector3*>(m_associatedCloud->getPointPersistentPtr(i));
            const CCVector3* d = (const CCVector3*)verticesDisplacement->getValue(i);
            (*P) += (*d)*(factor/(PointCoordinateType)edgesCount[i]);
        }
    }

    m_associatedCloud->updateModificationTime();

    if (hasNormals())
        computeNormals();

    if (verticesDisplacement)
        verticesDisplacement->release();
    verticesDisplacement=0;

    if (edgesCount)
        delete[] edgesCount;
    edgesCount=0;

    if (nProgress)
        delete nProgress;
    nProgress=0;

    return true;
}
示例#8
0
void SkinnedMesh::buildSkinnedMesh(ID3DXMesh* mesh)
{
    //====================================================================
    // First add a normal component and 2D texture coordinates component.

    D3DVERTEXELEMENT9 elements[64];
    UINT numElements = 0;
    VertexPNT::Decl->GetDeclaration(elements, &numElements);

    ID3DXMesh* tempMesh = 0;
    HR(mesh->CloneMesh(D3DXMESH_SYSTEMMEM, elements, gd3dDevice, &tempMesh));

    if( !hasNormals(tempMesh) )
        HR(D3DXComputeNormals(tempMesh, 0));

    //====================================================================
    // Optimize the mesh; in particular, the vertex cache.
    DWORD* adj = new DWORD[tempMesh->GetNumFaces()*3];
    ID3DXBuffer* remap = 0;
    HR(tempMesh->GenerateAdjacency(EPSILON, adj));
    ID3DXMesh* optimizedTempMesh = 0;
    HR(tempMesh->Optimize(D3DXMESH_SYSTEMMEM | D3DXMESHOPT_VERTEXCACHE |
                          D3DXMESHOPT_ATTRSORT, adj, 0, 0, &remap, &optimizedTempMesh));

    ReleaseCOM(tempMesh); // Done w/ this mesh.
    delete[] adj;         // Done with buffer.

    // In the .X file (specifically the array DWORD vertexIndices[nWeights]
    // data member of the SkinWeights template) each bone has an array of
    // indices which identify the vertices of the mesh that the bone influences.
    // Because we have just rearranged the vertices (from optimizing), the vertex
    // indices of a bone are obviously incorrect (i.e., they index to vertices the bone
    // does not influence since we moved vertices around).  In order to update a bone's
    // vertex indices to the vertices the bone _does_ influence, we simply need to specify
    // where we remapped the vertices to, so that the vertex indices can be updated to
    // match.  This is done with the ID3DXSkinInfo::Remap method.
    HR(mSkinInfo->Remap(optimizedTempMesh->GetNumVertices(),
                        (DWORD*)remap->GetBufferPointer()));
    ReleaseCOM(remap); // Done with remap info.

    //====================================================================
    // The vertex format of the source mesh does not include vertex weights
    // nor bone index data, which are both needed for vertex blending.
    // Therefore, we must convert the source mesh to an "indexed-blended-mesh,"
    // which does have the necessary data.

    DWORD        numBoneComboEntries = 0;
    ID3DXBuffer* boneComboTable      = 0;
    HR(mSkinInfo->ConvertToIndexedBlendedMesh(optimizedTempMesh, D3DXMESH_MANAGED | D3DXMESH_WRITEONLY,
            MAX_NUM_BONES_SUPPORTED, 0, 0, 0, 0, &mMaxVertInfluences,
            &numBoneComboEntries, &boneComboTable, &mSkinnedMesh));

    ReleaseCOM(optimizedTempMesh); // Done with tempMesh.
    ReleaseCOM(boneComboTable); // Don't need bone table.

#if defined(DEBUG) | defined(_DEBUG)
    // Output to the debug output the vertex declaration of the mesh at this point.
    // This is for insight only to see what exactly ConvertToIndexedBlendedMesh
    // does to the vertex declaration.
    D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
    HR(mSkinnedMesh->GetDeclaration(elems));

    OutputDebugString("\nVertex Format After ConvertToIndexedBlendedMesh\n");
    int i = 0;
    while( elems[i].Stream != 0xff ) // While not D3DDECL_END()
    {
        if( elems[i].Type == D3DDECLTYPE_FLOAT1)
            OutputDebugString("Type = D3DDECLTYPE_FLOAT1; ");
        if( elems[i].Type == D3DDECLTYPE_FLOAT2)
            OutputDebugString("Type = D3DDECLTYPE_FLOAT2; ");
        if( elems[i].Type == D3DDECLTYPE_FLOAT3)
            OutputDebugString("Type = D3DDECLTYPE_FLOAT3; ");
        if( elems[i].Type == D3DDECLTYPE_UBYTE4)
            OutputDebugString("Type = D3DDECLTYPE_UBYTE4; ");

        if( elems[i].Usage == D3DDECLUSAGE_POSITION)
            OutputDebugString("Usage = D3DDECLUSAGE_POSITION\n");
        if( elems[i].Usage == D3DDECLUSAGE_BLENDWEIGHT)
            OutputDebugString("Usage = D3DDECLUSAGE_BLENDWEIGHT\n");
        if( elems[i].Usage == D3DDECLUSAGE_BLENDINDICES)
            OutputDebugString("Usage = D3DDECLUSAGE_BLENDINDICES\n");
        if( elems[i].Usage == D3DDECLUSAGE_NORMAL)
            OutputDebugString("Usage = D3DDECLUSAGE_NORMAL\n");
        if( elems[i].Usage == D3DDECLUSAGE_TEXCOORD)
            OutputDebugString("Usage = D3DDECLUSAGE_TEXCOORD\n");
        ++i;
    }
#endif
}
void ofxOBJModel::loadVbo() {
	int count = 0;
	for(int i = 0; i < meshes.size(); i++) {
		for(int j = 0; j < meshes[i]->faces.size(); j++) {
			
			int pointCount = meshes[i]->faces[j]->points.size();
			
			if(pointCount==3) {
				count += 3;
			} else {
				// if the poly has more than 3 sides, 
				// we're gonna do a triangle fan.
				// 4 points goes to 6 points
				// 5 points goes to 9 points
				// 6 points goes to 12 points
				count += (pointCount - 2)*3;
			}
			
		}
	}
	coords = new ofVec3f[count];
	ofVec3f *normals = NULL;
	ofVec2f *texCoords = NULL;
	if(hasNormals()) normals = new ofVec3f[count];
	if(hasTexCoords()) texCoords = new ofVec2f[count];
	int pos = 0; 
	for(int i = 0; i < meshes.size(); i++) {
		for(int j = 0; j < meshes[i]->faces.size(); j++) {
			
			int pointCount = meshes[i]->faces[j]->points.size();
			if(pointCount==3) {
				for(int k = 0; k < pointCount; k++) {
					coords[pos] = meshes[i]->faces[j]->points[k];
				
					if(normals!=NULL) {
						normals[pos] = meshes[i]->faces[j]->normals[k];
					}
					if(texCoords!=NULL) {
						texCoords[pos] = meshes[i]->faces[j]->texCoords[k];
					}
					
					pos++;
				}
			} else {
				// triangle fan
				int triCount = pointCount - 2;
				for(int tri = 0; tri < triCount; tri++) {
					for(int p = 0; p < 3; p++) {
						coords[pos] = meshes[i]->faces[j]->points[tri+p];
						
						if(normals!=NULL) {
							normals[pos] = meshes[i]->faces[j]->normals[tri+p];
						}
						if(texCoords!=NULL) {
							texCoords[pos] = meshes[i]->faces[j]->texCoords[tri+p];
						}
						pos++;
					}
				}
			}
		}
	}
	
	vbo.clear();
	
	vbo.setVertexData(coords, count, GL_STATIC_DRAW_ARB);
	
	if(normals!=NULL) vbo.setNormalData(normals, count, GL_STATIC_DRAW_ARB);
	if(texCoords!=NULL) vbo.setTexCoordData(texCoords, count, GL_STATIC_DRAW_ARB);
	
	//delete [] coords;
	if(normals!=NULL) delete [] normals;
	if(texCoords!=NULL) delete [] texCoords;
	vboCoordCount = count;
}