Esempio n. 1
0
void Horizon3DNode2::updateGeometry()
{
    osgGeo::Vec2i fullSize = getSize();

    osg::DoubleArray &depthVals = *dynamic_cast<osg::DoubleArray*>(getDepthArray());

    double min = +999999.0;
    double max = -999999.0;
    for(int j = 0; j < fullSize.x(); ++j)
    {
        for(int i = 0; i < fullSize.y(); ++i)
        {
            const double val = depthVals.at(i * fullSize.y() + j);
            if(isUndef(val))
                continue;
            min = std::min(val, min);
            max = std::max(val, max);
        }
    }
    const double diff = max - min;

    std::vector<osg::Vec2d> coords = getCornerCoords();

    osg::Vec2d iInc = (coords[2] - coords[0]) / (fullSize.x() - 1);
    osg::Vec2d jInc = (coords[1] - coords[0]) / (fullSize.y() - 1);

    const osgGeo::Vec2i tileSize(255, 255);

    const int compr = 1;

    const int hSize = tileSize.x() + 1;
    const int vSize = tileSize.y() + 1;

    osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array(hSize * vSize);
    osg::ref_ptr<osg::DrawElementsUInt> indices =
            new osg::DrawElementsUInt(GL_TRIANGLES);
    osg::ref_ptr<osg::Vec2Array> tCoords = new osg::Vec2Array(hSize * vSize);

    osg::Vec2 texStart(0.0, 0.0);
    osg::Vec2 textureTileStep(1.0, 1.0);

    for(int i = 0; i < hSize; ++i)
    {
        for(int j = 0; j < vSize; ++j)
        {
            osg::Vec2d hor = iInc * i + jInc * j;
            (*vertices)[i*vSize+j] = osg::Vec3(hor.x(), hor.y(), 0);
            (*tCoords)[i*vSize+j] = texStart + osg::Vec2(
                        float(i) / (hSize - 1) * textureTileStep.x(),
                        float(j) / (vSize - 1) * textureTileStep.y()
                        );
        }
    }

    for(int i = 0; i < hSize - 1; ++i)
    {
        for(int j = 0; j < vSize - 1; ++j)
        {
            const int i00 = i*vSize+j;
            const int i10 = (i+1)*vSize+j;
            const int i01 = i*vSize+(j+1);
            const int i11 = (i+1)*vSize+(j+1);

            // first triangle
            indices->push_back(i00);
            indices->push_back(i10);
            indices->push_back(i01);

            // second triangle
            indices->push_back(i10);
            indices->push_back(i01);
            indices->push_back(i11);
        }
    }

    osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
    geom->setVertexArray(vertices.get());
    geom->setTexCoordArray(0, tCoords.get());
    geom->addPrimitiveSet(indices.get());

    osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
    colors->push_back(osg::Vec4(1.0f, 0.0f, 1.0f, 1.0f)); // needs to be white!

    geom->setColorArray(colors.get());
    geom->setColorBinding(osg::Geometry::BIND_OVERALL);

    // ------------- geom finished ----------------

    ShaderUtility su;
    su.addDefinition("hasGeomShader");
    osg::Program* programGeom = su.createProgram("horizon3d_vert.glsl", "horizon3d_frag.glsl",
                                                 "horizon3d_geom.glsl");
    ShaderUtility su2;
    osg::Program* programNonGeom = su2.createProgram("horizon3d_vert.glsl", "horizon3d_frag.glsl");

    int numHTiles = ceil(float(fullSize.x()) / tileSize.x());
    int numVTiles = ceil(float(fullSize.y()) / tileSize.y());

    for(int hIdx = 0; hIdx < numHTiles; ++hIdx)
    {
        for(int vIdx = 0; vIdx < numVTiles; ++vIdx)
        {
            const int hSize2 = hIdx < (numHTiles - 1) ?
                        (tileSize.x() + 1) : (fullSize.x() - tileSize.x() * (numHTiles - 1)) / compr;
            const int vSize2 = vIdx < (numVTiles - 1) ?
                        (tileSize.y() + 1) : ((fullSize.y() - tileSize.y() * (numVTiles - 1))) / compr;

            if(hSize2 == 1 || vSize2 == 1)
                continue;

            osg::ref_ptr<osg::Image> image = new osg::Image;
            image->allocateImage(vSize, hSize, 1, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE);
            image->setInternalTextureFormat(GL_LUMINANCE8_ALPHA8);

            unsigned short *ptr = reinterpret_cast<unsigned short*>(image->data());
            bool hasUndefs = false;
            for(int j = 0; j < vSize; ++j)
            {
                for(int i = 0; i < hSize; ++i)
                {
                    bool defined = false;
                    if((i < hSize2) && (j < vSize2))
                    {
                        int iGlobal = hIdx * tileSize.x() + i;
                        int jGlobal = vIdx * tileSize.y() + j;
                        double val = depthVals.at(iGlobal * fullSize.y() + jGlobal);
                        if(!isUndef(val))
                        {
                            *ptr = (val - min) / diff * UCHAR_MAX;
                            defined = true;
                        }
                    }
                    if(!defined)
                    {
                        *ptr = 0xFF00;
                        hasUndefs = true;
                    }
                    ptr++;
                }
            }

            const int i1 = hIdx * tileSize.x();
            const int j1 = vIdx * tileSize.y();
            const osg::Vec2d start = coords[0] + iInc * i1 + jInc * j1;
            const osg::Vec3 shift(start.x(), start.y(), 0);

            osg::ref_ptr<osg::Texture2D> heightMap = new osg::Texture2D;
            heightMap->setImage(image.get());

            osg::ref_ptr<osg::Vec3Array> triangleNormals =
                    new osg::Vec3Array((hSize - 1) * (vSize - 1) * 2);

            for(int i = 0; i < hSize - 1; ++i)
                for(int j = 0; j < vSize - 1; ++j)
                {
                    if((i < hSize2 - 1) && (j < vSize2 - 1))
                    {
                        int iGlobal = hIdx * tileSize.x() + i;
                        int jGlobal = vIdx * tileSize.y() + j;

                        const int i00 = i*vSize+j;
                        const int i10 = (i+1)*vSize+j;
                        const int i01 = i*vSize+(j+1);
                        const int i11 = (i+1)*vSize+(j+1);

                        osg::Vec3 v00 = (*vertices)[i00] + shift;
                        osg::Vec3 v10 = (*vertices)[i10] + shift;
                        osg::Vec3 v01 = (*vertices)[i01] + shift;
                        osg::Vec3 v11 = (*vertices)[i11] + shift;

                        const int i00_Global = iGlobal * fullSize.y() + jGlobal;
                        const int i10_Global = (iGlobal+1) * fullSize.y() + jGlobal;
                        const int i01_Global = iGlobal * fullSize.y() + (jGlobal+1);
                        const int i11_Global = (iGlobal+1) * fullSize.y() + (jGlobal+1);

                        v00.z() = depthVals.at(i00_Global);
                        v10.z() = depthVals.at(i10_Global);
                        v01.z() = depthVals.at(i01_Global);
                        v11.z() = depthVals.at(i11_Global);

                        if(isUndef(v10.z()) || isUndef(v01.z()))
                            continue;

                        // calculate triangle normals
                        osg::Vec3 norm1 = (v01 - v00) ^ (v10 - v00);
                        norm1.normalize();
                        (*triangleNormals)[(i*(vSize-1)+j)*2] = norm1;

                        osg::Vec3 norm2 = (v10 - v11) ^ (v01 - v11);
                        norm2.normalize();
                        (*triangleNormals)[(i*(vSize-1)+j)*2+1] = norm2;
                    }
                }

            osg::Image *normalsImage = new osg::Image();
            normalsImage->allocateImage(hSize, vSize, 1, GL_RGB, GL_UNSIGNED_BYTE);
            GLubyte *normPtr = (GLubyte*)normalsImage->data();

            // The following loop calculates normals per vertex. Because
            // each vertex might be shared between many triangles(up to 6)
            // we find out which triangles this particular vertex is shared
            // and then compute the average of normals per triangle.
            osg::Vec3 triNormCache[6];
            for(int j = 0; j < vSize; ++j)
            {
                for(int i = 0; i < hSize; ++i)
                {
                    if((i < hSize2) && (j < vSize2))
                    {
                        int k = 0;

                        const int vSizeT = vSize - 1;

                        // 3
                        if((i < hSize - 1) && (j < vSize - 1))
                        {
                            triNormCache[k++] = (*triangleNormals)[(i*vSizeT+j)*2];
                        }

                        // 4, 5
                        if(i > 0 && j < vSize - 1)
                        {
                            triNormCache[k++] = (*triangleNormals)[((i-1)*vSizeT+j)*2];
                            triNormCache[k++] = (*triangleNormals)[((i-1)*vSizeT+j)*2+1];
                        }

                        // 1, 2
                        if(j > 0 && i < hSize - 1)
                        {
                            triNormCache[k++] = (*triangleNormals)[(i*vSizeT+j-1)*2];
                            triNormCache[k++] = (*triangleNormals)[(i*vSizeT+j-1)*2+1];
                        }

                        // 6
                        if(i > 0 && j > 0)
                        {
                            triNormCache[k++] = (*triangleNormals)[((i-1)*vSizeT+j-1)*2+1];
                        }

                        if(k > 0)
                        {
                            osg::Vec3 norm;
                            for(int l = 0; l < k; ++l)
                                norm += triNormCache[l];

                            norm.normalize();

                            // scale [-1;1] to [0..255]
                            #define C_255_OVER_2 127.5
                            *(normPtr + 0) = GLubyte((norm.x() + 1.0) * C_255_OVER_2);
                            *(normPtr + 1) = GLubyte((norm.y() + 1.0) * C_255_OVER_2);
                            *(normPtr + 2) = GLubyte((norm.z() + 1.0) * C_255_OVER_2);
                        }
                    }
                    normPtr += 3;
                }
            }

            osg::ref_ptr<osg::Texture2D> normals = new osg::Texture2D;
            normals->setImage(normalsImage);

            osg::Geode* geode = new osg::Geode;
            geode->addDrawable(geom.get());

            // apply vertex shader to shift geometry
            osg::StateSet *ss = geode->getOrCreateStateSet();
            ss->addUniform(new osg::Uniform("colour", osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f)));
            ss->addUniform(new osg::Uniform("depthMin", float(min)));
            ss->addUniform(new osg::Uniform("depthDiff", float(diff)));
            ss->setTextureAttributeAndModes(1, heightMap.get());
            ss->setTextureAttributeAndModes(2, normals.get());
            ss->addUniform(new osg::Uniform("heightMap", 1));
            ss->addUniform(new osg::Uniform("normals", 2));

            const Palette p;
            const int sz = p.colorPoints().size();

            osg::Uniform *colourPoints = new osg::Uniform(osg::Uniform::FLOAT_VEC4, "colourPoints[0]", 20);
            for(int i = 0; i < sz; ++i)
            {
                osg::Vec3 colour = p.colorPoints().at(i).color;
                colourPoints->setElement(i, osg::Vec4(colour, 1.0));
            }
            ss->addUniform(colourPoints);
            osg::Uniform *colourPositions = new osg::Uniform(osg::Uniform::FLOAT, "colourPositions[0]", 20);
            for(int i = 0; i < sz; ++i)
            {
                colourPositions->setElement(i, p.colorPoints().at(i).pos);
            }
            ss->addUniform(colourPositions);
            ss->addUniform(new osg::Uniform("paletteSize", sz));

            ss->setAttributeAndModes(hasUndefs ? programGeom : programNonGeom, osg::StateAttribute::ON);

            osg::ref_ptr<Horizon3DTileNode2> transform = new Horizon3DTileNode2;
            transform->setMatrix(osg::Matrix::translate(osg::Vec3(start, 0)));
            transform->setNode(0, geode);

            // compute bounding box as our nodes don't have proper vertex information
            // and OSG can't deduce bounding sphere for culling
            osg::BoundingBox bb(osg::Vec3(start, min),
                                osg::Vec3(start + iInc * hSize2 + jInc * vSize2, max));
            transform->setBoundingSphere(bb);

            _nodes.push_back(transform);
        }
    }

    _needsUpdate = false;
}
Esempio n. 2
0
void check()
{
	char ch;
	int i,cur=0;
	ch=str[cur];
	while(ch!='\0')
	{
		char token[100];
		i=0;
		if(isalpha(ch)||ch=='_')
		{
			while(isalpha(ch)||isdigit(ch)||ch=='_')
			{
				append(token,ch,i);
				i++;
				cur++;
				ch=str[cur];
			}
			append(token,'\0',i);
			isKey(token);
		}
		else if(ispunct(ch))
		{
			if(ch=='<'||ch=='>'||ch=='=')
			{
				append(token,ch,i);
				i++;
				cur++; 
				ch=str[cur];
				if(ch=='=')
				{
					append(token,ch,i);
					i++;
					cur++;
					ch=str[cur];
					isRelop(token);
				}
				else
					isRelop(token);
			}
			else if(ch=='!')
			{
				append(token,ch,i);
				i++;
				cur++;
				ch=str[cur];
				if(ch=='=')
				{
					append(token,ch,i);
					i++;;
					cur++;
					ch=str[cur];
					isRelop(token);
				}
				else
					continue;
			}
			else if(ch=='('||ch==')'||ch=='{'||ch=='}'||ch=='['||ch==']')
			{
				isPar(ch);
				cur++;
				ch=str[cur];
			}
			else if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='%'||ch=='^')
			{
				isOp(ch);
				cur++;
				ch=str[cur];
				
			}
			else if(ch=='"')
			{
				while(ch!='"')
				{
					cur++;
					ch=str[cur];
				}
			}
			else if(ch==','||ch==';')
			{
				cur++;
				ch=str[cur];
			}
		}
		else if(strncmp(&ch," ",1)==0||ch=='\t'||ch=='\n')
		{
			while(strncmp(&ch," ",1)==0||ch=='\t'||ch=='\n')
			{
				cur++;
				ch=str[cur];
			}
		}
		else if(isdigit(ch))
		{
			append(token,ch,i);
			i++;
			cur++;
			ch=str[cur];
			while(isdigit(ch))
			{
				append(token,ch,i);
				i++;
				cur++;
				ch=str[cur];
			}
			printf("%s\t\tNumeric constant\n",token);
			if(ch=='.')
			{
				append(token,ch,i);
				i++;
				cur++;
				ch=str[cur];
				while(isdigit(ch))
				{
					append(token,ch,i);
					i++;
					cur++;
					ch=str[cur];
				}
				printf("%s\t\tNumeric constant\n",token);
			}
		}
		else
		{
			isUndef(ch);
			cur++;
			ch=str[cur];
		}
	}
			
}