<commit_before>/**********************************************************************
 *
 *	FILE:			ReaderWriterdds.cpp
 *
 *	DESCRIPTION:	Class for reading a DDS file into an osg::Image.
 *
 *					Example on reading a DDS file code can be found at:
 *					http://developer.nvidia.com/docs/IO/1327/ATT/
 *					ARB_texture_compression.pdf
 *					Author: Sbastien Domin, NVIDIA Corporation
 *
 *	CREATED BY:		Rune Schmidt Jensen, rsj@uni-dk
 *
 *	HISTORY:		Created 31.03.2003
 *
  **********************************************************************/

#include <osg/Texture>

#include <osgDB/Registry>
#include <osgDB/FileNameUtils>

#include <stdio.h>

// NOTICE ON WIN32:
// typedef DWORD unsigned long;
// sizeof(DWORD) = 4
typedef struct _DDCOLORKEY
{
    unsigned long	dwColorSpaceLowValue;
	unsigned long	dwColorSpaceHighValue;
} DDCOLORKEY;

typedef struct _DDPIXELFORMAT
{
    unsigned long	dwSize;
    unsigned long	dwFlags;
    unsigned long	dwFourCC;
    union
    {
	unsigned long	dwRGBBitCount;
	unsigned long	dwYUVBitCount;
	unsigned long	dwZBufferBitDepth;
	unsigned long	dwAlphaBitDepth;
    };
    union
    {
	unsigned long	dwRBitMask;
	unsigned long	dwYBitMask;
    };
    union
    {
	unsigned long	dwGBitMask;
	unsigned long	dwUBitMask;
    };
    union
    {
	unsigned long	dwBBitMask;
	unsigned long	dwVBitMask;
    };
    union
    {
	unsigned long	dwRGBAlphaBitMask;
	unsigned long	dwYUVAlphaBitMask;
	unsigned long	dwRGBZBitMask;
	unsigned long	dwYUVZBitMask;
    };
} DDPIXELFORMAT;

typedef struct _DDSCAPS2
{
    unsigned long       dwCaps;
    unsigned long       dwCaps2;
    unsigned long       dwCaps3;
    union
    {
        unsigned long       dwCaps4;
        unsigned long       dwVolumeDepth;
    };
} DDSCAPS2;

typedef struct _DDSURFACEDESC2 {
    unsigned long         dwSize;
    unsigned long         dwFlags;
    unsigned long         dwHeight;
    unsigned long         dwWidth;
    union
    {
        long      lPitch;
        unsigned long      dwLinearSize;
    };
    unsigned long         dwBackBufferCount;
    union
    {
        unsigned long     dwMipMapCount;
        unsigned long     dwRefreshRate;
    };
    unsigned long         dwAlphaBitDepth;
    unsigned long         dwReserved;
    unsigned long*        lpSurface;
    DDCOLORKEY    ddckCKDestOverlay;
    DDCOLORKEY    ddckCKDestBlt;
    DDCOLORKEY    ddckCKSrcOverlay;
    DDCOLORKEY    ddckCKSrcBlt;
    DDPIXELFORMAT ddpfPixelFormat;
    DDSCAPS2      ddsCaps;
    unsigned long         dwTextureStage;
} DDSURFACEDESC2;

#ifndef MAKEFOURCC
    #define MAKEFOURCC(ch0, ch1, ch2, ch3)                              \
                ((unsigned long)(char)(ch0) | ((unsigned long)(char)(ch1) << 8) |   \
                ((unsigned long)(char)(ch2) << 16) | ((unsigned long)(char)(ch3) << 24 ))
#endif //defined(MAKEFOURCC)

/*
 * FOURCC codes for DX compressed-texture pixel formats
 */
#define FOURCC_DXT1  (MAKEFOURCC('D','X','T','1'))
#define FOURCC_DXT2  (MAKEFOURCC('D','X','T','2'))
#define FOURCC_DXT3  (MAKEFOURCC('D','X','T','3'))
#define FOURCC_DXT4  (MAKEFOURCC('D','X','T','4'))
#define FOURCC_DXT5  (MAKEFOURCC('D','X','T','5'))

osg::Image* ReadDDSFile(const char *filename){
	osg::Image* osgImage = new osg::Image();

	DDSURFACEDESC2 ddsd;

	char filecode[4];
	FILE *fp;

	// Open file.
	fp = fopen(filename, "rb");
	if (fp == NULL)
		return NULL;

	// Verify that this is a DDS file.
	fread(filecode, 1, 4, fp);
	if (strncmp(filecode, "DDS ", 4) != 0) {
		fclose(fp);
		return NULL;
	}

	// Get the surface desc.
	fread(&ddsd, sizeof(ddsd), 1, fp);

	// Read image data.
	unsigned int size = ddsd.dwMipMapCount > 1 ? ddsd.dwLinearSize * 2 : ddsd.dwLinearSize;
	unsigned char* imageData = (unsigned char*) malloc(size * sizeof(unsigned char));
	fread(imageData, 1, size, fp);
	// Close the file.
	fclose(fp);

	// Retreive image properties.
	int s = ddsd.dwWidth;
	int t = ddsd.dwHeight;
    int r = ddsd.dwMipMapCount>1?ddsd.dwMipMapCount:0;
	unsigned int dataType = GL_UNSIGNED_BYTE;
	unsigned int pixelFormat;
	unsigned int internalFormat;
	switch(ddsd.ddpfPixelFormat.dwFourCC){
		case FOURCC_DXT1:
			internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
			pixelFormat    = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
			break;
		case FOURCC_DXT3:
			internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
			pixelFormat    = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
			break;
		case FOURCC_DXT5:
			internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
			pixelFormat    = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
			break;
		default:
			free(imageData);
			return NULL;
	}

	// Set image data and properties.
	osgImage->setImage(s,t,r, internalFormat, pixelFormat, dataType, imageData, osg::Image::USE_NEW_DELETE);

	// Return Image.
	return osgImage;
}

class ReaderWriterDDS : public osgDB::ReaderWriter
{
    public:
        virtual const char* className() {
			return "DDS Image Reader";
		}

        virtual bool acceptsExtension(const std::string& extension) {
			return osgDB::equalCaseInsensitive(extension,"dds");
		}

        virtual ReadResult readImage(const std::string& fileName, const osgDB::ReaderWriter::Options*) {
			osg::Image* osgImage = ReadDDSFile(fileName.c_str());
            if (osgImage==NULL) return ReadResult::FILE_NOT_HANDLED;
            return osgImage;

        }
};

// now register with Registry to instantiate the above
// reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterDDS> g_readerWriter_DDS_Proxy;
<commit_msg>Fixes to the dds plugin.<commit_after>/**********************************************************************
 *
 *    FILE:            ReaderWriterdds.cpp
 *
 *    DESCRIPTION:    Class for reading a DDS file into an osg::Image.
 *
 *                    Example on reading a DDS file code can be found at:
 *                    http://developer.nvidia.com/docs/IO/1327/ATT/
 *                    ARB_texture_compression.pdf
 *                    Author: Sbastien Domin, NVIDIA Corporation
 *
 *    CREATED BY:        Rune Schmidt Jensen, rsj@uni-dk
 *
 *    HISTORY:        Created 31.03.2003
 *
  **********************************************************************/

#include <osg/Texture>
#include <osg/Notify>

#include <osgDB/Registry>
#include <osgDB/FileNameUtils>

#include <stdio.h>

// NOTICE ON WIN32:
// typedef DWORD unsigned long;
// sizeof(DWORD) = 4
typedef struct _DDCOLORKEY
{
    unsigned long    dwColorSpaceLowValue;
    unsigned long    dwColorSpaceHighValue;
} DDCOLORKEY;

typedef struct _DDPIXELFORMAT
{
    unsigned long    dwSize;
    unsigned long    dwFlags;
    unsigned long    dwFourCC;
    union
    {
        unsigned long    dwRGBBitCount;
        unsigned long    dwYUVBitCount;
        unsigned long    dwZBufferBitDepth;
        unsigned long    dwAlphaBitDepth;
    };
    union
    {
        unsigned long    dwRBitMask;
        unsigned long    dwYBitMask;
    };
    union
    {
        unsigned long    dwGBitMask;
        unsigned long    dwUBitMask;
    };
    union
    {
        unsigned long    dwBBitMask;
        unsigned long    dwVBitMask;
    };
    union
    {
        unsigned long    dwRGBAlphaBitMask;
        unsigned long    dwYUVAlphaBitMask;
        unsigned long    dwRGBZBitMask;
        unsigned long    dwYUVZBitMask;
    };
} DDPIXELFORMAT;

typedef struct _DDSCAPS2
{
    unsigned long       dwCaps;
    unsigned long       dwCaps2;
    unsigned long       dwCaps3;
    union
    {
        unsigned long       dwCaps4;
        unsigned long       dwVolumeDepth;
    };
} DDSCAPS2;

typedef struct _DDSURFACEDESC2
{
    unsigned long         dwSize;
    unsigned long         dwFlags;
    unsigned long         dwHeight;
    unsigned long         dwWidth;
    union
    {
        long              lPitch;
        unsigned long     dwLinearSize;
    };
    unsigned long         dwBackBufferCount;
    union
    {
        unsigned long     dwMipMapCount;
        unsigned long     dwRefreshRate;
    };
    unsigned long         dwAlphaBitDepth;
    unsigned long         dwReserved;
    unsigned long*        lpSurface;
    DDCOLORKEY    ddckCKDestOverlay;
    DDCOLORKEY    ddckCKDestBlt;
    DDCOLORKEY    ddckCKSrcOverlay;
    DDCOLORKEY    ddckCKSrcBlt;
    DDPIXELFORMAT ddpfPixelFormat;
    DDSCAPS2      ddsCaps;
    unsigned long         dwTextureStage;
} DDSURFACEDESC2;

#ifndef MAKEFOURCC
    #define MAKEFOURCC(ch0, ch1, ch2, ch3)                              \
                ((unsigned long)(char)(ch0) | ((unsigned long)(char)(ch1) << 8) |   \
                ((unsigned long)(char)(ch2) << 16) | ((unsigned long)(char)(ch3) << 24 ))
#endif //defined(MAKEFOURCC)

/*
 * FOURCC codes for DX compressed-texture pixel formats
 */
#define FOURCC_DXT1  (MAKEFOURCC('D','X','T','1'))
#define FOURCC_DXT2  (MAKEFOURCC('D','X','T','2'))
#define FOURCC_DXT3  (MAKEFOURCC('D','X','T','3'))
#define FOURCC_DXT4  (MAKEFOURCC('D','X','T','4'))
#define FOURCC_DXT5  (MAKEFOURCC('D','X','T','5'))

osg::Image* ReadDDSFile(const char *filename)
{
    osg::Image* osgImage = new osg::Image();

    DDSURFACEDESC2 ddsd;

    char filecode[4];
    FILE *fp;

    // Open file.
    fp = fopen(filename, "rb");
    if (fp == NULL)
        return NULL;

    // Verify that this is a DDS file.
    fread(filecode, 1, 4, fp);
    if (strncmp(filecode, "DDS ", 4) != 0) {
        fclose(fp);
        return NULL;
    }

    // Get the surface desc.
    fread(&ddsd, sizeof(ddsd), 1, fp);

    // Read image data.
    unsigned int size = ddsd.dwMipMapCount > 1 ? ddsd.dwLinearSize * 2 : ddsd.dwLinearSize;
    unsigned char* imageData = new unsigned char [size];
    fread(imageData, 1, size, fp);
    // Close the file.
    fclose(fp);

    // Retreive image properties.
    int s = ddsd.dwWidth;
    int t = ddsd.dwHeight;
    int r = 1; // we're not a 3d texture...
    unsigned int dataType = GL_UNSIGNED_BYTE;
    unsigned int pixelFormat;
    unsigned int internalFormat;
    switch(ddsd.ddpfPixelFormat.dwFourCC)
    {
        case FOURCC_DXT1:
            internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
            pixelFormat    = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
            break;
        case FOURCC_DXT3:
            internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
            pixelFormat    = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
            break;
        case FOURCC_DXT5:
            internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
            pixelFormat    = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
            break;
        default:
            delete [] imageData;
            return NULL;
    }

    if (ddsd.dwMipMapCount>1)
    {
        osg::notify(osg::WARN)<<"Warning: Mipmaps in dds file are ignored."<<std::endl;

//      this is code from the txp plugin, so won't compile here, but it'll be useful guide
//      to implementing the real mip mapping code.
//         // now set mipmap data (offsets into image raw data)
//         Image::MipmapDataType mipmaps;
//         // number of offsets in osg is one less than num_mipmaps
//         // because it's assumed that first offset iz 0
//         mipmaps.resize(num_mipmaps-1);
//         for( int k = 1 ; k < num_mipmaps;k++ )
//         {
//             mipmaps[k-1] = tmp_tex->MipLevelOffset(k);
//         }
//         image->setMipmapData(mipmaps);

    }

    // Set image data and properties.
    osgImage->setImage(s,t,r, internalFormat, pixelFormat, dataType, imageData, osg::Image::USE_NEW_DELETE);

    // Return Image.
    return osgImage;
}

class ReaderWriterDDS : public osgDB::ReaderWriter
{
    public:
        virtual const char* className()
        {
            return "DDS Image Reader";
        }

        virtual bool acceptsExtension(const std::string& extension)
        {
            return osgDB::equalCaseInsensitive(extension,"dds");
        }

        virtual ReadResult readImage(const std::string& fileName, const osgDB::ReaderWriter::Options*)
        {
            osg::Image* osgImage = ReadDDSFile(fileName.c_str());
            if (osgImage==NULL) return ReadResult::FILE_NOT_HANDLED;
            return osgImage;

        }
};

// now register with Registry to instantiate the above
// reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterDDS> g_readerWriter_DDS_Proxy;
<|endoftext|>


<commit_before>// -*-c++-*-

/*
 * Wavefront OBJ loader for Open Scene Graph
 *
 * Copyright (C) 2001 Ulrich Hertlein <u.hertlein@web.de>
 *
 * Modified by Robert Osfield to support per Drawable coord, normal and
 * texture coord arrays, bug fixes, and support for texture mapping.
 *
 * The Open Scene Graph (OSG) is a cross platform C++/OpenGL library for
 * real-time rendering of large 3D photo-realistic models.
 * The OSG homepage is http://www.openscenegraph.org/
 */

#if defined(_MSC_VER)
	#pragma warning( disable : 4786 )
#endif

#include <string>

#include <osg/Notify>
#include <osg/Node>
#include <osg/Transform>
#include <osg/Geode>

#include <osg/GeoSet>
#include <osg/StateSet>
#include <osg/Material>
#include <osg/Texture>
#include <osg/TexGen>

#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>

#include "glm.h"

class ReaderWriterOBJ : public osgDB::ReaderWriter
{
public:
    ReaderWriterOBJ() { }

    virtual const char* className() { return "Wavefront OBJ Reader"; }
    virtual bool acceptsExtension(const std::string& extension) {
        return (extension == "obj");
    }

    virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options*);

protected:
    osg::Drawable* makeDrawable(GLMmodel* obj, GLMgroup* grp, osg::StateSet**);
};

// register with Registry to instantiate the above reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterOBJ> g_objReaderWriterProxy;

// read file and convert to OSG.
osgDB::ReaderWriter::ReadResult ReaderWriterOBJ::readNode(const std::string& fileName, const osgDB::ReaderWriter::Options*)
{
    GLMmodel* obj = glmReadOBJ((char*) fileName.c_str());
    if (!obj)
        return ReadResult::FILE_NOT_HANDLED;

    std::string directory = osgDB::getFilePath(fileName);

    osg::notify(osg::INFO) << "vertices " << obj->numvertices << endl;
    osg::notify(osg::INFO)  << "normals " << obj->numnormals << endl;
    osg::notify(osg::INFO)  << "texcoords " << obj->numtexcoords << endl;
    osg::notify(osg::INFO)  << "face normals " << obj->numfacetnorms << endl;
    osg::notify(osg::INFO)  << "tris " << obj->numtriangles << endl;
    osg::notify(osg::INFO)  << "materials " << obj->nummaterials << endl;
    osg::notify(osg::INFO)  << "groups " << obj->numgroups << endl;

    if (obj->numnormals==0)
    {
        osg::notify(osg::NOTICE)  << "No normals in .obj file, automatically calculating normals..."<<endl;
        glmFacetNormals(obj);
        glmVertexNormals(obj,90.0f);
    }

    unsigned int i;

    // materials
    osg::StateSet** osg_mtl = NULL;
    if (obj->nummaterials > 0) {
        osg_mtl = new osg::StateSet*[obj->nummaterials];
        for (i = 0; i < obj->nummaterials; i++) {
            GLMmaterial* omtl = &(obj->materials[i]);
            cerr << "mtl: " << omtl->name << endl;

            osg::StateSet* stateset = new osg::StateSet;
            osg_mtl[i] = stateset;

            osg::Material* mtl = new osg::Material;
            mtl->setAmbient(osg::Material::FRONT_AND_BACK,
                            osg::Vec4(omtl->ambient[0], omtl->ambient[1],
                                      omtl->ambient[2], omtl->ambient[3]));
            mtl->setDiffuse(osg::Material::FRONT_AND_BACK,
                            osg::Vec4(omtl->diffuse[0], omtl->diffuse[1],
                                      omtl->diffuse[2], omtl->diffuse[3]));
            mtl->setSpecular(osg::Material::FRONT_AND_BACK,
                             osg::Vec4(omtl->specular[0], omtl->specular[1],
                                       omtl->specular[2], omtl->specular[3]));
            mtl->setEmission(osg::Material::FRONT_AND_BACK,
                             osg::Vec4(omtl->emmissive[0], omtl->emmissive[1],
                                       omtl->emmissive[2], omtl->emmissive[3]));
            // note, osg shininess scales between 0.0 and 1.0.
            mtl->setShininess(osg::Material::FRONT_AND_BACK, omtl->shininess/128.0f);

            stateset->setAttribute(mtl);

            if (omtl->textureName)
            {
                std::string fileName = osgDB::findFileInDirectory(omtl->textureName,directory,true);
                if (!fileName.empty())
                {

                    osg::Image* osg_image = osgDB::readImageFile(fileName.c_str());
                    if (osg_image)
                    {
                        osg::Texture* osg_texture = new osg::Texture;
                        osg_texture->setImage(osg_image);
                        stateset->setAttributeAndModes(osg_texture,osg::StateAttribute::ON);

                        if (omtl->textureReflection)
                        {
                            osg::TexGen* osg_texgen = new osg::TexGen;
                            osg_texgen->setMode(osg::TexGen::SPHERE_MAP);
                            stateset->setAttributeAndModes(osg_texgen,osg::StateAttribute::ON);
                        }
                    }
                    else
                    {
                        osg::notify(osg::NOTICE) << "Warning: Cannot create texture "<<omtl->textureName<<endl;
                    }
                }
                else
                {
                    osg::notify(osg::WARN) << "texture '"<<omtl->textureName<<"' not found"<<endl;
                }
            }
        }
    }

    // toplevel group or transform
    osg::Group* osg_top = NULL;
    if (obj->position[0] != 0.0f || obj->position[2] != 0.0f || obj->position[2] != 0.0f) {
        osg::Transform* xform = new osg::Transform;
		// note obj_x -> osg_x,
		//      obj_y -> osg_z,
		//      obj_z -> osg_y,
        xform->setMatrix(osg::Matrix::trans(obj->position[0], obj->position[2], obj->position[1]));
        osg_top = xform;
    }
    else
        osg_top = new osg::Group;

    osg_top->setName(obj->pathname);

    // subgroups
    // XXX one Geode per group is probably not necessary...
    GLMgroup* ogrp = obj->groups;
    while (ogrp) {
        if (ogrp->numtriangles > 0) {

            osg::Geode* osg_geo = new osg::Geode;
            osg_geo->setName(ogrp->name);
            osg_geo->addDrawable(makeDrawable(obj,ogrp, osg_mtl));
            osg_top->addChild(osg_geo);
        }
        ogrp = ogrp->next;
    }

    // free
    glmDelete(obj);
    if (osg_mtl)
        delete[] osg_mtl;

    return osg_top;
}

// make drawable from OBJ group
osg::Drawable* ReaderWriterOBJ::makeDrawable(GLMmodel* obj,
                                             GLMgroup* grp,
                                             osg::StateSet** mtl)
{

    GLMtriangle* tris = obj->triangles;

    unsigned int ntris = grp->numtriangles;
    unsigned int i = 0;

    // geoset
    osg::GeoSet* gset = new osg::GeoSet;

    // primitives are only triangles
    gset->setPrimType(osg::GeoSet::TRIANGLES);
    gset->setNumPrims(ntris);
    int* primLen = new int[ntris];
    gset->setPrimLengths(primLen);

    // the following code for mapping the coords, normals and texcoords
    // is complicated greatly by the need to create seperate out the
    // sets of coords etc for each drawable.

    typedef std::vector<int> IndexVec;

    // fill an vector full of 0's, one for each vertex.
    IndexVec vcount(obj->numvertices+1,0);
    IndexVec ncount(obj->numnormals+1,0);
    IndexVec tcount(obj->numtexcoords+1,0);

    bool needNormals = obj->normals && obj->normals>0;
    bool needTexcoords = obj->texcoords && obj->numtexcoords>0;

    // first count the number of vertices used in this group.
    for (i = 0; i < ntris; i++)
    {
        GLMtriangle* tri = &(tris[grp->triangles[i]]);

        // increment the count once for each traingle corner.
        ++vcount[tri->vindices[0]];
        ++vcount[tri->vindices[1]];
        ++vcount[tri->vindices[2]];

        if (needNormals)
        {
            ++ncount[tri->nindices[0]];
            ++ncount[tri->nindices[1]];
            ++ncount[tri->nindices[2]];
        }

        if (needTexcoords)
        {
            ++tcount[tri->tindices[0]];
            ++tcount[tri->tindices[1]];
            ++tcount[tri->tindices[2]];
        }
    }

    IndexVec::iterator itr;
    int numCoords = 0;
    for(itr=vcount.begin();
        itr!=vcount.end();
        ++itr)
    {
        if ((*itr)>0) ++numCoords;
    }

    if (numCoords==0) return NULL;

    int numNormals = 0;
    for(itr=ncount.begin();
        itr!=ncount.end();
        ++itr)
    {
        if ((*itr)>0) ++numNormals;
    }

    int numTexcoords = 0;
    for(itr=tcount.begin();
        itr!=tcount.end();
        ++itr)
    {
        if ((*itr)>0) ++numTexcoords;
    }

    // allocate drawables vertices.
    osg::Vec3* coords = new osg::Vec3[numCoords];

    // allocate drawables normals.
    osg::Vec3* normals = NULL;
    if (numNormals>0) normals = new osg::Vec3[numNormals];

    // allocate drawables textcoords.
    osg::Vec2* texcoords = NULL;
    if (numTexcoords>0) texcoords = new osg::Vec2[numTexcoords];

    // fill an vector full of 0's, one for each vertex.
    IndexVec vmapping(obj->numvertices+1,-1);
    IndexVec nmapping(obj->numnormals+1,-1);
    IndexVec tmapping(obj->numtexcoords+1,-1);

    int coordCount = 0;
    for (i = 0; i < vcount.size(); i++)
    {

        if (vcount[i]>0)
        {

            // note obj_x -> osg_x,
            //      obj_y -> -osg_z,
            //      obj_z -> osg_y,
            coords[coordCount].set(obj->vertices[i*3+0],
                                   -obj->vertices[i*3+2],
                                   obj->vertices[i*3+1]);

            vmapping[i]=coordCount;
            ++coordCount;
        }
    }

    int normCount = 0;
    for (i = 0; i < ncount.size(); i++)
    {

        if (ncount[i]>0)
        {
            // note obj_x -> osg_x,
            //      obj_y -> osg_z,
            //      obj_z -> osg_y,
            // to rotate the about x axis to have model z upwards.
            normals[normCount].set(obj->normals[i*3+0],
                                   -obj->normals[i*3+2],
                                   obj->normals[i*3+1]);
            nmapping[i]=normCount;
            ++normCount;
        }
    }

    int texCount = 0;
    for (i = 0; i < tcount.size(); i++)
    {
        if (tcount[i]>0)
        {
            texcoords[texCount].set(obj->texcoords[i*2+0], obj->texcoords[i*2+1]);
            tmapping[i]=texCount;
            ++texCount;
        }
    }

    // index arrays
    unsigned int* cindex = NULL;
    cindex = new unsigned int[ntris * 3];

    unsigned int* nindex = NULL;
    if (normals)
        nindex = new unsigned int[ntris * 3];

    unsigned int* tindex = NULL;
    if (texcoords)
        tindex = new unsigned int[ntris * 3];

    // setup arrays
    for (i = 0; i < ntris; i++) {
        primLen[i] = 3;
        GLMtriangle* tri = &(tris[grp->triangles[i]]);

        cindex[i*3+0] = vmapping[tri->vindices[0]];
        cindex[i*3+1] = vmapping[tri->vindices[1]];
        cindex[i*3+2] = vmapping[tri->vindices[2]];

        if (nindex) {
            nindex[i*3+0] = nmapping[tri->nindices[0]];
            nindex[i*3+1] = nmapping[tri->nindices[1]];
            nindex[i*3+2] = nmapping[tri->nindices[2]];
        }

        if (tindex) {
            tindex[i*3+0] = tmapping[tri->tindices[0]];
            tindex[i*3+1] = tmapping[tri->tindices[1]];
            tindex[i*3+2] = tmapping[tri->tindices[2]];
        }
    }

    if (coords && cindex)
        gset->setCoords(coords, cindex);

    if (normals && nindex) {
        gset->setNormals(normals, nindex);
        gset->setNormalBinding(osg::GeoSet::BIND_PERVERTEX);
    }

    if (texcoords && tindex) {
        gset->setTextureCoords(texcoords, tindex);
        gset->setTextureBinding(osg::GeoSet::BIND_PERVERTEX);
    }

    // state and material (if any)
    if (mtl) {

        gset->setStateSet(mtl[grp->material]);
    }
    else
        osg::notify(osg::INFO) << "Group " << grp->name << " has no material" << endl;

    return gset;
}

<commit_msg>Made a output message output as osg::DEBUG only.<commit_after>// -*-c++-*-

/*
 * Wavefront OBJ loader for Open Scene Graph
 *
 * Copyright (C) 2001 Ulrich Hertlein <u.hertlein@web.de>
 *
 * Modified by Robert Osfield to support per Drawable coord, normal and
 * texture coord arrays, bug fixes, and support for texture mapping.
 *
 * The Open Scene Graph (OSG) is a cross platform C++/OpenGL library for
 * real-time rendering of large 3D photo-realistic models.
 * The OSG homepage is http://www.openscenegraph.org/
 */

#if defined(_MSC_VER)
	#pragma warning( disable : 4786 )
#endif

#include <string>

#include <osg/Notify>
#include <osg/Node>
#include <osg/Transform>
#include <osg/Geode>

#include <osg/GeoSet>
#include <osg/StateSet>
#include <osg/Material>
#include <osg/Texture>
#include <osg/TexGen>

#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>

#include "glm.h"

class ReaderWriterOBJ : public osgDB::ReaderWriter
{
public:
    ReaderWriterOBJ() { }

    virtual const char* className() { return "Wavefront OBJ Reader"; }
    virtual bool acceptsExtension(const std::string& extension) {
        return (extension == "obj");
    }

    virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options*);

protected:
    osg::Drawable* makeDrawable(GLMmodel* obj, GLMgroup* grp, osg::StateSet**);
};

// register with Registry to instantiate the above reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterOBJ> g_objReaderWriterProxy;

// read file and convert to OSG.
osgDB::ReaderWriter::ReadResult ReaderWriterOBJ::readNode(const std::string& fileName, const osgDB::ReaderWriter::Options*)
{
    GLMmodel* obj = glmReadOBJ((char*) fileName.c_str());
    if (!obj)
        return ReadResult::FILE_NOT_HANDLED;

    std::string directory = osgDB::getFilePath(fileName);

    osg::notify(osg::INFO) << "vertices " << obj->numvertices << endl;
    osg::notify(osg::INFO)  << "normals " << obj->numnormals << endl;
    osg::notify(osg::INFO)  << "texcoords " << obj->numtexcoords << endl;
    osg::notify(osg::INFO)  << "face normals " << obj->numfacetnorms << endl;
    osg::notify(osg::INFO)  << "tris " << obj->numtriangles << endl;
    osg::notify(osg::INFO)  << "materials " << obj->nummaterials << endl;
    osg::notify(osg::INFO)  << "groups " << obj->numgroups << endl;

    if (obj->numnormals==0)
    {
        osg::notify(osg::NOTICE)  << "No normals in .obj file, automatically calculating normals..."<<endl;
        glmFacetNormals(obj);
        glmVertexNormals(obj,90.0f);
    }

    unsigned int i;

    // materials
    osg::StateSet** osg_mtl = NULL;
    if (obj->nummaterials > 0) {
        osg_mtl = new osg::StateSet*[obj->nummaterials];
        for (i = 0; i < obj->nummaterials; i++) {
            GLMmaterial* omtl = &(obj->materials[i]);
            osg::notify(DEBUG) << "mtl: " << omtl->name << endl;

            osg::StateSet* stateset = new osg::StateSet;
            osg_mtl[i] = stateset;

            osg::Material* mtl = new osg::Material;
            mtl->setAmbient(osg::Material::FRONT_AND_BACK,
                            osg::Vec4(omtl->ambient[0], omtl->ambient[1],
                                      omtl->ambient[2], omtl->ambient[3]));
            mtl->setDiffuse(osg::Material::FRONT_AND_BACK,
                            osg::Vec4(omtl->diffuse[0], omtl->diffuse[1],
                                      omtl->diffuse[2], omtl->diffuse[3]));
            mtl->setSpecular(osg::Material::FRONT_AND_BACK,
                             osg::Vec4(omtl->specular[0], omtl->specular[1],
                                       omtl->specular[2], omtl->specular[3]));
            mtl->setEmission(osg::Material::FRONT_AND_BACK,
                             osg::Vec4(omtl->emmissive[0], omtl->emmissive[1],
                                       omtl->emmissive[2], omtl->emmissive[3]));
            // note, osg shininess scales between 0.0 and 1.0.
            mtl->setShininess(osg::Material::FRONT_AND_BACK, omtl->shininess/128.0f);

            stateset->setAttribute(mtl);

            if (omtl->textureName)
            {
                std::string fileName = osgDB::findFileInDirectory(omtl->textureName,directory,true);
                if (!fileName.empty())
                {

                    osg::Image* osg_image = osgDB::readImageFile(fileName.c_str());
                    if (osg_image)
                    {
                        osg::Texture* osg_texture = new osg::Texture;
                        osg_texture->setImage(osg_image);
                        stateset->setAttributeAndModes(osg_texture,osg::StateAttribute::ON);

                        if (omtl->textureReflection)
                        {
                            osg::TexGen* osg_texgen = new osg::TexGen;
                            osg_texgen->setMode(osg::TexGen::SPHERE_MAP);
                            stateset->setAttributeAndModes(osg_texgen,osg::StateAttribute::ON);
                        }
                    }
                    else
                    {
                        osg::notify(osg::NOTICE) << "Warning: Cannot create texture "<<omtl->textureName<<endl;
                    }
                }
                else
                {
                    osg::notify(osg::WARN) << "texture '"<<omtl->textureName<<"' not found"<<endl;
                }
            }
        }
    }

    // toplevel group or transform
    osg::Group* osg_top = NULL;
    if (obj->position[0] != 0.0f || obj->position[2] != 0.0f || obj->position[2] != 0.0f) {
        osg::Transform* xform = new osg::Transform;
		// note obj_x -> osg_x,
		//      obj_y -> osg_z,
		//      obj_z -> osg_y,
        xform->setMatrix(osg::Matrix::trans(obj->position[0], obj->position[2], obj->position[1]));
        osg_top = xform;
    }
    else
        osg_top = new osg::Group;

    osg_top->setName(obj->pathname);

    // subgroups
    // XXX one Geode per group is probably not necessary...
    GLMgroup* ogrp = obj->groups;
    while (ogrp) {
        if (ogrp->numtriangles > 0) {

            osg::Geode* osg_geo = new osg::Geode;
            osg_geo->setName(ogrp->name);
            osg_geo->addDrawable(makeDrawable(obj,ogrp, osg_mtl));
            osg_top->addChild(osg_geo);
        }
        ogrp = ogrp->next;
    }

    // free
    glmDelete(obj);
    if (osg_mtl)
        delete[] osg_mtl;

    return osg_top;
}

// make drawable from OBJ group
osg::Drawable* ReaderWriterOBJ::makeDrawable(GLMmodel* obj,
                                             GLMgroup* grp,
                                             osg::StateSet** mtl)
{

    GLMtriangle* tris = obj->triangles;

    unsigned int ntris = grp->numtriangles;
    unsigned int i = 0;

    // geoset
    osg::GeoSet* gset = new osg::GeoSet;

    // primitives are only triangles
    gset->setPrimType(osg::GeoSet::TRIANGLES);
    gset->setNumPrims(ntris);
    int* primLen = new int[ntris];
    gset->setPrimLengths(primLen);

    // the following code for mapping the coords, normals and texcoords
    // is complicated greatly by the need to create seperate out the
    // sets of coords etc for each drawable.

    typedef std::vector<int> IndexVec;

    // fill an vector full of 0's, one for each vertex.
    IndexVec vcount(obj->numvertices+1,0);
    IndexVec ncount(obj->numnormals+1,0);
    IndexVec tcount(obj->numtexcoords+1,0);

    bool needNormals = obj->normals && obj->normals>0;
    bool needTexcoords = obj->texcoords && obj->numtexcoords>0;

    // first count the number of vertices used in this group.
    for (i = 0; i < ntris; i++)
    {
        GLMtriangle* tri = &(tris[grp->triangles[i]]);

        // increment the count once for each traingle corner.
        ++vcount[tri->vindices[0]];
        ++vcount[tri->vindices[1]];
        ++vcount[tri->vindices[2]];

        if (needNormals)
        {
            ++ncount[tri->nindices[0]];
            ++ncount[tri->nindices[1]];
            ++ncount[tri->nindices[2]];
        }

        if (needTexcoords)
        {
            ++tcount[tri->tindices[0]];
            ++tcount[tri->tindices[1]];
            ++tcount[tri->tindices[2]];
        }
    }

    IndexVec::iterator itr;
    int numCoords = 0;
    for(itr=vcount.begin();
        itr!=vcount.end();
        ++itr)
    {
        if ((*itr)>0) ++numCoords;
    }

    if (numCoords==0) return NULL;

    int numNormals = 0;
    for(itr=ncount.begin();
        itr!=ncount.end();
        ++itr)
    {
        if ((*itr)>0) ++numNormals;
    }

    int numTexcoords = 0;
    for(itr=tcount.begin();
        itr!=tcount.end();
        ++itr)
    {
        if ((*itr)>0) ++numTexcoords;
    }

    // allocate drawables vertices.
    osg::Vec3* coords = new osg::Vec3[numCoords];

    // allocate drawables normals.
    osg::Vec3* normals = NULL;
    if (numNormals>0) normals = new osg::Vec3[numNormals];

    // allocate drawables textcoords.
    osg::Vec2* texcoords = NULL;
    if (numTexcoords>0) texcoords = new osg::Vec2[numTexcoords];

    // fill an vector full of 0's, one for each vertex.
    IndexVec vmapping(obj->numvertices+1,-1);
    IndexVec nmapping(obj->numnormals+1,-1);
    IndexVec tmapping(obj->numtexcoords+1,-1);

    int coordCount = 0;
    for (i = 0; i < vcount.size(); i++)
    {

        if (vcount[i]>0)
        {

            // note obj_x -> osg_x,
            //      obj_y -> -osg_z,
            //      obj_z -> osg_y,
            coords[coordCount].set(obj->vertices[i*3+0],
                                   -obj->vertices[i*3+2],
                                   obj->vertices[i*3+1]);

            vmapping[i]=coordCount;
            ++coordCount;
        }
    }

    int normCount = 0;
    for (i = 0; i < ncount.size(); i++)
    {

        if (ncount[i]>0)
        {
            // note obj_x -> osg_x,
            //      obj_y -> osg_z,
            //      obj_z -> osg_y,
            // to rotate the about x axis to have model z upwards.
            normals[normCount].set(obj->normals[i*3+0],
                                   -obj->normals[i*3+2],
                                   obj->normals[i*3+1]);
            nmapping[i]=normCount;
            ++normCount;
        }
    }

    int texCount = 0;
    for (i = 0; i < tcount.size(); i++)
    {
        if (tcount[i]>0)
        {
            texcoords[texCount].set(obj->texcoords[i*2+0], obj->texcoords[i*2+1]);
            tmapping[i]=texCount;
            ++texCount;
        }
    }

    // index arrays
    unsigned int* cindex = NULL;
    cindex = new unsigned int[ntris * 3];

    unsigned int* nindex = NULL;
    if (normals)
        nindex = new unsigned int[ntris * 3];

    unsigned int* tindex = NULL;
    if (texcoords)
        tindex = new unsigned int[ntris * 3];

    // setup arrays
    for (i = 0; i < ntris; i++) {
        primLen[i] = 3;
        GLMtriangle* tri = &(tris[grp->triangles[i]]);

        cindex[i*3+0] = vmapping[tri->vindices[0]];
        cindex[i*3+1] = vmapping[tri->vindices[1]];
        cindex[i*3+2] = vmapping[tri->vindices[2]];

        if (nindex) {
            nindex[i*3+0] = nmapping[tri->nindices[0]];
            nindex[i*3+1] = nmapping[tri->nindices[1]];
            nindex[i*3+2] = nmapping[tri->nindices[2]];
        }

        if (tindex) {
            tindex[i*3+0] = tmapping[tri->tindices[0]];
            tindex[i*3+1] = tmapping[tri->tindices[1]];
            tindex[i*3+2] = tmapping[tri->tindices[2]];
        }
    }

    if (coords && cindex)
        gset->setCoords(coords, cindex);

    if (normals && nindex) {
        gset->setNormals(normals, nindex);
        gset->setNormalBinding(osg::GeoSet::BIND_PERVERTEX);
    }

    if (texcoords && tindex) {
        gset->setTextureCoords(texcoords, tindex);
        gset->setTextureBinding(osg::GeoSet::BIND_PERVERTEX);
    }

    // state and material (if any)
    if (mtl) {

        gset->setStateSet(mtl[grp->material]);
    }
    else
        osg::notify(osg::INFO) << "Group " << grp->name << " has no material" << endl;

    return gset;
}

<|endoftext|>


<commit_before>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// GRINS - General Reacting Incompressible Navier-Stokes
//
// Copyright (C) 2014-2015 Paul T. Bauman, Roy H. Stogner
// Copyright (C) 2010-2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc. 51 Franklin Street, Fifth Floor,
// Boston, MA  02110-1301  USA
//
//-----------------------------------------------------------------------el-

// This class
#include "grins/convection_diffusion.h"

// GRINS
#include "grins/common.h"
#include "grins/assembly_context.h"
#include "grins/materials_parsing.h"
#include "grins/generic_bc_handling.h"
#include "grins/generic_ic_handler.h"

// libMesh
#include "libmesh/getpot.h"
#include "libmesh/string_to_enum.h"
#include "libmesh/quadrature.h"
#include "libmesh/fem_system.h"

namespace GRINS
{
  ConvectionDiffusion::ConvectionDiffusion( const GRINS::PhysicsName& physics_name,
                                            const GetPot& input )
    : Physics(physics_name,input),
      _v(3,libMesh::ParsedFunction<libMesh::Number>("0.0") ),
      _kappa("0.0"),
      _var(input,physics_name)
  {
    unsigned int n_v_comps = input.vector_variable_size("Physics/"+physics_name+"/velocity_field");

    for( unsigned int v = 0; v < n_v_comps; v++ )
      _v[v].reparse( input("Physics/"+physics_name+"/velocity_field", "0.0", v) );

    std::string material_name = MaterialsParsing::material_name(input,physics_name);

    this->set_parameter(this->_kappa, input,
                        "Materials/"+material_name+"/Diffusivity/value",
                        "DIE!");

    _bc_handler = new GenericBCHandling(physics_name,input);
    _ic_handler = new GenericICHandler(physics_name,input);
  }

  void ConvectionDiffusion::init_variables( libMesh::FEMSystem* system )
  {
    _var.init(system);
  }

  void ConvectionDiffusion::set_time_evolving_vars( libMesh::FEMSystem* system )
  {
    system->time_evolving(_var.var());
  }

  void ConvectionDiffusion::init_context( AssemblyContext& context )
  {
    context.get_element_fe(_var.var())->get_JxW();
    context.get_element_fe(_var.var())->get_phi();
    context.get_element_fe(_var.var())->get_dphi();
    context.get_element_fe(_var.var())->get_xyz();
  }

  void ConvectionDiffusion::element_time_derivative( bool compute_jacobian,
                                                     AssemblyContext& context,
                                                     CachedValues& /*cache*/ )
  {
    const unsigned int n_dofs = context.get_dof_indices(_var.var()).size();

    const std::vector<libMesh::Real> &JxW =
      context.get_element_fe(_var.var())->get_JxW();

    const std::vector<std::vector<libMesh::Real> >& phi =
      context.get_element_fe(_var.var())->get_phi();

    const std::vector<std::vector<libMesh::RealGradient> >& grad_phi =
      context.get_element_fe(_var.var())->get_dphi();

    const std::vector<libMesh::Point>& x =
      context.get_element_fe(_var.var())->get_xyz();

    libMesh::DenseSubVector<libMesh::Number> &F = context.get_elem_residual(_var.var());

    libMesh::DenseSubMatrix<libMesh::Number> &K = context.get_elem_jacobian(_var.var(), _var.var());

    unsigned int n_qpoints = context.get_element_qrule().n_points();

    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
        libMesh::Number c = context.interior_value(_var.var(), qp);

        libMesh::Gradient grad_c;
	context.interior_gradient(_var.var(), qp, grad_c);

        libMesh::RealGradient v_qp;
        v_qp(0) = this->_v[0](x[qp], context.get_time());
        v_qp(1) = this->_v[1](x[qp], context.get_time());
        v_qp(2) = this->_v[2](x[qp], context.get_time());

        libMesh::Real kappa_qp = this->_kappa(x[qp], context.time);

        for (unsigned int i=0; i != n_dofs; i++)
	  {
            F(i) += JxW[qp]*( c*(v_qp*grad_phi[i][qp])
                              - kappa_qp*(grad_c*grad_phi[i][qp]) );

            if (compute_jacobian)
	      {
		for (unsigned int j=0; j != n_dofs; j++)
		  {
                    K(i,j) += context.get_elem_solution_derivative()*
                              JxW[qp]*( phi[j][qp]*(v_qp*grad_phi[i][qp])
                                      - kappa_qp*(grad_phi[j][qp]*grad_phi[i][qp]) );
                  }
              }
          }
      }
  }

  void ConvectionDiffusion::mass_residual( bool compute_jacobian,
                                           AssemblyContext& context,
                                           CachedValues& /*cache*/ )
  {
    const unsigned int n_dofs = context.get_dof_indices(_var.var()).size();

    const std::vector<libMesh::Real> &JxW =
      context.get_element_fe(_var.var())->get_JxW();

    const std::vector<std::vector<libMesh::Real> >& phi =
      context.get_element_fe(_var.var())->get_phi();

    libMesh::DenseSubVector<libMesh::Number> &F = context.get_elem_residual(_var.var());

    libMesh::DenseSubMatrix<libMesh::Number> &M = context.get_elem_jacobian(_var.var(), _var.var());

    unsigned int n_qpoints = context.get_element_qrule().n_points();

    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
        libMesh::Real c_dot;
        context.interior_rate(_var.var(), qp, c_dot);

        for (unsigned int i=0; i != n_dofs; i++)
	  {
            F(i) -= JxW[qp]*( c_dot*phi[i][qp] );

            if (compute_jacobian)
	      {
		for (unsigned int j=0; j != n_dofs; j++)
		  {
                    M(i,j) -=
                      context.get_elem_solution_rate_derivative()*
                      JxW[qp]*( phi[j][qp]*phi[i][qp] );
                  }
              }
          }
      }
  }

} // end namespace GRINS
<commit_msg>Register variable in ConvectionDiffusion Physics<commit_after>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// GRINS - General Reacting Incompressible Navier-Stokes
//
// Copyright (C) 2014-2015 Paul T. Bauman, Roy H. Stogner
// Copyright (C) 2010-2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc. 51 Franklin Street, Fifth Floor,
// Boston, MA  02110-1301  USA
//
//-----------------------------------------------------------------------el-

// This class
#include "grins/convection_diffusion.h"

// GRINS
#include "grins/common.h"
#include "grins/assembly_context.h"
#include "grins/materials_parsing.h"
#include "grins/generic_bc_handling.h"
#include "grins/generic_ic_handler.h"
#include "grins/variable_warehouse.h"

// libMesh
#include "libmesh/getpot.h"
#include "libmesh/string_to_enum.h"
#include "libmesh/quadrature.h"
#include "libmesh/fem_system.h"

namespace GRINS
{
  ConvectionDiffusion::ConvectionDiffusion( const GRINS::PhysicsName& physics_name,
                                            const GetPot& input )
    : Physics(physics_name,input),
      _v(3,libMesh::ParsedFunction<libMesh::Number>("0.0") ),
      _kappa("0.0"),
      _var(input,physics_name)
  {
    unsigned int n_v_comps = input.vector_variable_size("Physics/"+physics_name+"/velocity_field");

    for( unsigned int v = 0; v < n_v_comps; v++ )
      _v[v].reparse( input("Physics/"+physics_name+"/velocity_field", "0.0", v) );

    std::string material_name = MaterialsParsing::material_name(input,physics_name);

    this->set_parameter(this->_kappa, input,
                        "Materials/"+material_name+"/Diffusivity/value",
                        "DIE!");

    GRINSPrivate::VariableWarehouse::check_and_register_variable(this->_var.section_name(physics_name), this->_var);

    _bc_handler = new GenericBCHandling(physics_name,input);
    _ic_handler = new GenericICHandler(physics_name,input);
  }

  void ConvectionDiffusion::init_variables( libMesh::FEMSystem* system )
  {
    _var.init(system);
  }

  void ConvectionDiffusion::set_time_evolving_vars( libMesh::FEMSystem* system )
  {
    system->time_evolving(_var.var());
  }

  void ConvectionDiffusion::init_context( AssemblyContext& context )
  {
    context.get_element_fe(_var.var())->get_JxW();
    context.get_element_fe(_var.var())->get_phi();
    context.get_element_fe(_var.var())->get_dphi();
    context.get_element_fe(_var.var())->get_xyz();
  }

  void ConvectionDiffusion::element_time_derivative( bool compute_jacobian,
                                                     AssemblyContext& context,
                                                     CachedValues& /*cache*/ )
  {
    const unsigned int n_dofs = context.get_dof_indices(_var.var()).size();

    const std::vector<libMesh::Real> &JxW =
      context.get_element_fe(_var.var())->get_JxW();

    const std::vector<std::vector<libMesh::Real> >& phi =
      context.get_element_fe(_var.var())->get_phi();

    const std::vector<std::vector<libMesh::RealGradient> >& grad_phi =
      context.get_element_fe(_var.var())->get_dphi();

    const std::vector<libMesh::Point>& x =
      context.get_element_fe(_var.var())->get_xyz();

    libMesh::DenseSubVector<libMesh::Number> &F = context.get_elem_residual(_var.var());

    libMesh::DenseSubMatrix<libMesh::Number> &K = context.get_elem_jacobian(_var.var(), _var.var());

    unsigned int n_qpoints = context.get_element_qrule().n_points();

    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
        libMesh::Number c = context.interior_value(_var.var(), qp);

        libMesh::Gradient grad_c;
	context.interior_gradient(_var.var(), qp, grad_c);

        libMesh::RealGradient v_qp;
        v_qp(0) = this->_v[0](x[qp], context.get_time());
        v_qp(1) = this->_v[1](x[qp], context.get_time());
        v_qp(2) = this->_v[2](x[qp], context.get_time());

        libMesh::Real kappa_qp = this->_kappa(x[qp], context.time);

        for (unsigned int i=0; i != n_dofs; i++)
	  {
            F(i) += JxW[qp]*( c*(v_qp*grad_phi[i][qp])
                              - kappa_qp*(grad_c*grad_phi[i][qp]) );

            if (compute_jacobian)
	      {
		for (unsigned int j=0; j != n_dofs; j++)
		  {
                    K(i,j) += context.get_elem_solution_derivative()*
                              JxW[qp]*( phi[j][qp]*(v_qp*grad_phi[i][qp])
                                      - kappa_qp*(grad_phi[j][qp]*grad_phi[i][qp]) );
                  }
              }
          }
      }
  }

  void ConvectionDiffusion::mass_residual( bool compute_jacobian,
                                           AssemblyContext& context,
                                           CachedValues& /*cache*/ )
  {
    const unsigned int n_dofs = context.get_dof_indices(_var.var()).size();

    const std::vector<libMesh::Real> &JxW =
      context.get_element_fe(_var.var())->get_JxW();

    const std::vector<std::vector<libMesh::Real> >& phi =
      context.get_element_fe(_var.var())->get_phi();

    libMesh::DenseSubVector<libMesh::Number> &F = context.get_elem_residual(_var.var());

    libMesh::DenseSubMatrix<libMesh::Number> &M = context.get_elem_jacobian(_var.var(), _var.var());

    unsigned int n_qpoints = context.get_element_qrule().n_points();

    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
        libMesh::Real c_dot;
        context.interior_rate(_var.var(), qp, c_dot);

        for (unsigned int i=0; i != n_dofs; i++)
	  {
            F(i) -= JxW[qp]*( c_dot*phi[i][qp] );

            if (compute_jacobian)
	      {
		for (unsigned int j=0; j != n_dofs; j++)
		  {
                    M(i,j) -=
                      context.get_elem_solution_rate_derivative()*
                      JxW[qp]*( phi[j][qp]*phi[i][qp] );
                  }
              }
          }
      }
  }

} // end namespace GRINS
<|endoftext|>


<commit_before>#include <faunus/faunus.h>

/**
 * @brief  Constant-pH, NVT, MC simulation of a peptide in bulk or in a slit
 *         (charged and/or hydrophobic  surface). Implicit salt.
 *
 * @author Joao Henriques
 * @date   2013/11/22
 */

using namespace Faunus;

#ifdef SLIT
typedef Space<Geometry::Cuboidslit> Tspace;
typedef Potential::GouyChapman<> Textpot1;
typedef Potential::HydrophobicWall<> Textpot2;
#else
typedef Space<Geometry::Cuboid> Tspace;
#endif

typedef Potential::CombinedPairPotential<Potential::DebyeHuckel,
                                         Potential::LennardJonesR12>
                                         Tpairpot1;

typedef Potential::CombinedPairPotential<Tpairpot1,
                                         Potential::SquareWellHydrophobic>
                                         Tpairpot2;

int main() {
  cout << textio::splash();
  ::atom.includefile("param.json");
  InputMap mcp("simulation.input");
  EnergyDrift sys;
  Tspace spc(mcp);

#ifdef SLIT
  auto pot = Energy::Nonbonded<Tspace, Tpairpot2>(mcp)
           + Energy::ExternalPotential<Tspace, Textpot1>(mcp)
           + Energy::ExternalPotential<Tspace, Textpot2>(mcp)
           + Energy::MassCenterRestrain<Tspace>(mcp)
           + Energy::EquilibriumEnergy<Tspace>(mcp)
           + Energy::Bonded<Tspace>();
  pot.first.first.first.first.second.expot.setSurfPositionZ(&spc.geo.len_half.z());
  pot.first.first.first.second.expot.setSurfPositionZ(&spc.geo.len_half.z());
#else
  auto pot = Energy::Nonbonded<Tspace, Tpairpot2>(mcp)
           + Energy::MassCenterRestrain<Tspace>(mcp)
           + Energy::EquilibriumEnergy<Tspace>(mcp)
           + Energy::Bonded<Tspace>();
#endif
  auto bonded    = &pot.second;
  auto restraint = &pot.first.first.second;

  string file = mcp.get<string>("molecule", "");
  double req  = mcp.get<double>("harmonic_eqdist", 0);
  double k    = mcp.get<double>("harmonic_forceconst", 0);

  Tspace::ParticleVector v;
  FormatAAM::load(file, v);
  Geometry::FindSpace().find(spc.geo, spc.p, v);
  Group pol = spc.insert(v);
  pol.name  = "peptide";
  spc.enroll(pol);
  for (int i = pol.front(); i < pol.back(); i++)
    bonded->add(i, i + 1, Potential::Harmonic(k, req)
		        + Potential::LennardJonesR12(mcp, "r12repex"));

  restraint->add(pol);

  double midpoint;
  double min = mcp.get<double>("bin_min", 0);
  double max = mcp.get<double>("bin_max", pc::infty);
  if (max == pc::infty)
    midpoint = 0;
  else
    midpoint = (min + max - spc.geo.len.z()) / 2;
  Point pt;
  pt.x() = 0;
  pt.y() = 0;
  pt.z() = midpoint;
  Point mc = Geometry::massCenter(spc.geo, spc.p, pol);
  pol.translate(spc, - mc + pt);
  pol.accept(spc);

  FormatGRO gro;
  gro.len=spc.geo.len.x();

  Move::AtomicTranslation<Tspace> mv(mcp, pot, spc);
  Move::TranslateRotate<Tspace> gmv(mcp, pot, spc);
  Move::CrankShaft<Tspace> crank(mcp, pot, spc);
  Move::Pivot<Tspace> pivot(mcp, pot, spc);
  Move::SwapMove<Tspace> tit(mcp, pot, spc, pot.first.second);

  Analysis::PolymerShape shape;
  std::map<string, Average<double> > Rg2;
  Analysis::ChargeMultipole mp;
#ifdef SLIT
  Analysis::LineDistribution<> surfmcdist;
  std::map<int, Analysis::LineDistribution<> > surfresdist;
  Analysis::Table2D<double, Average<double> > netqtable;
  Analysis::Table2D<double, Average<double> > rg2table;
#endif

  spc.load("simulation.state");
  sys.init(Energy::systemEnergy(spc, pot, spc.p));

  int cnt = 0;
  for (auto &i : spc.p)
    if (i.hydrophobic)
      cnt++;
  cout << "\nNumber of hydrophobic sites = " << cnt << endl;

  cout << atom.info()
       << pol.info()
       << spc.info()
       << pot.info()
       << sys.info()
       << textio::header("The right man in the wrong place can make all the difference in the world.\n"
			 "  So, wake up, Mister Freeman. Wake up and smell the ashes.");

  std::ofstream f1("rg_step.dat");
  std::ofstream f2("surf_res_dist.dat");

  MCLoop loop(mcp);
  while (loop.macroCnt()) {
    while (loop.microCnt()) {
      int i = slp_global.rand() % 5;
      switch (i) {
      case 0:
  	mv.setGroup(pol);
  	sys += mv.move();
  	break;
      case 1:
  	gmv.setGroup(pol);
  	sys += gmv.move();
  	break;
      case 2:
  	crank.setGroup(pol);
  	sys += crank.move();
  	break;
      case 3:
	pivot.setGroup(pol);
	sys += pivot.move();
	break;
      case 4:
	sys += tit.move();
	mp.sample(pol,spc);
      }

      double rnd = slp_global();
      if (rnd < 0.05) {
	shape.sample(pol, spc);
	Point r2 = shape.vectorgyrationRadiusSquared(pol, spc);
	double rg2 = r2.x()+r2.y()+r2.z();
	Rg2[pol.name] += rg2;
      }

#ifdef SLIT
      if (rnd < 0.05) {
	Point mc = Geometry::massCenter(spc.geo, spc.p, pol);                // mass center coord
	double dist = pot.first.first.first.first.second.expot.surfDist(mc); // mc dist to surf
	surfmcdist(dist)++;                                                  // mass center prob distr along the z axis
	netqtable(dist) += pol.charge(spc.p);                                // net charge vs. dist to surf
	Point rg2 = shape.vectorgyrationRadiusSquared(pol, spc);             // Rg2 coord
	rg2table(dist) += rg2.x() + rg2.y() + rg2.z();                       // Rg2 vs. dist to surf
	for (int i = pol.front(); i <= pol.back(); i++) {
	  // res dist to surf
	  double resdist = spc.geo.len.z()/2 - spc.p[i].z();
	  // res prob distr along the z axis
	  surfresdist[i](resdist)++;
	}
      }
#endif

    } // End of micro loop

    sys.checkDrift(Energy::systemEnergy(spc, pot, spc.p));
    cout << loop.timing();

    for (auto &m : Rg2)
      f1 << loop.count() << " " << sqrt(m.second.avg()) << "\n";

#ifdef SLIT
    netqtable.save("netq_dist.dat");
    rg2table.save("rg2_dist.dat");
#endif

    gro.save("simulation.gro", spc.p, "append");

  } // End of macro loop

  FormatPQR::save("simulation.pqr", spc.p, spc.geo.len);
  spc.save("simulation.state");

#ifdef SLIT
  surfmcdist.save("surf_mc_dist.dat");
  for (double d = 0; d <= spc.geo.len.z(); d += 0.25) {
    for (int i = pol.front(); i <= pol.back(); i++)
      f2 << d << " " << i + 1 << " " << -log(surfresdist[i](d)) << endl;
    f2 << endl;
  }
#endif

  f1.close();
  f2.close();

  cout << sys.info()
       << mv.info()
       << gmv.info()
       << pivot.info()
       << crank.info()
       << tit.info()
       << mp.info()
       << shape.info()
       << loop.info();
}
<commit_msg>Another change in peptide.cpp<commit_after>#include <faunus/faunus.h>

/**
 * @brief  Constant-pH, NVT, MC simulation of a peptide in bulk or in a slit
 *         (charged and/or hydrophobic  surface). Implicit salt.
 *
 * @author Joao Henriques
 * @date   2013/11/24
 */

using namespace Faunus;

#ifdef SLIT
typedef Space<Geometry::Cuboidslit> Tspace;
typedef Potential::GouyChapman<> Textpot1;
typedef Potential::HydrophobicWall<> Textpot2;
#else
typedef Space<Geometry::Cuboid> Tspace;
#endif

typedef Potential::CombinedPairPotential<Potential::DebyeHuckel,
                                         Potential::LennardJonesR12>
                                         Tpairpot1;

typedef Potential::CombinedPairPotential<Tpairpot1,
                                         Potential::SquareWellHydrophobic>
                                         Tpairpot2;

int main() {
  cout << textio::splash();
  ::atom.includefile("param.json");
  InputMap mcp("simulation.input");
  EnergyDrift sys;
  Tspace spc(mcp);

#ifdef SLIT
  auto pot = Energy::Nonbonded<Tspace, Tpairpot2>(mcp)
           + Energy::ExternalPotential<Tspace, Textpot1>(mcp)
           + Energy::ExternalPotential<Tspace, Textpot2>(mcp)
           + Energy::MassCenterRestrain<Tspace>(mcp)
           + Energy::EquilibriumEnergy<Tspace>(mcp)
           + Energy::Bonded<Tspace>();
  pot.first.first.first.first.second.expot.setSurfPositionZ(&spc.geo.len_half.z());
  pot.first.first.first.second.expot.setSurfPositionZ(&spc.geo.len_half.z());
#else
  auto pot = Energy::Nonbonded<Tspace, Tpairpot2>(mcp)
           + Energy::MassCenterRestrain<Tspace>(mcp)
           + Energy::EquilibriumEnergy<Tspace>(mcp)
           + Energy::Bonded<Tspace>();
#endif
  auto bonded    = &pot.second;
  auto restraint = &pot.first.first.second;

  string file = mcp.get<string>("molecule", "");
  double req  = mcp.get<double>("harmonic_eqdist", 0);
  double k    = mcp.get<double>("harmonic_forceconst", 0);

  Tspace::ParticleVector v;
  FormatAAM::load(file, v);
  Geometry::FindSpace().find(spc.geo, spc.p, v);
  Group pol = spc.insert(v);
  pol.name  = "peptide";
  spc.enroll(pol);
  for (int i = pol.front(); i < pol.back(); i++)
    bonded->add(i, i + 1, Potential::Harmonic(k, req)
		        + Potential::LennardJonesR12(mcp, "r12repex"));

  restraint->add(pol);

  double midpoint;
  double min = mcp.get<double>("bin_min", 0);
  double max = mcp.get<double>("bin_max", pc::infty);
  if (max == pc::infty)
    midpoint = 0;
  else
    midpoint = (min + max - spc.geo.len.z()) / 2;
  Point pt;
  pt.x() = 0;
  pt.y() = 0;
  pt.z() = midpoint;
  Point mc = Geometry::massCenter(spc.geo, spc.p, pol);
  pol.translate(spc, - mc + pt);
  pol.accept(spc);

  FormatGRO gro;
  gro.len=spc.geo.len.x();

  Move::AtomicTranslation<Tspace> mv(mcp, pot, spc);
  Move::TranslateRotate<Tspace> gmv(mcp, pot, spc);
  Move::CrankShaft<Tspace> crank(mcp, pot, spc);
  Move::Pivot<Tspace> pivot(mcp, pot, spc);
  Move::SwapMove<Tspace> tit(mcp, pot, spc, pot.first.second);

  Analysis::PolymerShape shape;
  Average<double> avrg2;
  Analysis::ChargeMultipole mp;
#ifdef SLIT
  Analysis::LineDistribution<> surfmcdist;
  int cntr = 0;
  std::map<int, Analysis::LineDistribution<> > surfresdist;
  Analysis::Table2D<double, Average<double> > netqtable;
  Analysis::Table2D<double, Average<double> > rg2table;
#endif

  spc.load("simulation.state");
  sys.init(Energy::systemEnergy(spc, pot, spc.p));

  int cnt = 0;
  for (auto &i : spc.p)
    if (i.hydrophobic)
      cnt++;
  cout << "\nNumber of hydrophobic sites = " << cnt << endl;

  cout << atom.info()
       << pol.info()
       << spc.info()
       << pot.info()
       << sys.info()
       << textio::header("The right man in the wrong place can make all the difference in the world.\n"
			 "  So, wake up, Mister Freeman. Wake up and smell the ashes.");

  std::ofstream f1("rg_step.dat");
  std::ofstream f2("surf_res_dist.dat");

  MCLoop loop(mcp);
  while (loop.macroCnt()) {
    while (loop.microCnt()) {
      int i = slp_global.rand() % 5;
      switch (i) {
      case 0:
  	mv.setGroup(pol);
  	sys += mv.move();
  	break;
      case 1:
  	gmv.setGroup(pol);
  	sys += gmv.move();
  	break;
      case 2:
  	crank.setGroup(pol);
  	sys += crank.move();
  	break;
      case 3:
	pivot.setGroup(pol);
	sys += pivot.move();
	break;
      case 4:
	sys += tit.move();
	mp.sample(pol,spc);
      }

      double rnd = slp_global();
      if (rnd < 0.05) {
	shape.sample(pol, spc);
	Point r2 = shape.vectorgyrationRadiusSquared(pol, spc);
	double rg2 = r2.x()+r2.y()+r2.z();
	avrg2 += rg2;
      }

#ifdef SLIT
      if (rnd < 0.05) {
	Point mc = Geometry::massCenter(spc.geo, spc.p, pol);                // mass center coord
	double dist = pot.first.first.first.first.second.expot.surfDist(mc); // mc dist to surf
	surfmcdist(dist)++;                                                  // mass center prob distr along the z axis
	netqtable(dist) += pol.charge(spc.p);                                // net charge vs. dist to surf
	Point rg2 = shape.vectorgyrationRadiusSquared(pol, spc);             // Rg2 coord
	rg2table(dist) += rg2.x() + rg2.y() + rg2.z();                       // Rg2 vs. dist to surf
	for (int i = pol.front(); i <= pol.back(); i++) {
	  // res dist to surf
	  double resdist = spc.geo.len.z()/2 - spc.p[i].z();
	  // res prob distr along the z axis
	  surfresdist[i](resdist)++;
	}
	cntr += 1;
      }
#endif

    } // End of micro loop

    sys.checkDrift(Energy::systemEnergy(spc, pot, spc.p));
    cout << loop.timing();

    f1 << loop.count() << " " << sqrt(avrg2.avg()) << "\n";

#ifdef SLIT
    netqtable.save("netq_dist.dat");
    rg2table.save("rg2_dist.dat");
#endif

    gro.save("simulation.gro", spc.p, "append");

  } // End of macro loop

  FormatPQR::save("simulation.pqr", spc.p, spc.geo.len);
  spc.save("simulation.state");

#ifdef SLIT
  surfmcdist.save("surf_mc_dist.dat");
  for (double d = 0; d <= spc.geo.len.z(); d += 0.25) {
    for (int i = pol.front(); i <= pol.back(); i++)
      f2 << d << " " << i + 1 << " " << -log(double(surfresdist[i](d))/double(cntr)) << endl;
    f2 << endl;
  }
#endif

  f1.close();
  f2.close();

  cout << sys.info()
       << mv.info()
       << gmv.info()
       << pivot.info()
       << crank.info()
       << tit.info()
       << mp.info()
       << shape.info()
       << loop.info();
}
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "target.h"

#include "buildconfiguration.h"
#include "project.h"
#include "runconfiguration.h"

#include <utils/qtcassert.h>

using namespace ProjectExplorer;

namespace {
const char * const ACTIVE_BC_KEY("ProjectExplorer.Target.ActiveBuildConfiguration");
const char * const BC_KEY_PREFIX("ProjectExplorer.Target.BuildConfiguration.");
const char * const BC_COUNT_KEY("ProjectExplorer.Target.BuildConfigurationCount");

const char * const ACTIVE_RC_KEY("ProjectExplorer.Target.ActiveRunConfiguration");
const char * const RC_KEY_PREFIX("ProjectExplorer.Target.RunConfiguration.");
const char * const RC_COUNT_KEY("ProjectExplorer.Target.RunConfigurationCount");

} // namespace

// -------------------------------------------------------------------------
// Target
// -------------------------------------------------------------------------

Target::Target(Project *project, const QString &id) :
    ProjectConfiguration(id),
    m_project(project),
    m_isEnabled(true),
    m_activeBuildConfiguration(0),
    m_activeRunConfiguration(0)
{
}

Target::~Target()
{
    qDeleteAll(m_buildConfigurations);
    qDeleteAll(m_runConfigurations);
}

void Target::changeEnvironment()
{
    ProjectExplorer::BuildConfiguration *bc(qobject_cast<ProjectExplorer::BuildConfiguration *>(sender()));
    if (bc == activeBuildConfiguration())
        emit environmentChanged();
}

Project *Target::project() const
{
    return m_project;
}

void Target::addBuildConfiguration(BuildConfiguration *configuration)
{
    QTC_ASSERT(configuration && !m_buildConfigurations.contains(configuration), return);
    Q_ASSERT(configuration->target() == this);

    if (!buildConfigurationFactory())
        return;

    // Check that we don't have a configuration with the same displayName
    QString configurationDisplayName = configuration->displayName();
    QStringList displayNames;
    foreach (const BuildConfiguration *bc, m_buildConfigurations)
        displayNames << bc->displayName();
    configurationDisplayName = Project::makeUnique(configurationDisplayName, displayNames);
    configuration->setDisplayName(configurationDisplayName);

    // add it
    m_buildConfigurations.push_back(configuration);

    emit addedBuildConfiguration(configuration);

    connect(configuration, SIGNAL(environmentChanged()),
            SLOT(changeEnvironment()));

    if (!activeBuildConfiguration())
        setActiveBuildConfiguration(configuration);
}

void Target::removeBuildConfiguration(BuildConfiguration *configuration)
{
    //todo: this might be error prone
    if (!m_buildConfigurations.contains(configuration))
        return;

    m_buildConfigurations.removeOne(configuration);

    emit removedBuildConfiguration(configuration);

    if (activeBuildConfiguration() == configuration) {
        if (m_buildConfigurations.isEmpty())
            setActiveBuildConfiguration(0);
        else
            setActiveBuildConfiguration(m_buildConfigurations.at(0));
    }

    delete configuration;
}

QList<BuildConfiguration *> Target::buildConfigurations() const
{
    return m_buildConfigurations;
}

BuildConfiguration *Target::activeBuildConfiguration() const
{
    return m_activeBuildConfiguration;
}

void Target::setActiveBuildConfiguration(BuildConfiguration *configuration)
{
    if ((!configuration && m_buildConfigurations.isEmpty()) ||
        (configuration && m_buildConfigurations.contains(configuration) &&
         configuration != m_activeBuildConfiguration)) {
        m_activeBuildConfiguration = configuration;
        emit activeBuildConfigurationChanged(m_activeBuildConfiguration);
        emit environmentChanged();
    }
}

QList<RunConfiguration *> Target::runConfigurations() const
{
    return m_runConfigurations;
}

void Target::addRunConfiguration(RunConfiguration* runConfiguration)
{
    QTC_ASSERT(runConfiguration && !m_runConfigurations.contains(runConfiguration), return);
    Q_ASSERT(runConfiguration->target() == this);

    m_runConfigurations.push_back(runConfiguration);
    emit addedRunConfiguration(runConfiguration);

    if (!activeRunConfiguration())
        setActiveRunConfiguration(runConfiguration);
}

void Target::removeRunConfiguration(RunConfiguration* runConfiguration)
{
    QTC_ASSERT(runConfiguration && m_runConfigurations.contains(runConfiguration), return);

    m_runConfigurations.removeOne(runConfiguration);

    if (activeRunConfiguration() == runConfiguration) {
        if (m_runConfigurations.isEmpty())
            setActiveRunConfiguration(0);
        else
            setActiveRunConfiguration(m_runConfigurations.at(0));
    }

    emit removedRunConfiguration(runConfiguration);
    delete runConfiguration;
}

RunConfiguration* Target::activeRunConfiguration() const
{
    return m_activeRunConfiguration;
}

void Target::setActiveRunConfiguration(RunConfiguration* configuration)
{
    if ((!configuration && !m_runConfigurations.isEmpty()) ||
        (configuration && m_runConfigurations.contains(configuration) &&
         configuration != m_activeRunConfiguration)) {
        m_activeRunConfiguration = configuration;
        emit activeRunConfigurationChanged(m_activeRunConfiguration);
    }
}

bool Target::isEnabled() const
{
    return m_isEnabled;
}

QIcon Target::icon() const
{
    return m_icon;
}

void Target::setIcon(QIcon icon)
{
    m_icon = icon;
    emit iconChanged();
}

QString Target::toolTip() const
{
    return m_toolTip;
}

void Target::setToolTip(const QString &text)
{
    m_toolTip = text;
    emit toolTipChanged();
}

QVariantMap Target::toMap() const
{
    const QList<BuildConfiguration *> bcs = buildConfigurations();

    QVariantMap map(ProjectConfiguration::toMap());
    map.insert(QLatin1String(ACTIVE_BC_KEY), bcs.indexOf(m_activeBuildConfiguration));
    map.insert(QLatin1String(BC_COUNT_KEY), bcs.size());
    for (int i = 0; i < bcs.size(); ++i)
        map.insert(QString::fromLatin1(BC_KEY_PREFIX) + QString::number(i), bcs.at(i)->toMap());

    const QList<RunConfiguration *> rcs = runConfigurations();
    map.insert(QLatin1String(ACTIVE_RC_KEY), rcs.indexOf(m_activeRunConfiguration));
    map.insert(QLatin1String(RC_COUNT_KEY), rcs.size());
    for (int i = 0; i < rcs.size(); ++i)
        map.insert(QString::fromLatin1(RC_KEY_PREFIX) + QString::number(i), rcs.at(i)->toMap());

    return map;
}

void Target::setEnabled(bool enabled)
{
    if (enabled == m_isEnabled)
        return;

    m_isEnabled = enabled;
    emit targetEnabled(m_isEnabled);
}

bool Target::fromMap(const QVariantMap &map)
{
    if (!ProjectConfiguration::fromMap(map))
        return false;

    bool ok;
    int bcCount(map.value(QLatin1String(BC_COUNT_KEY), 0).toInt(&ok));
    if (!ok || bcCount < 0)
        bcCount = 0;
    int activeConfiguration(map.value(QLatin1String(ACTIVE_BC_KEY), 0).toInt(&ok));
    if (!ok || activeConfiguration < 0)
        activeConfiguration = 0;
    if (0 > activeConfiguration || bcCount < activeConfiguration)
        activeConfiguration = 0;

    for (int i = 0; i < bcCount; ++i) {
        const QString key(QString::fromLatin1(BC_KEY_PREFIX) + QString::number(i));
        if (!map.contains(key))
            return false;
        BuildConfiguration *bc(buildConfigurationFactory()->restore(this, map.value(key).toMap()));
        if (!bc)
            continue;
        addBuildConfiguration(bc);
        if (i == activeConfiguration)
            setActiveBuildConfiguration(bc);
    }
    if (buildConfigurations().isEmpty())
        return false;

    int rcCount(map.value(QLatin1String(RC_COUNT_KEY), 0).toInt(&ok));
    if (!ok || rcCount < 0)
        rcCount = 0;
    activeConfiguration = map.value(QLatin1String(ACTIVE_RC_KEY), 0).toInt(&ok);
    if (!ok || activeConfiguration < 0)
        activeConfiguration = 0;
    if (0 > activeConfiguration || rcCount < activeConfiguration)
        activeConfiguration = 0;

    for (int i = 0; i < rcCount; ++i) {
        const QString key(QString::fromLatin1(RC_KEY_PREFIX) + QString::number(i));
        if (!map.contains(key))
            return false;

        QVariantMap valueMap(map.value(key).toMap());
        IRunConfigurationFactory *factory(IRunConfigurationFactory::restoreFactory(this, valueMap));
        if (!factory)
            continue; // Skip RCs we do not know about.)

        RunConfiguration *rc(factory->restore(this, valueMap));
        if (!rc)
            continue;
        addRunConfiguration(rc);
        if (i == activeConfiguration)
            setActiveRunConfiguration(rc);
    }
    // Ignore missing RCs: We will just populate them using the default ones.

    return true;
}

// -------------------------------------------------------------------------
// ITargetFactory
// -------------------------------------------------------------------------

ITargetFactory::ITargetFactory(QObject *parent) :
    QObject(parent)
{
}

ITargetFactory::~ITargetFactory()
{
}
<commit_msg>No BuildConfigurations is OK for certain projects<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "target.h"

#include "buildconfiguration.h"
#include "project.h"
#include "runconfiguration.h"

#include <utils/qtcassert.h>

using namespace ProjectExplorer;

namespace {
const char * const ACTIVE_BC_KEY("ProjectExplorer.Target.ActiveBuildConfiguration");
const char * const BC_KEY_PREFIX("ProjectExplorer.Target.BuildConfiguration.");
const char * const BC_COUNT_KEY("ProjectExplorer.Target.BuildConfigurationCount");

const char * const ACTIVE_RC_KEY("ProjectExplorer.Target.ActiveRunConfiguration");
const char * const RC_KEY_PREFIX("ProjectExplorer.Target.RunConfiguration.");
const char * const RC_COUNT_KEY("ProjectExplorer.Target.RunConfigurationCount");

} // namespace

// -------------------------------------------------------------------------
// Target
// -------------------------------------------------------------------------

Target::Target(Project *project, const QString &id) :
    ProjectConfiguration(id),
    m_project(project),
    m_isEnabled(true),
    m_activeBuildConfiguration(0),
    m_activeRunConfiguration(0)
{
}

Target::~Target()
{
    qDeleteAll(m_buildConfigurations);
    qDeleteAll(m_runConfigurations);
}

void Target::changeEnvironment()
{
    ProjectExplorer::BuildConfiguration *bc(qobject_cast<ProjectExplorer::BuildConfiguration *>(sender()));
    if (bc == activeBuildConfiguration())
        emit environmentChanged();
}

Project *Target::project() const
{
    return m_project;
}

void Target::addBuildConfiguration(BuildConfiguration *configuration)
{
    QTC_ASSERT(configuration && !m_buildConfigurations.contains(configuration), return);
    Q_ASSERT(configuration->target() == this);

    if (!buildConfigurationFactory())
        return;

    // Check that we don't have a configuration with the same displayName
    QString configurationDisplayName = configuration->displayName();
    QStringList displayNames;
    foreach (const BuildConfiguration *bc, m_buildConfigurations)
        displayNames << bc->displayName();
    configurationDisplayName = Project::makeUnique(configurationDisplayName, displayNames);
    configuration->setDisplayName(configurationDisplayName);

    // add it
    m_buildConfigurations.push_back(configuration);

    emit addedBuildConfiguration(configuration);

    connect(configuration, SIGNAL(environmentChanged()),
            SLOT(changeEnvironment()));

    if (!activeBuildConfiguration())
        setActiveBuildConfiguration(configuration);
}

void Target::removeBuildConfiguration(BuildConfiguration *configuration)
{
    //todo: this might be error prone
    if (!m_buildConfigurations.contains(configuration))
        return;

    m_buildConfigurations.removeOne(configuration);

    emit removedBuildConfiguration(configuration);

    if (activeBuildConfiguration() == configuration) {
        if (m_buildConfigurations.isEmpty())
            setActiveBuildConfiguration(0);
        else
            setActiveBuildConfiguration(m_buildConfigurations.at(0));
    }

    delete configuration;
}

QList<BuildConfiguration *> Target::buildConfigurations() const
{
    return m_buildConfigurations;
}

BuildConfiguration *Target::activeBuildConfiguration() const
{
    return m_activeBuildConfiguration;
}

void Target::setActiveBuildConfiguration(BuildConfiguration *configuration)
{
    if ((!configuration && m_buildConfigurations.isEmpty()) ||
        (configuration && m_buildConfigurations.contains(configuration) &&
         configuration != m_activeBuildConfiguration)) {
        m_activeBuildConfiguration = configuration;
        emit activeBuildConfigurationChanged(m_activeBuildConfiguration);
        emit environmentChanged();
    }
}

QList<RunConfiguration *> Target::runConfigurations() const
{
    return m_runConfigurations;
}

void Target::addRunConfiguration(RunConfiguration* runConfiguration)
{
    QTC_ASSERT(runConfiguration && !m_runConfigurations.contains(runConfiguration), return);
    Q_ASSERT(runConfiguration->target() == this);

    m_runConfigurations.push_back(runConfiguration);
    emit addedRunConfiguration(runConfiguration);

    if (!activeRunConfiguration())
        setActiveRunConfiguration(runConfiguration);
}

void Target::removeRunConfiguration(RunConfiguration* runConfiguration)
{
    QTC_ASSERT(runConfiguration && m_runConfigurations.contains(runConfiguration), return);

    m_runConfigurations.removeOne(runConfiguration);

    if (activeRunConfiguration() == runConfiguration) {
        if (m_runConfigurations.isEmpty())
            setActiveRunConfiguration(0);
        else
            setActiveRunConfiguration(m_runConfigurations.at(0));
    }

    emit removedRunConfiguration(runConfiguration);
    delete runConfiguration;
}

RunConfiguration* Target::activeRunConfiguration() const
{
    return m_activeRunConfiguration;
}

void Target::setActiveRunConfiguration(RunConfiguration* configuration)
{
    if ((!configuration && !m_runConfigurations.isEmpty()) ||
        (configuration && m_runConfigurations.contains(configuration) &&
         configuration != m_activeRunConfiguration)) {
        m_activeRunConfiguration = configuration;
        emit activeRunConfigurationChanged(m_activeRunConfiguration);
    }
}

bool Target::isEnabled() const
{
    return m_isEnabled;
}

QIcon Target::icon() const
{
    return m_icon;
}

void Target::setIcon(QIcon icon)
{
    m_icon = icon;
    emit iconChanged();
}

QString Target::toolTip() const
{
    return m_toolTip;
}

void Target::setToolTip(const QString &text)
{
    m_toolTip = text;
    emit toolTipChanged();
}

QVariantMap Target::toMap() const
{
    const QList<BuildConfiguration *> bcs = buildConfigurations();

    QVariantMap map(ProjectConfiguration::toMap());
    map.insert(QLatin1String(ACTIVE_BC_KEY), bcs.indexOf(m_activeBuildConfiguration));
    map.insert(QLatin1String(BC_COUNT_KEY), bcs.size());
    for (int i = 0; i < bcs.size(); ++i)
        map.insert(QString::fromLatin1(BC_KEY_PREFIX) + QString::number(i), bcs.at(i)->toMap());

    const QList<RunConfiguration *> rcs = runConfigurations();
    map.insert(QLatin1String(ACTIVE_RC_KEY), rcs.indexOf(m_activeRunConfiguration));
    map.insert(QLatin1String(RC_COUNT_KEY), rcs.size());
    for (int i = 0; i < rcs.size(); ++i)
        map.insert(QString::fromLatin1(RC_KEY_PREFIX) + QString::number(i), rcs.at(i)->toMap());

    return map;
}

void Target::setEnabled(bool enabled)
{
    if (enabled == m_isEnabled)
        return;

    m_isEnabled = enabled;
    emit targetEnabled(m_isEnabled);
}

bool Target::fromMap(const QVariantMap &map)
{
    if (!ProjectConfiguration::fromMap(map))
        return false;

    bool ok;
    int bcCount(map.value(QLatin1String(BC_COUNT_KEY), 0).toInt(&ok));
    if (!ok || bcCount < 0)
        bcCount = 0;
    int activeConfiguration(map.value(QLatin1String(ACTIVE_BC_KEY), 0).toInt(&ok));
    if (!ok || activeConfiguration < 0)
        activeConfiguration = 0;
    if (0 > activeConfiguration || bcCount < activeConfiguration)
        activeConfiguration = 0;

    for (int i = 0; i < bcCount; ++i) {
        const QString key(QString::fromLatin1(BC_KEY_PREFIX) + QString::number(i));
        if (!map.contains(key))
            return false;
        BuildConfiguration *bc(buildConfigurationFactory()->restore(this, map.value(key).toMap()));
        if (!bc)
            continue;
        addBuildConfiguration(bc);
        if (i == activeConfiguration)
            setActiveBuildConfiguration(bc);
    }
    if (buildConfigurations().isEmpty() && buildConfigurationFactory())
        return false;

    int rcCount(map.value(QLatin1String(RC_COUNT_KEY), 0).toInt(&ok));
    if (!ok || rcCount < 0)
        rcCount = 0;
    activeConfiguration = map.value(QLatin1String(ACTIVE_RC_KEY), 0).toInt(&ok);
    if (!ok || activeConfiguration < 0)
        activeConfiguration = 0;
    if (0 > activeConfiguration || rcCount < activeConfiguration)
        activeConfiguration = 0;

    for (int i = 0; i < rcCount; ++i) {
        const QString key(QString::fromLatin1(RC_KEY_PREFIX) + QString::number(i));
        if (!map.contains(key))
            return false;

        QVariantMap valueMap(map.value(key).toMap());
        IRunConfigurationFactory *factory(IRunConfigurationFactory::restoreFactory(this, valueMap));
        if (!factory)
            continue; // Skip RCs we do not know about.)

        RunConfiguration *rc(factory->restore(this, valueMap));
        if (!rc)
            continue;
        addRunConfiguration(rc);
        if (i == activeConfiguration)
            setActiveRunConfiguration(rc);
    }
    // Ignore missing RCs: We will just populate them using the default ones.

    return true;
}

// -------------------------------------------------------------------------
// ITargetFactory
// -------------------------------------------------------------------------

ITargetFactory::ITargetFactory(QObject *parent) :
    QObject(parent)
{
}

ITargetFactory::~ITargetFactory()
{
}
<|endoftext|>