Esempio n. 1
0
void TubeGenerator::generateCarbonTube(int n1, int n2, int k, float transition, float bondLength, std::vector<Molecule::Atom>& atoms, std::vector<Molecule::Link>& links)
{
    if (n1 < n2)
        std::swap(n1, n2);

    atoms.clear();
    links.clear();

    gameplay::Vector2 a1(1.7320508f, 0.0f);
    gameplay::Vector2 a2(-0.8660254f, 1.5f);

    gameplay::Vector2 R = (a1 * static_cast<float>(n1) + a2 * static_cast<float>(n2))* bondLength;
    gameplay::Vector2 L(-R.y, R.x);
    L.normalize();
    L.scale(k * bondLength);

    int ymin = -1;
    int ymax = static_cast<int>(ceilf(std::max(L.y, R.y) / bondLength)) + 1;
    int xmin = static_cast<int>(floorf(L.x / bondLength / a1.x)) - 1;
    int xmax = static_cast<int>(ceilf(R.x / bondLength / a1.x - a2.x * ymax)) + 1;

    std::map<std::tuple<int, int, int>, int> clippedAtoms;
    
    float Rlen = R.length();
    float Llen = L.length();
    float eps = 0.0001f;

    for (int y = ymin; y <= ymax; y++)
        for (int x = xmin; x <= xmax; x++)
        {
            // process hexagon atoms
            gameplay::Vector2 hexagonCenter(x * bondLength * a1.x + a2.x * y * bondLength, y * bondLength * a2.y);

            // process only two hexagon's atoms
            // these are unique to hexagon
            // the rest will be processed by other hexagons
            // each atom then can be uniquely defined by hexagon coordinates (x, y) and one index (0-1)
            for (int i = 0; i < 2; i++)
            {
                float phi = MATH_PI / 6.0f + MATH_PI / 3.0f * i;

                gameplay::Vector2 atomPosition(cosf(phi), sinf(phi));
                atomPosition = hexagonCenter + atomPosition * bondLength;

                // clip atoms by square defined by R and L vectors
                float u = gameplay::Vector2::dot(atomPosition, R) / Rlen;
                float v = gameplay::Vector2::dot(atomPosition, L) / Llen;

                if (u >= -eps && v >= -eps && u < Rlen - eps && v < Llen - eps)
                {
                    clippedAtoms.insert(std::make_pair(std::make_tuple(x, y, i), static_cast<int>(atoms.size())));
                    atoms.push_back({ 1, 0.0f, gameplay::Vector3(u, v, 0.0f) });
                    //atoms.push_back({ 1, 0.0f, gameplay::Vector3(atomPosition.x, atomPosition.y, 0.0f) });
                }
            }
        }

    std::vector<std::tuple<int, int, int>> unboundAtoms;

    // check links
    for (auto it = clippedAtoms.begin(), end_it = clippedAtoms.end(); it != end_it; it++)
    {
        int x = std::get<0>((*it).first);
        int y = std::get<1>((*it).first);

        if (std::get<2>((*it).first) == 0)
        {
            auto next = clippedAtoms.find(std::make_tuple(x, y, 1));
            if (next != clippedAtoms.end())
                links.push_back({ (*it).second, (*next).second, 1 });
            else
                unboundAtoms.push_back((*it).first);

            next = clippedAtoms.find(std::make_tuple(x, y - 1, 1));
            if (next != clippedAtoms.end())
                links.push_back({ (*it).second, (*next).second, 1 });
            else
                unboundAtoms.push_back((*it).first);

            next = clippedAtoms.find(std::make_tuple(x + 1, y, 1));
            if (next != clippedAtoms.end())
                links.push_back({ (*it).second, (*next).second, 1 });
            else
                unboundAtoms.push_back((*it).first);
        }
    }

    // bend graphene
    if (transition > 0.0f)
    {
        for (auto it = atoms.begin(), end_it = atoms.end(); it != end_it; it++)
        {
            float radius = R.length() / MATH_PIX2 / transition;
            float phi = (*it).pos.x / radius;
            (*it).pos.x = radius * sinf(phi);
            (*it).pos.z = radius * cosf(phi);
        }
    }

    // add new links
    //for (auto it = unboundAtoms.begin(), end_it = unboundAtoms.end(); it != end_it; it++)
    //{
    //    auto first = clippedAtoms.find(std::make_tuple(x, y, 0));
    //    if (first != clippedAtoms.end())
    //    {
    //        auto next = clippedAtoms.find(std::make_tuple(x, y, 1));
    //        if (next == clippedAtoms.end())
    //        {
    //            for (int x1 = xmax; x1 > x; x1--)
    //            {
    //                auto last = clippedAtoms.find(std::make_tuple(x1, y, 1));
    //                if (last != clippedAtoms.end())
    //                {
    //                    links.push_back({ (*first).second, (*last).second, 1 });
    //                    break;
    //                }
    //            }
    //        }

    //        next = clippedAtoms.find(std::make_tuple(x, y - 1, 1));
    //        if (next == clippedAtoms.end())
    //        {
    //            for (int x1 = xmin; x1 < x; x1++ )
    //            {
    //                auto last = clippedAtoms.find(std::make_tuple(x1, y - 1, 1));
    //                if (last != clippedAtoms.end())
    //                {
    //                    links.push_back({ (*first).second, (*last).second, 1 });
    //                    break;
    //                }
    //            }
    //        }

    //        next = clippedAtoms.find(std::make_tuple(x + 1, y, 1));
    //        if (next == clippedAtoms.end())
    //        {
    //            for (int x1 = xmin; x1 < x; x1++)
    //            {
    //                auto last = clippedAtoms.find(std::make_tuple(x1, y, 1));
    //                if (last != clippedAtoms.end())
    //                {
    //                    links.push_back({ (*first).second, (*last).second, 1 });
    //                    break;
    //                }
    //            }
    //        }
    //    }
    //}
}
Esempio n. 2
0
void
NotificationView::SetText(const char* app, const char* title, const char* text,
	float newMaxWidth)
{
	if (newMaxWidth < 0)
		newMaxWidth = Bounds().Width() - (kEdgePadding * 2);

	// Delete old lines
	LineInfoList::iterator lIt;
	for (lIt = fLines.begin(); lIt != fLines.end(); lIt++)
		delete (*lIt);
	fLines.clear();

	fApp = app;
	fTitle = title;
	fText = text;

	float iconRight = kEdgePadding + kEdgePadding;
	if (fBitmap != NULL)
		iconRight += fParent->IconSize();

	font_height fh;
	be_bold_font->GetHeight(&fh);
	float fontHeight = ceilf(fh.leading) + ceilf(fh.descent)
		+ ceilf(fh.ascent);
	float y = fontHeight;

	// Title
	LineInfo* titleLine = new LineInfo;
	titleLine->text = fTitle;
	titleLine->font = *be_bold_font;

	if (fParent->Layout() == AllTextRightOfIcon)
		titleLine->location = BPoint(iconRight, y);
	else
		titleLine->location = BPoint(kEdgePadding, y);

	fLines.push_front(titleLine);
	y += fontHeight;

	// Rest of text is rendered with be_plain_font.
	be_plain_font->GetHeight(&fh);
	fontHeight = ceilf(fh.leading) + ceilf(fh.descent)
		+ ceilf(fh.ascent);

	// Split text into chunks between certain characters and compose the lines.
	const char kSeparatorCharacters[] = " \n-\\/";
	BString textBuffer = fText;
	textBuffer.ReplaceAll("\t", "    ");
	const char* chunkStart = textBuffer.String();
	float maxWidth = newMaxWidth - kEdgePadding - iconRight;
	LineInfo* line = NULL;
	ssize_t length = textBuffer.Length();
	while (chunkStart - textBuffer.String() < length) {
		size_t chunkLength = strcspn(chunkStart, kSeparatorCharacters) + 1;

		// Start a new line if either we didn't start one before,
		// the current offset
		BString tempText;
		if (line != NULL)
			tempText.SetTo(line->text);
		tempText.Append(chunkStart, chunkLength);

		if (line == NULL || chunkStart[0] == '\n'
			|| StringWidth(tempText) > maxWidth) {
			line = new LineInfo;
			line->font = *be_plain_font;
			line->location = BPoint(iconRight + kEdgePadding, y);

			fLines.push_front(line);
			y += fontHeight;

			// Skip the eventual new-line character at the beginning of this
			// chunk.
			if (chunkStart[0] == '\n') {
				chunkStart++;
				chunkLength--;
			}
			// Skip more new-line characters and move the line further down.
			while (chunkStart[0] == '\n') {
				chunkStart++;
				chunkLength--;
				line->location.y += fontHeight;
				y += fontHeight;
			}
			// Strip space at beginning of a new line.
			while (chunkStart[0] == ' ') {
				chunkLength--;
				chunkStart++;
			}
		}

		if (chunkStart[0] == '\0')
			break;

		// Append the chunk to the current line, which was either a new
		// line or the one from the previous iteration.
		line->text.Append(chunkStart, chunkLength);

		chunkStart += chunkLength;
	}

	fHeight = y + (kEdgePadding * 2);

	// Make sure icon fits
	if (fBitmap != NULL) {
		float minHeight = 0;
		if (fParent->Layout() == TitleAboveIcon) {
			LineInfo* appLine = fLines.back();
			font_height fh;
			appLine->font.GetHeight(&fh);
			minHeight = appLine->location.y + fh.descent;
		}

		minHeight += fBitmap->Bounds().Height() + 2 * kEdgePadding;
		if (fHeight < minHeight)
			fHeight = minHeight;
	}

	BMessenger messenger(Parent());
	messenger.SendMessage(kResizeToFit);
}
unsigned char* Sample_TileMesh::buildTileMesh(const int tx, const int ty, const float* bmin, const float* bmax, int& dataSize)
{
	if (!m_geom || !m_geom->getMesh() || !m_geom->getChunkyMesh())
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Input mesh is not specified.");
		return 0;
	}
	
	m_tileMemUsage = 0;
	m_tileBuildTime = 0;
	
	cleanup();
	
	const float* verts = m_geom->getMesh()->getVerts();
	const int nverts = m_geom->getMesh()->getVertCount();
	const int ntris = m_geom->getMesh()->getTriCount();
	const rcChunkyTriMesh* chunkyMesh = m_geom->getChunkyMesh();
		
	// Init build configuration from GUI
	memset(&m_cfg, 0, sizeof(m_cfg));
	m_cfg.cs = m_cellSize;
	m_cfg.ch = m_cellHeight;
	m_cfg.walkableSlopeAngle = m_agentMaxSlope;
	m_cfg.walkableHeight = (int)ceilf(m_agentHeight / m_cfg.ch);
	m_cfg.walkableClimb = (int)floorf(m_agentMaxClimb / m_cfg.ch);
	m_cfg.walkableRadius = (int)ceilf(m_agentRadius / m_cfg.cs);
	m_cfg.maxEdgeLen = (int)(m_edgeMaxLen / m_cellSize);
	m_cfg.maxSimplificationError = m_edgeMaxError;
	m_cfg.minRegionArea = (int)rcSqr(m_regionMinSize);		// Note: area = size*size
	m_cfg.mergeRegionArea = (int)rcSqr(m_regionMergeSize);	// Note: area = size*size
	m_cfg.maxVertsPerPoly = (int)m_vertsPerPoly;
	m_cfg.tileSize = (int)m_tileSize;
	m_cfg.borderSize = m_cfg.walkableRadius + 3; // Reserve enough padding.
	m_cfg.width = m_cfg.tileSize + m_cfg.borderSize*2;
	m_cfg.height = m_cfg.tileSize + m_cfg.borderSize*2;
	m_cfg.detailSampleDist = m_detailSampleDist < 0.9f ? 0 : m_cellSize * m_detailSampleDist;
	m_cfg.detailSampleMaxError = m_cellHeight * m_detailSampleMaxError;
	
	// Expand the heighfield bounding box by border size to find the extents of geometry we need to build this tile.
	//
	// This is done in order to make sure that the navmesh tiles connect correctly at the borders,
	// and the obstacles close to the border work correctly with the dilation process.
	// No polygons (or contours) will be created on the border area.
	//
	// IMPORTANT!
	//
	//   :''''''''':
	//   : +-----+ :
	//   : |     | :
	//   : |     |<--- tile to build
	//   : |     | :  
	//   : +-----+ :<-- geometry needed
	//   :.........:
	//
	// You should use this bounding box to query your input geometry.
	//
	// For example if you build a navmesh for terrain, and want the navmesh tiles to match the terrain tile size
	// you will need to pass in data from neighbour terrain tiles too! In a simple case, just pass in all the 8 neighbours,
	// or use the bounding box below to only pass in a sliver of each of the 8 neighbours.
	rcVcopy(m_cfg.bmin, bmin);
	rcVcopy(m_cfg.bmax, bmax);
	m_cfg.bmin[0] -= m_cfg.borderSize*m_cfg.cs;
	m_cfg.bmin[2] -= m_cfg.borderSize*m_cfg.cs;
	m_cfg.bmax[0] += m_cfg.borderSize*m_cfg.cs;
	m_cfg.bmax[2] += m_cfg.borderSize*m_cfg.cs;
	
	// Reset build times gathering.
	m_ctx->resetTimers();
	
	// Start the build process.
	m_ctx->startTimer(RC_TIMER_TOTAL);
	
	m_ctx->log(RC_LOG_PROGRESS, "Building navigation:");
	m_ctx->log(RC_LOG_PROGRESS, " - %d x %d cells", m_cfg.width, m_cfg.height);
	m_ctx->log(RC_LOG_PROGRESS, " - %.1fK verts, %.1fK tris", nverts/1000.0f, ntris/1000.0f);
	
	// Allocate voxel heightfield where we rasterize our input data to.
	m_solid = rcAllocHeightfield();
	if (!m_solid)
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'solid'.");
		return 0;
	}
	if (!rcCreateHeightfield(m_ctx, *m_solid, m_cfg.width, m_cfg.height, m_cfg.bmin, m_cfg.bmax, m_cfg.cs, m_cfg.ch))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not create solid heightfield.");
		return 0;
	}
	
	// Allocate array that can hold triangle flags.
	// If you have multiple meshes you need to process, allocate
	// and array which can hold the max number of triangles you need to process.
	m_triareas = new AreaType[chunkyMesh->maxTrisPerChunk];
	if (!m_triareas)
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'm_triareas' (%d).", chunkyMesh->maxTrisPerChunk);
		return 0;
	}
	
	float tbmin[2], tbmax[2];
	tbmin[0] = m_cfg.bmin[0];
	tbmin[1] = m_cfg.bmin[2];
	tbmax[0] = m_cfg.bmax[0];
	tbmax[1] = m_cfg.bmax[2];
	int cid[512];// TODO: Make grow when returning too many items.
	const int ncid = rcGetChunksOverlappingRect(chunkyMesh, tbmin, tbmax, cid, 512);
	if (!ncid)
		return 0;
	
	m_tileTriCount = 0;
	
	for (int i = 0; i < ncid; ++i)
	{
		const rcChunkyTriMeshNode& node = chunkyMesh->nodes[cid[i]];
		const int* ctris = &chunkyMesh->tris[node.i*3];
		const int nctris = node.n;
		
		m_tileTriCount += nctris;
		
		memset(m_triareas, 0, nctris*sizeof(unsigned char));
		rcMarkWalkableTriangles(m_ctx, m_cfg.walkableSlopeAngle,
								verts, nverts, ctris, nctris, m_triareas);
		
		if (!rcRasterizeTriangles(m_ctx, verts, nverts, ctris, m_triareas, nctris, *m_solid, m_cfg.walkableClimb))
			return 0;
	}
	
	if (!m_keepInterResults)
	{
		delete [] m_triareas;
		m_triareas = 0;
	}
	
	// Once all geometry is rasterized, we do initial pass of filtering to
	// remove unwanted overhangs caused by the conservative rasterization
	// as well as filter spans where the character cannot possibly stand.
	rcFilterLowHangingWalkableObstacles(m_ctx, m_cfg.walkableClimb, *m_solid);
	rcFilterLedgeSpans(m_ctx, m_cfg.walkableHeight, m_cfg.walkableClimb, *m_solid);
	rcFilterWalkableLowHeightSpans(m_ctx, m_cfg.walkableHeight, *m_solid);
	
	// Compact the heightfield so that it is faster to handle from now on.
	// This will result more cache coherent data as well as the neighbours
	// between walkable cells will be calculated.
	m_chf = rcAllocCompactHeightfield();
	if (!m_chf)
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'chf'.");
		return 0;
	}
	if (!rcBuildCompactHeightfield(m_ctx, m_cfg.walkableHeight, m_cfg.walkableClimb, *m_solid, *m_chf))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build compact data.");
		return 0;
	}
	
	if (!m_keepInterResults)
	{
		rcFreeHeightField(m_solid);
		m_solid = 0;
	}

	// Erode the walkable area by agent radius.
	if (!rcErodeWalkableArea(m_ctx, m_cfg.walkableRadius, *m_chf))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not erode.");
		return 0;
	}

	// (Optional) Mark areas.
	const ConvexVolume* vols = m_geom->getConvexVolumes();
	for (int i  = 0; i < m_geom->getConvexVolumeCount(); ++i)
		rcMarkConvexPolyArea(m_ctx, vols[i].verts, vols[i].nverts, vols[i].hmin, vols[i].hmax, (unsigned char)vols[i].area, *m_chf);
	
	
	// Partition the heightfield so that we can use simple algorithm later to triangulate the walkable areas.
	// There are 3 martitioning methods, each with some pros and cons:
	// 1) Watershed partitioning
	//   - the classic Recast partitioning
	//   - creates the nicest tessellation
	//   - usually slowest
	//   - partitions the heightfield into nice regions without holes or overlaps
	//   - the are some corner cases where this method creates produces holes and overlaps
	//      - holes may appear when a small obstacles is close to large open area (triangulation can handle this)
	//      - overlaps may occur if you have narrow spiral corridors (i.e stairs), this make triangulation to fail
	//   * generally the best choice if you precompute the nacmesh, use this if you have large open areas
	// 2) Monotone partioning
	//   - fastest
	//   - partitions the heightfield into regions without holes and overlaps (guaranteed)
	//   - creates long thin polygons, which sometimes causes paths with detours
	//   * use this if you want fast navmesh generation
	// 3) Layer partitoining
	//   - quite fast
	//   - partitions the heighfield into non-overlapping regions
	//   - relies on the triangulation code to cope with holes (thus slower than monotone partitioning)
	//   - produces better triangles than monotone partitioning
	//   - does not have the corner cases of watershed partitioning
	//   - can be slow and create a bit ugly tessellation (still better than monotone)
	//     if you have large open areas with small obstacles (not a problem if you use tiles)
	//   * good choice to use for tiled navmesh with medium and small sized tiles
	
	if (m_partitionType == SAMPLE_PARTITION_WATERSHED)
	{
		// Prepare for region partitioning, by calculating distance field along the walkable surface.
		if (!rcBuildDistanceField(m_ctx, *m_chf))
		{
			m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build distance field.");
			return 0;
		}
		
		// Partition the walkable surface into simple regions without holes.
		if (!rcBuildRegions(m_ctx, *m_chf, m_cfg.borderSize, m_cfg.minRegionArea, m_cfg.mergeRegionArea))
		{
			m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build watershed regions.");
			return 0;
		}
	}
	else if (m_partitionType == SAMPLE_PARTITION_MONOTONE)
	{
		// Partition the walkable surface into simple regions without holes.
		// Monotone partitioning does not need distancefield.
		if (!rcBuildRegionsMonotone(m_ctx, *m_chf, m_cfg.borderSize, m_cfg.minRegionArea, m_cfg.mergeRegionArea))
		{
			m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build monotone regions.");
			return 0;
		}
	}
	else // SAMPLE_PARTITION_LAYERS
	{
		// Partition the walkable surface into simple regions without holes.
		if (!rcBuildLayerRegions(m_ctx, *m_chf, m_cfg.borderSize, m_cfg.minRegionArea))
		{
			m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build layer regions.");
			return 0;
		}
	}
	 	
	// Create contours.
	m_cset = rcAllocContourSet();
	if (!m_cset)
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'cset'.");
		return 0;
	}
	if (!rcBuildContours(m_ctx, *m_chf, m_cfg.maxSimplificationError, m_cfg.maxEdgeLen, *m_cset))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not create contours.");
		return 0;
	}
	
	if (m_cset->nconts == 0)
	{
		return 0;
	}
	
	// Build polygon navmesh from the contours.
	m_pmesh = rcAllocPolyMesh();
	if (!m_pmesh)
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'pmesh'.");
		return 0;
	}
	if (!rcBuildPolyMesh(m_ctx, *m_cset, m_cfg.maxVertsPerPoly, *m_pmesh))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not triangulate contours.");
		return 0;
	}
	
	// Build detail mesh.
	m_dmesh = rcAllocPolyMeshDetail();
	if (!m_dmesh)
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'dmesh'.");
		return 0;
	}
	
	if (!rcBuildPolyMeshDetail(m_ctx, *m_pmesh, *m_chf,
							   m_cfg.detailSampleDist, m_cfg.detailSampleMaxError,
							   *m_dmesh))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could build polymesh detail.");
		return 0;
	}
	
	if (!m_keepInterResults)
	{
		rcFreeCompactHeightfield(m_chf);
		m_chf = 0;
		rcFreeContourSet(m_cset);
		m_cset = 0;
	}
	
	unsigned char* navData = 0;
	int navDataSize = 0;
	if (m_cfg.maxVertsPerPoly <= DT_VERTS_PER_POLYGON)
	{
		if (m_pmesh->nverts >= 0xffff)
		{
			// The vertex indices are ushorts, and cannot point to more than 0xffff vertices.
			m_ctx->log(RC_LOG_ERROR, "Too many vertices per tile %d (max: %d).", m_pmesh->nverts, 0xffff);
			return 0;
		}
		
		// Update poly flags from areas.
		/*for (int i = 0; i < m_pmesh->npolys; ++i)
		{
			if (m_pmesh->areas[i] == RC_WALKABLE_AREA)
				m_pmesh->areas[i] = SAMPLE_POLYAREA_GROUND;
			
			if (m_pmesh->areas[i] == SAMPLE_POLYAREA_GROUND ||
				m_pmesh->areas[i] == SAMPLE_POLYAREA_GRASS ||
				m_pmesh->areas[i] == SAMPLE_POLYAREA_ROAD)
			{
				m_pmesh->flags[i] = SAMPLE_POLYFLAGS_WALK;
			}
			else if (m_pmesh->areas[i] == SAMPLE_POLYAREA_WATER)
			{
				m_pmesh->flags[i] = SAMPLE_POLYFLAGS_SWIM;
			}
			else if (m_pmesh->areas[i] == SAMPLE_POLYAREA_DOOR)
			{
				m_pmesh->flags[i] = SAMPLE_POLYFLAGS_WALK | SAMPLE_POLYFLAGS_DOOR;
			}
		}*/
		
		dtNavMeshCreateParams params;
		memset(&params, 0, sizeof(params));
		params.verts = m_pmesh->verts;
		params.vertCount = m_pmesh->nverts;
		params.polys = m_pmesh->polys;
		params.polyAreas = m_pmesh->areas;
		params.polyCount = m_pmesh->npolys;
		params.nvp = m_pmesh->nvp;
		params.detailMeshes = m_dmesh->meshes;
		params.detailVerts = m_dmesh->verts;
		params.detailVertsCount = m_dmesh->nverts;
		params.detailTris = m_dmesh->tris;
		params.detailTriCount = m_dmesh->ntris;
		params.offMeshConVerts = m_geom->getOffMeshConnectionVerts();
		params.offMeshConRad = m_geom->getOffMeshConnectionRads();
		params.offMeshConDir = m_geom->getOffMeshConnectionDirs();
		params.offMeshConAreas = m_geom->getOffMeshConnectionAreas();
		params.offMeshConFlags = m_geom->getOffMeshConnectionFlags();
		params.offMeshConUserID = m_geom->getOffMeshConnectionId();
		params.offMeshConCount = m_geom->getOffMeshConnectionCount();
		params.walkableHeight = m_agentHeight;
		params.walkableRadius = m_agentRadius;
		params.walkableClimb = m_agentMaxClimb;
		params.tileX = tx;
		params.tileY = ty;
		params.tileLayer = 0;
		rcVcopy(params.bmin, m_pmesh->bmin);
		rcVcopy(params.bmax, m_pmesh->bmax);
		params.cs = m_cfg.cs;
		params.ch = m_cfg.ch;
		params.buildBvTree = true;
		
		if (!dtCreateNavMeshData(&params, &navData, &navDataSize))
		{
			m_ctx->log(RC_LOG_ERROR, "Could not build Detour navmesh.");
			return 0;
		}		
	}
	m_tileMemUsage = navDataSize/1024.0f;
	
	m_ctx->stopTimer(RC_TIMER_TOTAL);
	
	// Show performance stats.
	duLogBuildTimes(*m_ctx, m_ctx->getAccumulatedTime(RC_TIMER_TOTAL));
	m_ctx->log(RC_LOG_PROGRESS, ">> Polymesh: %d vertices  %d polygons", m_pmesh->nverts, m_pmesh->npolys);
	
	m_tileBuildTime = m_ctx->getAccumulatedTime(RC_TIMER_TOTAL)/1000.0f;

	dataSize = navDataSize;
	return navData;
}
// This works by converting the SVG arc to "simple" beziers.
// Partly adapted from Niko's code in kdelibs/kdecore/svgicons.
// See also SVG implementation notes: http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter
bool SVGPathParser::decomposeArcToCubic(float angle, float rx, float ry, FloatPoint& point1, FloatPoint& point2, bool largeArcFlag, bool sweepFlag)
{
    FloatSize midPointDistance = point1 - point2;
    midPointDistance.scale(0.5f);

    AffineTransform pointTransform;
    pointTransform.rotate(-angle);

    FloatPoint transformedMidPoint = pointTransform.mapPoint(FloatPoint(midPointDistance.width(), midPointDistance.height()));
    float squareRx = rx * rx;
    float squareRy = ry * ry;
    float squareX = transformedMidPoint.x() * transformedMidPoint.x();
    float squareY = transformedMidPoint.y() * transformedMidPoint.y();

    // Check if the radii are big enough to draw the arc, scale radii if not.
    // http://www.w3.org/TR/SVG/implnote.html#ArcCorrectionOutOfRangeRadii
    float radiiScale = squareX / squareRx + squareY / squareRy;
    if (radiiScale > 1) {
        rx *= sqrtf(radiiScale);
        ry *= sqrtf(radiiScale);
    }

    pointTransform.makeIdentity();
    pointTransform.scale(1 / rx, 1 / ry);
    pointTransform.rotate(-angle);

    point1 = pointTransform.mapPoint(point1);
    point2 = pointTransform.mapPoint(point2);
    FloatSize delta = point2 - point1;

    float d = delta.width() * delta.width() + delta.height() * delta.height();
    float scaleFactorSquared = std::max(1 / d - 0.25f, 0.f);

    float scaleFactor = sqrtf(scaleFactorSquared);
    if (sweepFlag == largeArcFlag)
        scaleFactor = -scaleFactor;

    delta.scale(scaleFactor);
    FloatPoint centerPoint = point1 + point2;
    centerPoint.scale(0.5f, 0.5f);
    centerPoint.move(-delta.height(), delta.width());

    float theta1 = FloatPoint(point1 - centerPoint).slopeAngleRadians();
    float theta2 = FloatPoint(point2 - centerPoint).slopeAngleRadians();

    float thetaArc = theta2 - theta1;
    if (thetaArc < 0 && sweepFlag)
        thetaArc += 2 * piFloat;
    else if (thetaArc > 0 && !sweepFlag)
        thetaArc -= 2 * piFloat;

    pointTransform.makeIdentity();
    pointTransform.rotate(angle);
    pointTransform.scale(rx, ry);

    // Some results of atan2 on some platform implementations are not exact enough. So that we get more
    // cubic curves than expected here. Adding 0.001f reduces the count of sgements to the correct count.
    int segments = ceilf(fabsf(thetaArc / (piOverTwoFloat + 0.001f)));
    for (int i = 0; i < segments; ++i) {
        float startTheta = theta1 + i * thetaArc / segments;
        float endTheta = theta1 + (i + 1) * thetaArc / segments;

        float t = (8 / 6.f) * tanf(0.25f * (endTheta - startTheta));
        if (!std::isfinite(t))
            return false;
        float sinStartTheta = sinf(startTheta);
        float cosStartTheta = cosf(startTheta);
        float sinEndTheta = sinf(endTheta);
        float cosEndTheta = cosf(endTheta);

        point1 = FloatPoint(cosStartTheta - t * sinStartTheta, sinStartTheta + t * cosStartTheta);
        point1.move(centerPoint.x(), centerPoint.y());
        FloatPoint targetPoint = FloatPoint(cosEndTheta, sinEndTheta);
        targetPoint.move(centerPoint.x(), centerPoint.y());
        point2 = targetPoint;
        point2.move(t * sinEndTheta, -t * cosEndTheta);

        m_consumer->curveToCubic(pointTransform.mapPoint(point1), pointTransform.mapPoint(point2),
                                 pointTransform.mapPoint(targetPoint), AbsoluteCoordinates);
    }
    return true;
}
Esempio n. 5
0
float MathUtil::ceilfValue(float value) {
    return ceilf(value);
}
/*
 * caller free both sino and newSino
 * 
 * This function prepares a new set of sinograms for the next recursive call.
 * It DOES angularly downsample the sinograms.
 *
 */
sinograms* newSinoForNextIter_forw(sinograms* sino,int newSinoSize,myFloat constShiftingFactor,myFloat* nu_i)
{

  int P = sino->num;
  sinograms* newSino;
  int size = sino->size;
  int newNumSino;
  int m,n,k,p;
  myFloat kk,pp;
  myFloat sum;
  myFloat angle;
  
  myFloat temp1,temp2,temp3;
  myFloat shiftingFactor;
  myFloat radialShift;
  myFloat totalShift;
  myFloat temp;
  
  int n2;
  int lowerPBound,upperPBound,lowerKBound,upperKBound;
  myFloat angularSupport;
  myFloat radialSupport;

  //preparing new sinograms
  newSino = (sinograms*)malloc(1*sizeof(sinograms));
  newSino->T = T;
  newSino->size = newSinoSize; 
  newSino->num = ceilf((myFloat)P/2);

  newNumSino = newSino->num;
  (newSino->sino)  = (myFloat**)malloc(newNumSino*sizeof(myFloat*));
  (newSino->sine) = (myFloat*)malloc(newNumSino*sizeof(myFloat));
  (newSino->cosine) = (myFloat*)malloc(newNumSino*sizeof(myFloat));
  //done preparing spaces for new sinograms


  angularSupport = ANGULAR_SUPPORT;
  radialSupport = RADIAL_SUPPORT;


  for(n=0;n<newNumSino;n++){
    //for each new angle
    n2 = 2*n;                
    (newSino->sino)[n] = (myFloat*)malloc(newSinoSize*sizeof(myFloat));
    (newSino->sine)[n] = (sino->sine)[n2];
    (newSino->cosine)[n] = (sino->cosine)[n2];    
    
    lowerPBound = maxInt(n2-(int)(angularSupport),0);    
    upperPBound = minInt(n2+ceilf(angularSupport),P-1);  


    for(m=0;m<newSinoSize;m++){
      //for each new radial array index
      sum = 0;
      
      for(p=lowerPBound;p<=upperPBound;p++){
	    //for each old angle
	    temp1 = n2-p;
	    temp2 = ANGULAR_INTERP(temp1);

	    radialShift = m+nu_i[n2]-nu_i[p];
	    shiftingFactor = rintf(nu_i[p]) + constShiftingFactor;

	    lowerKBound = (minInt(maxInt(ceilf(radialShift-shiftingFactor-radialSupport),0),size-1));
	    upperKBound = (maxInt(minInt((int)(radialShift-shiftingFactor+radialSupport),size-1),0)); 
	
	    
        //this loop can be optimized more, but i didn't have time.
	    for(k=lowerKBound;k<=upperKBound;k++){ 
	        //for each old radial array index
	        temp3 = (sino->sino)[p][k];
	  
	        kk = k + shiftingFactor; 
	        temp = radialShift-kk;
	        temp1 = RADIAL_INTERP(temp);
	  
	        sum += temp1 * temp2 * temp3;

	    }//end for k
      }//end for p

      (newSino->sino)[n][m] =  sum;
        
    }//end for m
  }//end for n

  return newSino;
}
Esempio n. 7
0
unsigned char* Sample_TileMesh::buildTileMesh(const int tx, const int ty, const float* bmin, const float* bmax, int& dataSize)
{
	if (!m_geom || !m_geom->getMesh() || !m_geom->getChunkyMesh())
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Input mesh is not specified.");
		return 0;
	}
	
	m_tileMemUsage = 0;
	m_tileBuildTime = 0;
	
	cleanup();
	
	const float* verts = m_geom->getMesh()->getVerts();
	const int nverts = m_geom->getMesh()->getVertCount();
	const int ntris = m_geom->getMesh()->getTriCount();
	const rcChunkyTriMesh* chunkyMesh = m_geom->getChunkyMesh();
		
	// Init build configuration from GUI
	memset(&m_cfg, 0, sizeof(m_cfg));
	m_cfg.cs = m_cellSize;
	m_cfg.ch = m_cellHeight;
	m_cfg.walkableSlopeAngle = m_agentMaxSlope;
	m_cfg.walkableHeight = (int)ceilf(m_agentHeight / m_cfg.ch);
	m_cfg.walkableClimb = (int)floorf(m_agentMaxClimb / m_cfg.ch);
	m_cfg.walkableRadius = (int)ceilf(m_agentRadius / m_cfg.cs);
	m_cfg.maxEdgeLen = (int)(m_edgeMaxLen / m_cellSize);
	m_cfg.maxSimplificationError = m_edgeMaxError;
	m_cfg.minRegionSize = (int)rcSqr(m_regionMinSize);
	m_cfg.mergeRegionSize = (int)rcSqr(m_regionMergeSize);
	m_cfg.maxVertsPerPoly = (int)m_vertsPerPoly;
	m_cfg.tileSize = (int)m_tileSize;
	m_cfg.borderSize = m_cfg.walkableRadius + 3; // Reserve enough padding.
	m_cfg.width = m_cfg.tileSize + m_cfg.borderSize*2;
	m_cfg.height = m_cfg.tileSize + m_cfg.borderSize*2;
	m_cfg.detailSampleDist = m_detailSampleDist < 0.9f ? 0 : m_cellSize * m_detailSampleDist;
	m_cfg.detailSampleMaxError = m_cellHeight * m_detailSampleMaxError;
	
	rcVcopy(m_cfg.bmin, bmin);
	rcVcopy(m_cfg.bmax, bmax);
	m_cfg.bmin[0] -= m_cfg.borderSize*m_cfg.cs;
	m_cfg.bmin[2] -= m_cfg.borderSize*m_cfg.cs;
	m_cfg.bmax[0] += m_cfg.borderSize*m_cfg.cs;
	m_cfg.bmax[2] += m_cfg.borderSize*m_cfg.cs;
	
	// Reset build times gathering.
	m_ctx->resetBuildTimes();
	
	// Start the build process.	
	rcTimeVal totStartTime = m_ctx->getTime();
	
	m_ctx->log(RC_LOG_PROGRESS, "Building navigation:");
	m_ctx->log(RC_LOG_PROGRESS, " - %d x %d cells", m_cfg.width, m_cfg.height);
	m_ctx->log(RC_LOG_PROGRESS, " - %.1fK verts, %.1fK tris", nverts/1000.0f, ntris/1000.0f);
	
	// Allocate voxel heighfield where we rasterize our input data to.
	m_solid = rcAllocHeightfield();
	if (!m_solid)
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'solid'.");
		return 0;
	}
	if (!rcCreateHeightfield(m_ctx, *m_solid, m_cfg.width, m_cfg.height, m_cfg.bmin, m_cfg.bmax, m_cfg.cs, m_cfg.ch))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not create solid heightfield.");
		return 0;
	}
	
	// Allocate array that can hold triangle flags.
	// If you have multiple meshes you need to process, allocate
	// and array which can hold the max number of triangles you need to process.
	m_triareas = new unsigned char[chunkyMesh->maxTrisPerChunk];
	if (!m_triareas)
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'm_triareas' (%d).", chunkyMesh->maxTrisPerChunk);
		return 0;
	}
	
	float tbmin[2], tbmax[2];
	tbmin[0] = m_cfg.bmin[0];
	tbmin[1] = m_cfg.bmin[2];
	tbmax[0] = m_cfg.bmax[0];
	tbmax[1] = m_cfg.bmax[2];
	int cid[512];// TODO: Make grow when returning too many items.
	const int ncid = rcGetChunksInRect(chunkyMesh, tbmin, tbmax, cid, 512);
	if (!ncid)
		return 0;
	
	m_tileTriCount = 0;
	
	for (int i = 0; i < ncid; ++i)
	{
		const rcChunkyTriMeshNode& node = chunkyMesh->nodes[cid[i]];
		const int* tris = &chunkyMesh->tris[node.i*3];
		const int ntris = node.n;
		
		m_tileTriCount += ntris;
		
		memset(m_triareas, 0, ntris*sizeof(unsigned char));
		rcMarkWalkableTriangles(m_ctx, m_cfg.walkableSlopeAngle,
								verts, nverts, tris, ntris, m_triareas);
		
		rcRasterizeTriangles(m_ctx, verts, nverts, tris, m_triareas, ntris, *m_solid, m_cfg.walkableClimb);
	}
	
	if (!m_keepInterResults)
	{
		delete [] m_triareas;
		m_triareas = 0;
	}
	
	// Once all geometry is rasterized, we do initial pass of filtering to
	// remove unwanted overhangs caused by the conservative rasterization
	// as well as filter spans where the character cannot possibly stand.
	rcFilterLowHangingWalkableObstacles(m_ctx, m_cfg.walkableClimb, *m_solid);
	rcFilterLedgeSpans(m_ctx, m_cfg.walkableHeight, m_cfg.walkableClimb, *m_solid);
	rcFilterWalkableLowHeightSpans(m_ctx, m_cfg.walkableHeight, *m_solid);
	
	// Compact the heightfield so that it is faster to handle from now on.
	// This will result more cache coherent data as well as the neighbours
	// between walkable cells will be calculated.
	m_chf = rcAllocCompactHeightfield();
	if (!m_chf)
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'chf'.");
		return 0;
	}
	if (!rcBuildCompactHeightfield(m_ctx, m_cfg.walkableHeight, m_cfg.walkableClimb, *m_solid, *m_chf))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build compact data.");
		return 0;
	}
	
	if (!m_keepInterResults)
	{
		rcFreeHeightField(m_solid);
		m_solid = 0;
	}

	// Erode the walkable area by agent radius.
	if (!rcErodeWalkableArea(m_ctx, m_cfg.walkableRadius, *m_chf))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not erode.");
		return false;
	}

	// (Optional) Mark areas.
	const ConvexVolume* vols = m_geom->getConvexVolumes();
	for (int i  = 0; i < m_geom->getConvexVolumeCount(); ++i)
		rcMarkConvexPolyArea(m_ctx, vols[i].verts, vols[i].nverts, vols[i].hmin, vols[i].hmax, (unsigned char)vols[i].area, *m_chf);
	
	// Prepare for region partitioning, by calculating distance field along the walkable surface.
	if (!rcBuildDistanceField(m_ctx, *m_chf))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build distance field.");
		return 0;
	}
	
	// Partition the walkable surface into simple regions without holes.
	if (!rcBuildRegions(m_ctx, *m_chf, m_cfg.borderSize, m_cfg.minRegionSize, m_cfg.mergeRegionSize))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build regions.");
		return 0;
	}
	
	// Create contours.
	m_cset = rcAllocContourSet();
	if (!m_cset)
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'cset'.");
		return 0;
	}
	if (!rcBuildContours(m_ctx, *m_chf, m_cfg.maxSimplificationError, m_cfg.maxEdgeLen, *m_cset))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not create contours.");
		return 0;
	}
	
	if (m_cset->nconts == 0)
	{
		return 0;
	}
	
	// Build polygon navmesh from the contours.
	m_pmesh = rcAllocPolyMesh();
	if (!m_pmesh)
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'pmesh'.");
		return 0;
	}
	if (!rcBuildPolyMesh(m_ctx, *m_cset, m_cfg.maxVertsPerPoly, *m_pmesh))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not triangulate contours.");
		return 0;
	}
	
	// Build detail mesh.
	m_dmesh = rcAllocPolyMeshDetail();
	if (!m_dmesh)
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'dmesh'.");
		return 0;
	}
	
	if (!rcBuildPolyMeshDetail(m_ctx, *m_pmesh, *m_chf,
							   m_cfg.detailSampleDist, m_cfg.detailSampleMaxError,
							   *m_dmesh))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could build polymesh detail.");
		return 0;
	}
	
	if (!m_keepInterResults)
	{
		rcFreeCompactHeightfield(m_chf);
		m_chf = 0;
		rcFreeContourSet(m_cset);
		m_cset = 0;
	}
	
	unsigned char* navData = 0;
	int navDataSize = 0;
	if (m_cfg.maxVertsPerPoly <= DT_VERTS_PER_POLYGON)
	{
		// Remove padding from the polymesh data. TODO: Remove this odditity.
		for (int i = 0; i < m_pmesh->nverts; ++i)
		{
			unsigned short* v = &m_pmesh->verts[i*3];
			v[0] -= (unsigned short)m_cfg.borderSize;
			v[2] -= (unsigned short)m_cfg.borderSize;
		}
		
		if (m_pmesh->nverts >= 0xffff)
		{
			// The vertex indices are ushorts, and cannot point to more than 0xffff vertices.
			m_ctx->log(RC_LOG_ERROR, "Too many vertices per tile %d (max: %d).", m_pmesh->nverts, 0xffff);
			return false;
		}
		
		// Update poly flags from areas.
		for (int i = 0; i < m_pmesh->npolys; ++i)
		{
			if (m_pmesh->areas[i] == RC_WALKABLE_AREA)
				m_pmesh->areas[i] = SAMPLE_POLYAREA_GROUND;
			
			if (m_pmesh->areas[i] == SAMPLE_POLYAREA_GROUND ||
				m_pmesh->areas[i] == SAMPLE_POLYAREA_GRASS ||
				m_pmesh->areas[i] == SAMPLE_POLYAREA_ROAD)
			{
				m_pmesh->flags[i] = SAMPLE_POLYFLAGS_WALK;
			}
			else if (m_pmesh->areas[i] == SAMPLE_POLYAREA_WATER)
			{
				m_pmesh->flags[i] = SAMPLE_POLYFLAGS_SWIM;
			}
			else if (m_pmesh->areas[i] == SAMPLE_POLYAREA_DOOR)
			{
				m_pmesh->flags[i] = SAMPLE_POLYFLAGS_WALK | SAMPLE_POLYFLAGS_DOOR;
			}
		}
		
		dtNavMeshCreateParams params;
		memset(&params, 0, sizeof(params));
		params.verts = m_pmesh->verts;
		params.vertCount = m_pmesh->nverts;
		params.polys = m_pmesh->polys;
		params.polyAreas = m_pmesh->areas;
		params.polyFlags = m_pmesh->flags;
		params.polyCount = m_pmesh->npolys;
		params.nvp = m_pmesh->nvp;
		params.detailMeshes = m_dmesh->meshes;
		params.detailVerts = m_dmesh->verts;
		params.detailVertsCount = m_dmesh->nverts;
		params.detailTris = m_dmesh->tris;
		params.detailTriCount = m_dmesh->ntris;
		params.offMeshConVerts = m_geom->getOffMeshConnectionVerts();
		params.offMeshConRad = m_geom->getOffMeshConnectionRads();
		params.offMeshConDir = m_geom->getOffMeshConnectionDirs();
		params.offMeshConAreas = m_geom->getOffMeshConnectionAreas();
		params.offMeshConFlags = m_geom->getOffMeshConnectionFlags();
		params.offMeshConCount = m_geom->getOffMeshConnectionCount();
		params.walkableHeight = m_agentHeight;
		params.walkableRadius = m_agentRadius;
		params.walkableClimb = m_agentMaxClimb;
		params.tileX = tx;
		params.tileY = ty;
		rcVcopy(params.bmin, bmin);
		rcVcopy(params.bmax, bmax);
		params.cs = m_cfg.cs;
		params.ch = m_cfg.ch;
		params.tileSize = m_cfg.tileSize;
		
		if (!dtCreateNavMeshData(&params, &navData, &navDataSize))
		{
			m_ctx->log(RC_LOG_ERROR, "Could not build Detour navmesh.");
			return 0;
		}
		
		// Restore padding so that the debug visualization is correct.
		for (int i = 0; i < m_pmesh->nverts; ++i)
		{
			unsigned short* v = &m_pmesh->verts[i*3];
			v[0] += (unsigned short)m_cfg.borderSize;
			v[2] += (unsigned short)m_cfg.borderSize;
		}
		
	}
	m_tileMemUsage = navDataSize/1024.0f;
	
	rcTimeVal totEndTime = m_ctx->getTime();
	
	// Show performance stats.
	duLogBuildTimes(m_ctx, m_ctx->getDeltaTimeUsec(totStartTime, totEndTime));
	m_ctx->log(RC_LOG_PROGRESS, ">> Polymesh: %d vertices  %d polygons", m_pmesh->nverts, m_pmesh->npolys);
	
	m_tileBuildTime = m_ctx->getDeltaTimeUsec(totStartTime, totEndTime)/1000.0f;

	dataSize = navDataSize;
	return navData;
}
Esempio n. 8
0
void SGShowAllLayer::initView()
{
    ResourceManager::sharedInstance()->bindTexture("sgstrenglayer/sgstrenglayer.plist", RES_TYPE_LAYER_UI, sg_showAllLayer, LIM_PNG_AS_PNG);
    ResourceManager::sharedInstance()->bindTexture("sgmainlayer/sgmainlayer.plist", RES_TYPE_LAYER_UI, sg_showAllLayer, LIM_PNG_AS_PNG);
    ResourceManager::sharedInstance()->bindTexture("sgembattlelayer/sgembattlelayer.plist", RES_TYPE_LAYER_UI, sg_showAllLayer, LIM_PNG_AS_PNG);

    float h = SGMainManager::shareMain()->getHeadHeight();
    float b = SGMainManager::shareMain()->getBottomHeight();
    CCSize s= CCDirector::sharedDirector()->getWinSize();
        
    CCSprite *titleBg = CCSprite::createWithSpriteFrameName("barrack_title_bg.png");
    this->addChild(titleBg);
    titleBg->setAnchorPoint(ccp(0.5, 1));
    titleBg->setPosition(ccpAdd(SGLayout::getPoint(kUpCenter), ccp(0, - h )));
    
    SGButton *backBtn = SGButton::create("redbtn_jiao.png",
                                         "public_font_back.png",
                                         this,
                                         menu_selector(SGShowAllLayer::backHandler),
                                         ccp(-18, 0),
                                         false,
                                         true);
    this->addBtn(backBtn);
    backBtn->setAnchorPoint(ccp(0, 0.5));
    backBtn->setPosition(ccp(0, titleBg->getPosition().y-titleBg->getContentSize().height/2));
    
    SGButton *sortBtn = SGButton::create("redbtn_jiao.png",
                                         "public_range.png",
                                         this,
                                         menu_selector(SGShowAllLayer::sortHandler),
                                         ccp(18, 0),
                                         true,
                                         true);
    this->addBtn(sortBtn);
    sortBtn->setAnchorPoint(ccp(1, 1));
    sortBtn->setPosition(ccpAdd(SGLayout::getPoint(kBottomRight),ccp(0, titleBg->getPosition().y)));
    
    CCSprite *font2 = CCSprite::createWithSpriteFrameName("font_szwjscsx.png");
    font2->setPosition(ccp(s.width/2, titleBg->getPosition().y - titleBg->getContentSize().height/2));
    this->addChild(font2);
    
    scrollView = SNSScrollView::create(CCRectMake(0, 280, s.width, s.height - h - b  - titleBg->getContentSize().height-10));
    scrollView->setPosition(ccpAdd(SGLayout::getPoint(kBottomLeft), ccp(0, b)));
    this->addChild(scrollView);
    scrollView->setHorizontal(false);
    scrollView->setVertical(true);
    
//    CCArray *cards = SGPlayerInfo::sharePlayerInfo()->getShowOfficerCards();
    int id = SGTeamgroup::shareTeamgroupInfo()->getiscurrent();
    CCArray *cards = SGTeamgroup::shareTeamgroupInfo()->getEmbattleOfficers(id);
    int bagSize = SGPlayerInfo::sharePlayerInfo()->getPlayerBagSize();
    CCLOG("bagSize:%d",bagSize);
    bagSize = 52;
    float row = (float)bagSize/5;
    int allrow = ceilf(row);
    float itemWidth = 0;
    float itemHeight = 0;
    
    for (int i = 0; i<bagSize; i++)
    {
        SGOfficerCard *card = NULL;
        SGEmbattleItem *item = NULL;
        if (i<cards->count())
        {
            card = (SGOfficerCard *)cards->objectAtIndex(i);
            
        }
        if (card)
        {
            item = SGEmbattleItem::create(this, card,SGTeamgroup::shareTeamgroupInfo()->getiscurrent());
        }
        else
        {
            item = SGEmbattleItem::create(this,(i+1),SGTeamgroup::shareTeamgroupInfo()->getiscurrent());
        }
        
        cardArray->addObject(item);
        scrollView->m_body->addChild(item);
        itemWidth = item->getWidth();
        itemHeight = item->getHeight();
        
        CCSize s = CCDirector::sharedDirector()->getWinSize();
        float wid = s.width - itemWidth*5 ;
        item->setPosition(ccp(i%5*(itemWidth + 20)+10 + wid/2, (item->getHeight() + 20)*allrow - item->getHeight() * .5 - (i/5) * (itemHeight + 20)));
    }
    
    scrollView->setBodySize(CCSizeMake((itemWidth + 20) *5 , (itemHeight + 20)*allrow));
    
    scrollviewRect = CCRectMake(0, b, s.width, s.height - h - b - titleBg->getContentSize().height-10);
    
}
Esempio n. 9
0
void
NotificationView::SetText(float newMaxWidth)
{
	if (newMaxWidth < 0 && Parent())
		newMaxWidth = Parent()->Bounds().IntegerWidth();
	if (newMaxWidth <= 0)
		newMaxWidth = kDefaultWidth;

	// Delete old lines
	LineInfoList::iterator lIt;
	for (lIt = fLines.begin(); lIt != fLines.end(); lIt++)
		delete (*lIt);
	fLines.clear();

	float iconRight = kIconStripeWidth;
	if (fBitmap != NULL)
		iconRight += fParent->IconSize();
	else
		iconRight += 32;

	font_height fh;
	be_bold_font->GetHeight(&fh);
	float fontHeight = ceilf(fh.leading) + ceilf(fh.descent)
		+ ceilf(fh.ascent);
	float y = 2 * fontHeight;

	// Title
	LineInfo* titleLine = new LineInfo;
	titleLine->text = fNotification->Title();
	titleLine->font = *be_bold_font;

	titleLine->location = BPoint(iconRight + kEdgePadding, y);

	fLines.push_front(titleLine);
	y += fontHeight;

	// Rest of text is rendered with be_plain_font.
	be_plain_font->GetHeight(&fh);
	fontHeight = ceilf(fh.leading) + ceilf(fh.descent)
		+ ceilf(fh.ascent);

	// Split text into chunks between certain characters and compose the lines.
	const char kSeparatorCharacters[] = " \n-\\";
	BString textBuffer = fNotification->Content();
	textBuffer.ReplaceAll("\t", "    ");
	const char* chunkStart = textBuffer.String();
	float maxWidth = newMaxWidth - kEdgePadding - iconRight;
	LineInfo* line = NULL;
	ssize_t length = textBuffer.Length();
	while (chunkStart - textBuffer.String() < length) {
		size_t chunkLength = strcspn(chunkStart, kSeparatorCharacters) + 1;

		// Start a new line if we didn't start one before
		BString tempText;
		if (line != NULL)
			tempText.SetTo(line->text);
		tempText.Append(chunkStart, chunkLength);

		if (line == NULL || chunkStart[0] == '\n'
			|| StringWidth(tempText) > maxWidth) {
			line = new LineInfo;
			line->font = *be_plain_font;
			line->location = BPoint(iconRight + kEdgePadding, y);

			fLines.push_front(line);
			y += fontHeight;

			// Skip the eventual new-line character at the beginning of this chunk
			if (chunkStart[0] == '\n') {
				chunkStart++;
				chunkLength--;
			}

			// Skip more new-line characters and move the line further down
			while (chunkStart[0] == '\n') {
				chunkStart++;
				chunkLength--;
				line->location.y += fontHeight;
				y += fontHeight;
			}

			// Strip space at beginning of a new line
			while (chunkStart[0] == ' ') {
				chunkLength--;
				chunkStart++;
			}
		}

		if (chunkStart[0] == '\0')
			break;

		// Append the chunk to the current line, which was either a new
		// line or the one from the previous iteration
		line->text.Append(chunkStart, chunkLength);

		chunkStart += chunkLength;
	}

	fHeight = y + (kEdgePadding * 2);

	// Make sure icon fits
	if (fBitmap != NULL) {
		float minHeight = fBitmap->Bounds().Height() + 2 * kEdgePadding;

		if (fHeight < minHeight)
			fHeight = minHeight;
	}

	// Make sure the progress bar is below the text, and the window is big
	// enough.
	static_cast<BGroupLayout*>(GetLayout())->SetInsets(kIconStripeWidth + 8,
		fHeight, 8, 8);

	_CalculateSize();
}
Esempio n. 10
0
int numBytesForPacketHeaderGivenPacketType(PacketType type) {
    return (int) ceilf((float)type / 255)
    + numHashBytesInPacketHeaderGivenPacketType(type)
    + NUM_STATIC_HEADER_BYTES;
}
    /*!
     Build a NAVIGATION mesh from an OBJ mesh index. Usually this OBJMESH is either a collision map
     or a mesh that have been built especially for navigation.
     
     \param[in,out] navigation A valid NAVIGATION structure pointer.
     \param[in] obj A valid OBJ structure pointer.
     \param[in] mesh_index The mesh index of the OBJMESH to use to create the NAVIGATION mesh.
     
     \return Return 1 if the NAVIGATION mesh have been generated successfully, else this function will return 0.
     */
    unsigned char NAVIGATION_build( NAVIGATION *navigation, Object *obj, unsigned int mesh_index )
    {
        unsigned int i = 0,
        j = 0,
        k = 0,
        triangle_count = 0;
        
        int *indices = NULL;
        
        Mesh *objmesh = obj->meshList[ mesh_index ];
        
//        vec3 *vertex_array = ( vec3 * ) malloc( objmesh->n_objvertexdata * sizeof( vec3 ) ),
        vec3 *vertex_array = ( vec3 * ) malloc( objmesh->uniqueVertexUVIndexList.size() * sizeof( vec3 ) ),
        *vertex_start = vertex_array;
        
        rcHeightfield *rcheightfield;
        
        rcCompactHeightfield *rccompactheightfield;
        
        rcContourSet *rccontourset;
        
        rcPolyMesh *rcpolymesh;
        
        rcPolyMeshDetail *rcpolymeshdetail;
        
        
        while( i != objmesh->uniqueVertexUVIndexList.size() )
        {
            
            
            memcpy( vertex_array,
                   &obj->vertexMgr.uniqueVertexList[objmesh->uniqueVertexUVIndexList[i].vertexIndex],
                   sizeof( vec3 ) );
            
            *vertex_array = vertex_array->toRecast();
            
//            vec3_to_recast( vertex_array );
            
            ++vertex_array;
            ++i;
        }
        
//        while( i != objmesh->n_objvertexdata )
//        {
//            memcpy( vertex_array,
//                   &obj->indexed_vertex[ objmesh->objvertexdata[ i ].vertex_index ],
//                   sizeof( vec3 ) );
//            
//            vec3_to_recast( vertex_array );
//            
//            ++vertex_array;
//            ++i;
//        }
        
            triangle_count += objmesh->vertexIndexList.size();
            
            indices = ( int * ) realloc( indices, triangle_count * sizeof( int ) );
            
            j = 0;
            while( j != objmesh->vertexIndexList.size() )
            {
                indices[ k ] = objmesh->vertexIndexList[ j ];
                
                ++k;
                ++j;
            }
//
//        i = 0;
//        while( i != objmesh->n_objtrianglelist )
//        {
//            triangle_count += objmesh->objtrianglelist[ i ].n_indice_array;
//            
//            indices = ( int * ) realloc( indices, triangle_count * sizeof( int ) );
//            
//            j = 0;
//            while( j != objmesh->objtrianglelist[ i ].n_indice_array )
//            {
//                indices[ k ] = objmesh->objtrianglelist[ i ].indice_array[ j ];
//                
//                ++k;
//                ++j;
//            }
//            
//            ++i;
//        }
        
        triangle_count /= 3;
        
        rcConfig rcconfig;
        
        memset( &rcconfig, 0, sizeof( rcConfig ) );
        
        rcconfig.cs						= navigation->navigationconfiguration.cell_size;
        rcconfig.ch						= navigation->navigationconfiguration.cell_height;
        rcconfig.walkableHeight			= ( int )ceilf ( navigation->navigationconfiguration.agent_height / rcconfig.ch );
        rcconfig.walkableRadius			= ( int )ceilf ( navigation->navigationconfiguration.agent_radius / rcconfig.cs );
        rcconfig.walkableClimb			= ( int )floorf( navigation->navigationconfiguration.agent_max_climb / rcconfig.ch );
        rcconfig.walkableSlopeAngle		= navigation->navigationconfiguration.agent_max_slope;
        rcconfig.minRegionSize			= ( int )rcSqr( navigation->navigationconfiguration.region_min_size );
        rcconfig.mergeRegionSize		= ( int )rcSqr( navigation->navigationconfiguration.region_merge_size );
        rcconfig.maxEdgeLen				= ( int )( navigation->navigationconfiguration.edge_max_len / rcconfig.cs );
        rcconfig.maxSimplificationError = navigation->navigationconfiguration.edge_max_error;
        rcconfig.maxVertsPerPoly		= ( int )navigation->navigationconfiguration.vert_per_poly;
        rcconfig.detailSampleDist		= rcconfig.cs * navigation->navigationconfiguration.detail_sample_dst;
        rcconfig.detailSampleMaxError   = rcconfig.ch * navigation->navigationconfiguration.detail_sample_max_error;
        
        
        rcCalcBounds( ( float * )vertex_start,
                     (int)objmesh->uniqueVertexUVIndexList.size(),
//                     objmesh->n_objvertexdata,
                     rcconfig.bmin,
                     rcconfig.bmax );
        
        
        rcCalcGridSize(  rcconfig.bmin,
                       rcconfig.bmax,
                       rcconfig.cs,
                       &rcconfig.width,
                       &rcconfig.height );
        
        
        rcheightfield = rcAllocHeightfield();
        
        rcCreateHeightfield( *rcheightfield,
                            rcconfig.width,
                            rcconfig.height,
                            rcconfig.bmin,
                            rcconfig.bmax,
                            rcconfig.cs,
                            rcconfig.ch );
        
        
        navigation->triangle_flags = new unsigned char[ triangle_count ];
        
        memset( navigation->triangle_flags, 0, triangle_count * sizeof( unsigned char ) );
        
        rcMarkWalkableTriangles( rcconfig.walkableSlopeAngle,
                                ( float * )vertex_start,
                                (int)objmesh->uniqueVertexUVIndexList.size(),
//                                objmesh->n_objvertexdata,
                                indices,
                                triangle_count,
                                navigation->triangle_flags );
        
        
        rcRasterizeTriangles( ( float * )vertex_start,
                             (int)objmesh->uniqueVertexUVIndexList.size(),
//                             objmesh->n_objvertexdata,
                             indices,
                             navigation->triangle_flags,
                             triangle_count,
                             *rcheightfield,
                             rcconfig.walkableClimb );
        
        
        delete []navigation->triangle_flags;
        navigation->triangle_flags = NULL;
        
        free( vertex_start );
        free( indices      );
        
        
        rcFilterLowHangingWalkableObstacles(  rcconfig.walkableClimb,
                                            *rcheightfield );
        
        
        rcFilterLedgeSpans(  rcconfig.walkableHeight,
                           rcconfig.walkableClimb,
                           *rcheightfield );
        
        
        rcFilterWalkableLowHeightSpans(  rcconfig.walkableHeight,
                                       *rcheightfield );
        
        
        rccompactheightfield = rcAllocCompactHeightfield();
        
        rcBuildCompactHeightfield( rcconfig.walkableHeight,
                                  rcconfig.walkableClimb,
                                  RC_WALKABLE,
                                  *rcheightfield,
                                  *rccompactheightfield );
        
        rcFreeHeightField( rcheightfield );
        rcheightfield = NULL;
        
        rcErodeArea( RC_WALKABLE_AREA,
                    rcconfig.walkableRadius,
                    *rccompactheightfield );
        
        
        rcBuildDistanceField( *rccompactheightfield );
        
        
        rcBuildRegions( *rccompactheightfield,
                       rcconfig.borderSize,
                       rcconfig.minRegionSize,
                       rcconfig.mergeRegionSize );
        
        
        rccontourset = rcAllocContourSet();
        
        rcBuildContours( *rccompactheightfield,
                        rcconfig.maxSimplificationError,
                        rcconfig.maxEdgeLen,
                        *rccontourset );
        
        
        rcpolymesh = rcAllocPolyMesh();
        
        rcBuildPolyMesh( *rccontourset,
                        rcconfig.maxVertsPerPoly,
                        *rcpolymesh );
        
        
        rcpolymeshdetail = rcAllocPolyMeshDetail();
        
        rcBuildPolyMeshDetail( *rcpolymesh,
                              *rccompactheightfield,
                              rcconfig.detailSampleDist,
                              rcconfig.detailSampleMaxError,
                              *rcpolymeshdetail );
        
        
        rcFreeCompactHeightfield( rccompactheightfield );
        rccompactheightfield = NULL;
        
        rcFreeContourSet( rccontourset );
        rccontourset = NULL;
        
        
        if( rcconfig.maxVertsPerPoly <= DT_VERTS_PER_POLYGON )
        {
            dtNavMeshCreateParams dtnavmeshcreateparams;
            
            unsigned char *nav_data = NULL;
            
            int nav_data_size = 0;
            
            i = 0;
            while( i != rcpolymesh->npolys )
            {
                if( rcpolymesh->areas[ i ] == RC_WALKABLE_AREA )
                {
                    rcpolymesh->areas[ i ] = 0;
                    rcpolymesh->flags[ i ] = 0x01;
                }
                
                ++i;
            }
            
            
            memset( &dtnavmeshcreateparams, 0, sizeof( dtNavMeshCreateParams ) );
            
            dtnavmeshcreateparams.verts			   = rcpolymesh->verts;
            dtnavmeshcreateparams.vertCount		   = rcpolymesh->nverts;
            dtnavmeshcreateparams.polys			   = rcpolymesh->polys;
            dtnavmeshcreateparams.polyAreas		   = rcpolymesh->areas;
            dtnavmeshcreateparams.polyFlags		   = rcpolymesh->flags;
            dtnavmeshcreateparams.polyCount		   = rcpolymesh->npolys;
            dtnavmeshcreateparams.nvp			   = rcpolymesh->nvp;
            
            dtnavmeshcreateparams.detailMeshes	   = rcpolymeshdetail->meshes;
            dtnavmeshcreateparams.detailVerts	   = rcpolymeshdetail->verts;
            dtnavmeshcreateparams.detailVertsCount = rcpolymeshdetail->nverts;
            dtnavmeshcreateparams.detailTris       = rcpolymeshdetail->tris;
            dtnavmeshcreateparams.detailTriCount   = rcpolymeshdetail->ntris;
            
            dtnavmeshcreateparams.walkableHeight   = navigation->navigationconfiguration.agent_height;
            dtnavmeshcreateparams.walkableRadius   = navigation->navigationconfiguration.agent_radius;
            dtnavmeshcreateparams.walkableClimb    = navigation->navigationconfiguration.agent_max_climb;
            
            rcVcopy( dtnavmeshcreateparams.bmin, rcpolymesh->bmin );
            rcVcopy( dtnavmeshcreateparams.bmax, rcpolymesh->bmax );
            
            dtnavmeshcreateparams.cs = rcconfig.cs;
            dtnavmeshcreateparams.ch = rcconfig.ch;
            
            
            dtCreateNavMeshData( &dtnavmeshcreateparams,
                                &nav_data,
                                &nav_data_size );
            
            if( !nav_data ) return 0;
            
            navigation->dtnavmesh = dtAllocNavMesh();
            
            navigation->dtnavmesh->init( nav_data,
                                        nav_data_size,
                                        DT_TILE_FREE_DATA,
                                        NAVIGATION_MAX_NODE );
            
            rcFreePolyMesh( rcpolymesh );
            rcpolymesh = NULL;
            
            rcFreePolyMeshDetail( rcpolymeshdetail );
            rcpolymeshdetail = NULL;
            
            return 1;
        }
        
        return 0;
    }
Esempio n. 12
0
inline void VectorCeil(vec3_t in)
{
	in[0] = ceilf(in[0]);
	in[1] = ceilf(in[1]);
	in[2] = ceilf(in[2]);
}
Esempio n. 13
0
int
process_cl (struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out)
{
  dt_iop_nlmeans_params_t *d = (dt_iop_nlmeans_params_t *)piece->data;
  dt_iop_nlmeans_global_data_t *gd = (dt_iop_nlmeans_global_data_t *)self->data;


  const int devid = piece->pipe->devid;
  const int width = roi_in->width;
  const int height = roi_in->height;

  cl_mem dev_U4 = NULL;
  cl_mem dev_U4_t = NULL;

  cl_int err = -999;

  const int P = ceilf(d->radius * roi_in->scale / piece->iscale); // pixel filter size
  const int K = ceilf(7 * roi_in->scale / piece->iscale); // nbhood
  const float sharpness = 3000.0f/(1.0f+d->strength);

  if(P < 1)
  {
    size_t origin[] = { 0, 0, 0};
    size_t region[] = { width, height, 1};
    err = dt_opencl_enqueue_copy_image(devid, dev_in, dev_out, origin, origin, region);
    if (err != CL_SUCCESS) goto error;
    return TRUE;
  }

  float max_L = 120.0f, max_C = 512.0f;
  float nL = 1.0f/max_L, nC = 1.0f/max_C;
  float nL2 = nL*nL, nC2 = nC*nC;
  //float weight[4] = { powf(d->luma, 0.6), powf(d->chroma, 0.6), powf(d->chroma, 0.6), 1.0f };
  float weight[4] = { d->luma, d->chroma, d->chroma, 1.0f };

  dev_U4 = dt_opencl_alloc_device(devid, roi_out->width, roi_out->height, sizeof(float));
  if (dev_U4 == NULL) goto error;

  dev_U4_t = dt_opencl_alloc_device(devid, roi_out->width, roi_out->height, sizeof(float));
  if (dev_U4_t == NULL) goto error;


  // prepare local work group
  size_t maxsizes[3] = { 0 };        // the maximum dimensions for a work group
  size_t workgroupsize = 0;          // the maximum number of items in a work group
  unsigned long localmemsize = 0;    // the maximum amount of local memory we can use
  size_t kernelworkgroupsize = 0;    // the maximum amount of items in work group of the kernel
  // assuming this is the same for nlmeans_horiz and nlmeans_vert

  // make sure blocksize is not too large
  int blocksize = BLOCKSIZE;
  if(dt_opencl_get_work_group_limits(devid, maxsizes, &workgroupsize, &localmemsize) == CL_SUCCESS &&
      dt_opencl_get_kernel_work_group_size(devid, gd->kernel_nlmeans_horiz, &kernelworkgroupsize) == CL_SUCCESS)
  {
    // reduce blocksize step by step until it fits to limits
    while(blocksize > maxsizes[0] || blocksize > maxsizes[1] || blocksize > kernelworkgroupsize
          || blocksize > workgroupsize || (blocksize+2*P)*sizeof(float) > localmemsize)
    {
      if(blocksize == 1) break;
      blocksize >>= 1;
    }
  }
  else
  {
Esempio n. 14
0
static qboolean VID_CreateWindow( int width, int height, qboolean fullscreen )
{
    RECT			r;
    int				stylebits;
    int				x, y, w, h, exstyle;

    /* Register the frame class */
    if (!s_classRegistered)
    {
        WNDCLASS wc;

        memset( &wc, 0, sizeof( wc ) );
        wc.style         = 0;
        wc.lpfnWndProc   = (WNDPROC)glw_state.wndproc;
        wc.cbClsExtra    = 0;
        wc.cbWndExtra    = 0;
        wc.hInstance     = glw_state.hInstance;
        wc.hIcon         = LoadIcon(glw_state.hInstance, MAKEINTRESOURCE(IDI_ICON1));
        wc.hCursor       = LoadCursor (NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
        wc.lpszMenuName  = 0;
        wc.lpszClassName = WINDOW_CLASS_NAME;

        if (!RegisterClass(&wc)) {
            PrintWinError("VID_CreateWindow: RegisterClass", true);
            return false;
        }

        s_classRegistered = true;
    }

    if (fullscreen) {
        exstyle = WS_EX_TOPMOST;
        stylebits = WS_POPUP|WS_VISIBLE;

        w = width;
        h = height;
        x = 0;
        y = 0;
    }
    else {
        exstyle = 0;
        stylebits = WINDOW_STYLE;

        r.left = 0;
        r.top = 0;
        r.right  = width;
        r.bottom = height;

        AdjustWindowRect (&r, stylebits, FALSE);

        w = r.right - r.left;
        h = r.bottom - r.top;
        x = vid_xpos->integer;
        y = vid_ypos->integer;
    }

    glw_state.hWnd = CreateWindowEx (
                         exstyle,
                         WINDOW_CLASS_NAME,
                         APPLICATION,
                         stylebits,
                         x, y, w, h,
                         NULL,
                         NULL,
                         glw_state.hInstance,
                         NULL);

    if (!glw_state.hWnd) {
        PrintWinError("VID_CreateWindow: CreateWindowEx", true);
        return false;
    }

    ShowWindow( glw_state.hWnd, SW_SHOW );
    UpdateWindow( glw_state.hWnd );

    // init all the gl stuff for the window
    if (!GLimp_InitGL())
    {
        Com_Printf ( "VID_CreateWindow() - GLimp_InitGL failed\n");

        if (glw_state.hGLRC) {
            qwglDeleteContext( glw_state.hGLRC );
            glw_state.hGLRC = NULL;
        }
        if (glw_state.hDC) {
            ReleaseDC( glw_state.hWnd, glw_state.hDC );
            glw_state.hDC = NULL;
        }

        ShowWindow( glw_state.hWnd, SW_HIDE );
        DestroyWindow( glw_state.hWnd );
        glw_state.hWnd = NULL;
        return false;
    }

    SetForegroundWindow( glw_state.hWnd );
    SetFocus( glw_state.hWnd );

    vid_scaled_width = (int)ceilf((float)width / gl_scale->value);
    vid_scaled_height = (int)ceilf((float)height / gl_scale->value);

    //round to powers of 8/2 to avoid blackbars
    width = (vid_scaled_width+7)&~7;
    height = (vid_scaled_height+1)&~1;

    // let the sound and input subsystems know about the new window
    VID_NewWindow( width, height );
    //VID_NewWindow( width / gl_scale->value, height / gl_scale->value);

    return true;
}
Esempio n. 15
0
/*
 ** Here is the fun part, the median-cut colormap generator.  This is based
 ** on Paul Heckbert's paper, "Color Image Quantization for Frame Buffer
 ** Display," SIGGRAPH 1982 Proceedings, page 297.
 */
LIQ_PRIVATE colormap *mediancut(histogram *hist, const float min_opaque_val, unsigned int newcolors, const double target_mse, const double max_mse, void* (*malloc)(size_t), void (*free)(void*))
{
    hist_item *achv = hist->achv;
    struct box bv[newcolors];

    /*
     ** Set up the initial box.
     */
    bv[0].ind = 0;
    bv[0].colors = hist->size;
    bv[0].color = averagepixels(bv[0].colors, &achv[bv[0].ind], min_opaque_val, (f_pixel){0.5,0.5,0.5,0.5});
    bv[0].variance = box_variance(achv, &bv[0]);
    bv[0].max_error = box_max_error(achv, &bv[0]);
    bv[0].sum = 0;
    bv[0].total_error = -1;
    for(unsigned int i=0; i < bv[0].colors; i++) bv[0].sum += achv[i].adjusted_weight;

    unsigned int boxes = 1;

    // remember smaller palette for fast searching
    colormap *representative_subset = NULL;
    unsigned int subset_size = ceilf(powf(newcolors,0.7f));

    /*
     ** Main loop: split boxes until we have enough.
     */
    while (boxes < newcolors) {

        if (boxes == subset_size) {
            representative_subset = pam_colormap(boxes, malloc, free);
            set_colormap_from_boxes(representative_subset, bv, boxes, achv);
        }

        // first splits boxes that exceed quality limit (to have colors for things like odd green pixel),
        // later raises the limit to allow large smooth areas/gradients get colors.
        const double current_max_mse = max_mse + (boxes/(double)newcolors)*16.0*max_mse;
        const int bi = best_splittable_box(bv, boxes, current_max_mse);
        if (bi < 0)
            break;        /* ran out of colors! */

        unsigned int indx = bv[bi].ind;
        unsigned int clrs = bv[bi].colors;

        /*
         Classic implementation tries to get even number of colors or pixels in each subdivision.

         Here, instead of popularity I use (sqrt(popularity)*variance) metric.
         Each subdivision balances number of pixels (popular colors) and low variance -
         boxes can be large if they have similar colors. Later boxes with high variance
         will be more likely to be split.

         Median used as expected value gives much better results than mean.
         */

        const double halfvar = prepare_sort(&bv[bi], achv);
        double lowervar=0;

        // hist_item_sort_halfvar sorts and sums lowervar at the same time
        // returns item to break at …minus one, which does smell like an off-by-one error.
        hist_item *break_p = hist_item_sort_halfvar(&achv[indx], clrs, &lowervar, halfvar);
        unsigned int break_at = MIN(clrs-1, break_p - &achv[indx] + 1);

        /*
         ** Split the box.
         */
        double sm = bv[bi].sum;
        double lowersum = 0;
        for(unsigned int i=0; i < break_at; i++) lowersum += achv[indx + i].adjusted_weight;

        const f_pixel previous_center = bv[bi].color;
        bv[bi].colors = break_at;
        bv[bi].sum = lowersum;
        bv[bi].color = averagepixels(bv[bi].colors, &achv[bv[bi].ind], min_opaque_val, previous_center);
        bv[bi].total_error = -1;
        bv[bi].variance = box_variance(achv, &bv[bi]);
        bv[bi].max_error = box_max_error(achv, &bv[bi]);
        bv[boxes].ind = indx + break_at;
        bv[boxes].colors = clrs - break_at;
        bv[boxes].sum = sm - lowersum;
        bv[boxes].color = averagepixels(bv[boxes].colors, &achv[bv[boxes].ind], min_opaque_val, previous_center);
        bv[boxes].total_error = -1;
        bv[boxes].variance = box_variance(achv, &bv[boxes]);
        bv[boxes].max_error = box_max_error(achv, &bv[boxes]);

        ++boxes;

        if (total_box_error_below_target(target_mse, bv, boxes, hist)) {
            break;
        }
    }

    colormap *map = pam_colormap(boxes, malloc, free);
    set_colormap_from_boxes(map, bv, boxes, achv);

    map->subset_palette = representative_subset;
    adjust_histogram(achv, map, bv, boxes);

    return map;
}
Esempio n. 16
0
	bool NavMesh::BuildMesh()
	{
		dtStatus status;
		if (!m_geom || !m_geom->getMesh()) return false;
		m_tmproc->init(m_geom);
		// Init cache
		const float* bmin = m_geom->getMeshBoundsMin();
		const float* bmax = m_geom->getMeshBoundsMax();
		int gw = 0, gh = 0;
		rcCalcGridSize(bmin, bmax, m_cellSize, &gw, &gh);
		const int ts = (int)m_tileSize;
		const int tw = (gw + ts-1) / ts;
		const int th = (gh + ts-1) / ts;
		// Generation params.
		rcConfig cfg;
		memset(&cfg, 0, sizeof(cfg));
		cfg.cs = m_cellSize;
		cfg.ch = m_cellHeight;
		cfg.walkableSlopeAngle = m_agentMaxSlope;
		cfg.walkableHeight = (int)ceilf(m_agentHeight / cfg.ch);
		cfg.walkableClimb = (int)floorf(m_agentMaxClimb / cfg.ch);
		cfg.walkableRadius = (int)ceilf(m_agentRadius / cfg.cs);
		cfg.maxEdgeLen = (int)(m_edgeMaxLen / m_cellSize);
		cfg.maxSimplificationError = m_edgeMaxError;
		cfg.minRegionArea = (int)rcSqr(m_regionMinSize);		// Note: area = size*size
		cfg.mergeRegionArea = (int)rcSqr(m_regionMergeSize);	// Note: area = size*size
		cfg.maxVertsPerPoly = (int)m_vertsPerPoly;
		cfg.tileSize = (int)m_tileSize;
		cfg.borderSize = cfg.walkableRadius + 3; // Reserve enough padding.
		cfg.width = cfg.tileSize + cfg.borderSize*2;
		cfg.height = cfg.tileSize + cfg.borderSize*2;
		cfg.detailSampleDist = m_detailSampleDist < 0.9f ? 0 : m_cellSize * m_detailSampleDist;
		cfg.detailSampleMaxError = m_cellHeight * m_detailSampleMaxError;
		rcVcopy(cfg.bmin, bmin);
		rcVcopy(cfg.bmax, bmax);
		// Tile cache params.
		dtTileCacheParams tcparams;
		memset(&tcparams, 0, sizeof(tcparams));
		rcVcopy(tcparams.orig, bmin);
		tcparams.cs = m_cellSize;
		tcparams.ch = m_cellHeight;
		tcparams.width = (int)m_tileSize;
		tcparams.height = (int)m_tileSize;
		tcparams.walkableHeight = m_agentHeight;
		tcparams.walkableRadius = m_agentRadius;
		tcparams.walkableClimb = m_agentMaxClimb;
		tcparams.maxSimplificationError = m_edgeMaxError;
		tcparams.maxTiles = tw*th*EXPECTED_LAYERS_PER_TILE;
		tcparams.maxObstacles = 128;

		dtFreeTileCache(m_tileCache);

		m_tileCache = dtAllocTileCache();
		if (!m_tileCache) return false;
		status = m_tileCache->init(&tcparams, m_talloc, m_tcomp, m_tmproc);
		if (dtStatusFailed(status)) return false;

		dtFreeNavMesh(m_navMesh);

		m_navMesh = dtAllocNavMesh();
		if (!m_navMesh) return false;

		dtNavMeshParams params;
		memset(&params, 0, sizeof(params));
		rcVcopy(params.orig, m_geom->getMeshBoundsMin());
		params.tileWidth = m_tileSize*m_cellSize;
		params.tileHeight = m_tileSize*m_cellSize;
		params.maxTiles = m_maxTiles;
		params.maxPolys = m_maxPolysPerTile;

		status = m_navMesh->init(&params);
		if (dtStatusFailed(status)) return false;

		status = m_navQuery->init(m_navMesh, 2048);
		if (dtStatusFailed(status)) return false;

		for (int y = 0; y < th; ++y)
		{
			for (int x = 0; x < tw; ++x)
			{
				TileCacheData tiles[MAX_LAYERS];
				memset(tiles, 0, sizeof(tiles));
				int n = rasterizeTileLayers(m_geom, x, y, cfg, tiles, MAX_LAYERS);
				for (int i = 0; i < n; ++i)
				{
					TileCacheData* tile = &tiles[i];
					status = m_tileCache->addTile(tile->data, tile->dataSize, DT_COMPRESSEDTILE_FREE_DATA, 0);
					if (dtStatusFailed(status))
					{
						dtFree(tile->data);
						tile->data = 0;
						continue;
					}
				}
			}
		}
		for (int y = 0; y < th; ++y)
			for (int x = 0; x < tw; ++x)
				m_tileCache->buildNavMeshTilesAt(x,y, m_navMesh);
	}
Esempio n. 17
0
void SimRender::AngularStepFromChordLen(const float maxChordLength, const float radius, float& out_stepAngle, unsigned& out_numSteps)
{
	float maxAngle = Geometry::ChordToCentralAngle(maxChordLength, radius);
	out_numSteps = ceilf(float(2*M_PI)/maxAngle);
	out_stepAngle = float(2*M_PI)/out_numSteps;
}
Esempio n. 18
0
bool imguiSlider(const char* text, float* val, float vmin, float vmax, float vinc, bool enabled)
{
	g_state.widgetId++;
	unsigned int id = (g_state.areaId<<16) | g_state.widgetId;
	
	int x = g_state.widgetX;
	int y = g_state.widgetY - BUTTON_HEIGHT;
	int w = g_state.widgetW;
	int h = SLIDER_HEIGHT;
	g_state.widgetY -= SLIDER_HEIGHT + DEFAULT_SPACING;

	addGfxCmdRoundedRect((float)x, (float)y, (float)w, (float)h, 4.0f, imguiRGBA(0,0,0,128));

	const int range = w - SLIDER_MARKER_WIDTH;

	float u = (*val - vmin) / (vmax-vmin);
	if (u < 0) u = 0;
	if (u > 1) u = 1;
	int m = (int)(u * range);

	bool over = enabled && inRect(x+m, y, SLIDER_MARKER_WIDTH, SLIDER_HEIGHT);
	bool res = buttonLogic(id, over);
	bool valChanged = false;

	if (isActive(id))
	{
		if (g_state.wentActive)
		{
			g_state.dragX = g_state.mx;
			g_state.dragOrig = u;
		}
		if (g_state.dragX != g_state.mx)
		{
			u = g_state.dragOrig + (float)(g_state.mx - g_state.dragX) / (float)range;
			if (u < 0) u = 0;
			if (u > 1) u = 1;
			*val = vmin + u*(vmax-vmin);
			*val = floorf(*val / vinc)*vinc; // Snap to vinc
			m = (int)(u * range);
			valChanged = true;
		}
	}

	if (isActive(id))
		addGfxCmdRoundedRect((float)(x+m), (float)y, (float)SLIDER_MARKER_WIDTH, (float)SLIDER_HEIGHT, 4.0f, imguiRGBA(255,255,255,255));
	else
		addGfxCmdRoundedRect((float)(x+m), (float)y, (float)SLIDER_MARKER_WIDTH, (float)SLIDER_HEIGHT, 4.0f, isHot(id) ? imguiRGBA(255,196,0,128) : imguiRGBA(255,255,255,64));

	// TODO: fix this, take a look at 'nicenum'.
	int digits = (int)(ceilf(log10f(vinc)));
	char fmt[16];
	snprintf(fmt, 16, "%%.%df", digits >= 0 ? 0 : -digits);
	char msg[128];
	snprintf(msg, 128, fmt, *val);
	
	if (enabled)
	{
		addGfxCmdText(x+SLIDER_HEIGHT/2, y+SLIDER_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_LEFT, text, isHot(id) ? imguiRGBA(255,196,0,255) : imguiRGBA(255,255,255,200));
		addGfxCmdText(x+w-SLIDER_HEIGHT/2, y+SLIDER_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_RIGHT, msg, isHot(id) ? imguiRGBA(255,196,0,255) : imguiRGBA(255,255,255,200));
	}
	else
	{
		addGfxCmdText(x+SLIDER_HEIGHT/2, y+SLIDER_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_LEFT, text, imguiRGBA(128,128,128,200));
		addGfxCmdText(x+w-SLIDER_HEIGHT/2, y+SLIDER_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_RIGHT, msg, imguiRGBA(128,128,128,200));
	}

	return res || valChanged;
}
/*
 * sino is freed by caller
 * ans is freed by caller
 *
 * This function is the top-level function for recursive backprojection.
 * It makes a call to 'direct_forw' once size<=baseSize.
 */
void bp_forw(sinograms* sino,int size,myFloat* tau,image* ans)
{
  sinograms* newSino;
  image* subImage;

  int i,j,m,n,k,p,u,v;

  myFloat* curRow;
  myFloat temp1,temp2;

  int pp;

  int newSize;
  int numSino;
  int sinoSize;
  int offsetX;
  int offsetY;

  myFloat shiftX,shiftY; 

  myFloat* nu_i;
  myFloat* nu_i2;
  myFloat* nu_temp;
  myFloat nu_p,nu_2n;

  int P = sino->num;
  myFloat angle;

  myFloat sum=0;
  myFloat shift;

  int newSinoSize;
  int newNumSino;
  int constShiftingFactor;
  int shiftingFactor; 

  if( size<=baseSize || sino->num <= 1 ){ 
    //BASE CASE!!!!
    direct_forw( sino , size , tau , ans );  
    return;
  } 

  else{
    printf( "\n\nGeneral case!!!!\n\n" );
    //GENERAL CASE
    subImage = ( image* ) malloc( 1 * sizeof( image ) );          //prepare subImage for recursive call
    newSize = size / 2;
    numSino = ( sino->num );
    sinoSize = ( sino->size );

    subImage->size = newSize;
    ( subImage->pixel ) = ( myFloat** )malloc( newSize * sizeof( myFloat* ) );
    shift = ( myFloat )size/4 * oneOverT;  //save some computations when computing nu's by premultiply with 1/T

    newSinoSize = ceilf((myFloat)sinoSize/2) + (sinoSize%4==3 || sinoSize%4==2?1:0);
    constShiftingFactor = ((myFloat)newSinoSize/2) - ((myFloat)sinoSize/2);    

    //for each part (that we break the image into)
    for(i=0;i<NUM_PARTS;i++){
        if(i==0){
	        shiftX = shift;
	        shiftY = shift;
        }
        else if(i==1){
	        shiftX = -shift;
	        shiftY = shift;
        }
        else if(i==2){
	        shiftX = -shift;
	        shiftY = -shift;
        }
        else {
	        shiftX = shift;
	        shiftY = -shift;
        }


      /************/

      nu_i = (myFloat*)malloc(numSino*sizeof(myFloat));
      nu_i2 = (myFloat*)malloc(numSino*sizeof(myFloat));          
      nu_temp = (myFloat*)malloc(numSino*sizeof(myFloat));

      for(p=0;p<numSino;p++){
	    //for each angle, compute nu_i,p
	    nu_i[p] = nu_forw(tau[p],shiftX,shiftY,(sino->sine)[p],(sino->cosine)[p]);//,oneOverT);
	    nu_temp[p] = rintf(nu_i[p]);
      }//end for p

      //nu_i are real nu's (for this quadrant, for all theta's)
      //nu_temp are rounded nu's

      //decide whether to downsample
      if(size<=dwnsplSize){
        printf("\nIter 1\n");
	    //throw away half the projections as usual
	    newSino = newSinoForNextIter_forw(sino,newSinoSize,constShiftingFactor,nu_i);
	    pp = 2;   
      }
      else {  
	    //keep all of them!
        printf("\nIter 2\n");  
	    newSino = newSinoForNextIter_forw2(sino,newSinoSize,constShiftingFactor,nu_i);
	    pp = 1;   
      } 

      /************/


      
      //manipulate the right part of the image
      if(i<2){
	    // 0 and 1
	    offsetY = newSize;
      }
      else {
	    // 2 and 3
	    offsetY = 0;
      }

      if(i==0 || i==3){
	    // 0 and 3
	    offsetX = newSize;
      }
      else {
	    // 1 and 2
	    offsetX = 0;
      }

      //make subImages point to appropriate parts of the big image
      for(m=0;m<newSize;m++){
	    (subImage->pixel)[m] = (ans->pixel)[m+offsetY] + offsetX;
      }
      
      newNumSino = (newSino->num);
      //for each nu_p, compute <nu_p>
      for(p=0;p<newNumSino;p++){
        nu_i2[p] = nu_i[p];
	    nu_i[p] = nu_i[pp*p]-nu_temp[pp*p];
      }


      //call bp_forw recursively
      /////////////////////////////////////////////////
      bp_forw(newSino,/*ker,*/newSize,nu_i,subImage);     //
      /////////////////////////////////////////////////
      
      
      if( size <= dwnsplSize ){
        printf( "\nTobe done\n" );
      }

      else{
        for(n=0;n<newNumSino;n++){
            shiftingFactor = rintf(nu_i2[n]) + constShiftingFactor;      
            for(m=0;m<newSinoSize;m++){
                (sino->sino)[n][m-shiftingFactor] += (newSino->sino)[n][m];
            }//end for m
        }//end for n        
      }//end if

      //free(subImage);
      //free(subImage->pixel);     
      //freeSino_forw(newSino);
      //free(newSino);
      //subImage = NULL;
      //free(nu_i);
      //free(nu_temp);
      //nu_i = NULL;
    
    }//end for i

    free(subImage);
    free(subImage->pixel);

    freeSino_forw(newSino);
    free(newSino);
    newSino = NULL;
    free(nu_i);
    free(nu_temp);
    nu_i = NULL;     
    
    //do not free subImage's pixels, because they are the output!
    
    return;

  }//end if not base case


}//end function bp_forw
Esempio n. 20
0
struct item_data item_bench(const struct p_bench_item *item,
                            struct p_bench_specification *spec)
{
    struct item_data data, best = { .end = ~(0ULL) };
    uint64_t item_start_time = platform_clock();

    /* Warm up caches, branch predictors etc. */
    /* Calculate inner loop. */
    int inner_loop;
    data.start = platform_clock();
    for (int i = 0; i < 50; i++)
        item->benchmark(spec);
    data.end = platform_clock();

    {
        float tmp = data.end - data.start;
        tmp /= 50.0f;
        /* 50k us seems to work */
        tmp = 50000.0f / tmp;
        inner_loop = ceilf(tmp);
    }

    /* Repeat tests to get more stable results between runs */
    while (true) {
        /* Measure 10 iterations so the clocksource's resolution doesn't
         * play tricks on us */
        data.start = platform_clock();
        for (int j = 0; j < inner_loop; j++)
            item->benchmark(spec);
        data.end = platform_clock();

        /* Use best measurement */
        if (best.end - best.start > data.end - data.start)
            best = data;

        /* Test each function for 1/2 second */
        if (data.end - item_start_time >= 500000000ULL)
            break;
    }
    {
        /* Adjust for iterations in inner loop above */
        float tmp = best.end - best.start;
        tmp /= (float) inner_loop;
        best.end = best.start + tmp;
    }
    return best;
}

int main(void)
{
    struct p_bench_specification spec = { 0 };
    char *raw_mem = NULL;
    spec.current_size = MAX_ELEMS;

    setup_memory(&spec.mem, &raw_mem, spec.current_size);
    bench_printf(";name, size, duration (ns)\n");
    for (const struct p_bench_item *item = benchmark_items; item->name != NULL;
         ++item) {
        struct item_data best;
        bool consistent = false;

        best = item_bench(item, &spec);
        for (int tries = 0; tries < 50; tries++) {
            struct item_data snd;
            float fst_time, snd_time;

            /* Benchmark again ... */
            snd = item_bench(item, &spec);

            fst_time = best.end - best.start;
            snd_time = snd.end - snd.start;

            /* ... and start over if results deviate too much */
            if (fst_time / snd_time < 0.995 || snd_time / fst_time < 0.995) {
                /* Take average so abnormally low results converge over time */
                best.end += (snd_time - fst_time) / 2.0f;
                usleep(100000);

                continue;
            }

            if (fst_time > snd_time)
                best = snd;

            consistent = true;
            break;
        }
        if (!consistent) {
            fprintf(stderr, ";WARNING: %s not consistent\n", item->name);
            fflush(stderr);
        }
        item_done(&best, &spec, item->name);
    }
    return EXIT_SUCCESS;
}
#else /* __epiphany__ */
int main(void)
{
    struct p_bench_specification spec = { 0 };
    char *raw_mem = NULL;
    spec.current_size = MAX_ELEMS;
    uint32_t nbench = 0;

    setup_memory(&spec.mem, &raw_mem, spec.current_size);
    bench_printf(";name, size, duration (ns)\n");
    for (const struct p_bench_item *item = benchmark_items; item->name != NULL;
         ++item) {
        struct item_data data;

        data.start = platform_clock();
        item->benchmark(&spec);
        data.end = platform_clock();

        strcpy(epiphany_results[nbench].name, item->name);
        epiphany_results[nbench].ns = data.end - data.start;
        epiphany_results[nbench].size = (uint64_t) spec.current_size;
        nbench++;
        epiphany_status->nbench = nbench;
    }
    epiphany_status->done = 1;
    return EXIT_SUCCESS;
}
#endif

static void setup_output_pointers(struct p_bench_raw_memory *mem, void *p)
{
    /* Assume largest type is 64 bits */

    /* TODO: All pointers point to same memory region so output will be bogus */
    mem->o1.p_u64 = p;
    mem->o2.p_u64 = p;
    mem->o3.p_u64 = p;
    mem->o4.p_u64 = p;
}
Esempio n. 21
0
int8	i8ceils(int8 x) {
  return (int8)(ceilf(x));
}
inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, GlyphBuffer* glyphBuffer)
{
    bool rtl = m_run.rtl();
    bool hasExtraSpacing = (m_font->letterSpacing() || m_font->wordSpacing() || m_expansion) && !m_run.spacingDisabled();

    float widthSinceLastRounding = m_runWidthSoFar;
    m_runWidthSoFar = floorf(m_runWidthSoFar);
    widthSinceLastRounding -= m_runWidthSoFar;

    float lastRoundingWidth = m_finalRoundingWidth;
    FloatRect bounds;

    const SimpleFontData* primaryFont = m_font->primaryFont();
    const SimpleFontData* lastFontData = primaryFont;
    int lastGlyphCount = glyphBuffer ? glyphBuffer->size() : 0;

    UChar32 character = 0;
    unsigned clusterLength = 0;
    CharactersTreatedAsSpace charactersTreatedAsSpace;
    String normalizedSpacesStringCache;
    while (textIterator.consume(character, clusterLength)) {
        unsigned advanceLength = clusterLength;
        int currentCharacter = textIterator.currentCharacter();
        const GlyphData& glyphData = glyphDataForCharacter(character, rtl, currentCharacter, advanceLength, normalizedSpacesStringCache);
        Glyph glyph = glyphData.glyph;
        const SimpleFontData* fontData = glyphData.fontData;

        ASSERT(fontData);

        // Now that we have a glyph and font data, get its width.
        float width;
        if (character == '\t' && m_run.allowTabs())
            width = m_font->tabWidth(*fontData, m_run.tabSize(), m_run.xPos() + m_runWidthSoFar + widthSinceLastRounding);
        else {
            width = fontData->widthForGlyph(glyph);

            // SVG uses horizontalGlyphStretch(), when textLength is used to stretch/squeeze text.
            width *= m_run.horizontalGlyphStretch();

            // We special case spaces in two ways when applying word rounding.
            // First, we round spaces to an adjusted width in all fonts.
            // Second, in fixed-pitch fonts we ensure that all characters that
            // match the width of the space character have the same width as the space character.
            if (m_run.applyWordRounding() && width == fontData->spaceWidth() && (fontData->pitch() == FixedPitch || glyph == fontData->spaceGlyph()))
                width = fontData->adjustedSpaceWidth();
        }

        if (fontData != lastFontData && width) {
            if (shouldApplyFontTransforms()) {
                m_runWidthSoFar += applyFontTransforms(glyphBuffer, m_run.ltr(), lastGlyphCount, lastFontData, *this, m_typesettingFeatures, charactersTreatedAsSpace);
                lastGlyphCount = glyphBuffer->size(); // applyFontTransforms doesn't update when there had been only one glyph.
            }

            lastFontData = fontData;
            if (m_fallbackFonts && fontData != primaryFont) {
                // FIXME: This does a little extra work that could be avoided if
                // glyphDataForCharacter() returned whether it chose to use a small caps font.
                if (!m_font->isSmallCaps() || character == u_toupper(character))
                    m_fallbackFonts->add(fontData);
                else {
                    const GlyphData& uppercaseGlyphData = m_font->glyphDataForCharacter(u_toupper(character), rtl);
                    if (uppercaseGlyphData.fontData != primaryFont)
                        m_fallbackFonts->add(uppercaseGlyphData.fontData);
                }
            }
        }

        if (hasExtraSpacing) {
            // Account for letter-spacing.
            if (width && m_font->letterSpacing())
                width += m_font->letterSpacing();

            static bool expandAroundIdeographs = Font::canExpandAroundIdeographsInComplexText();
            bool treatAsSpace = Font::treatAsSpace(character);
            if (treatAsSpace || (expandAroundIdeographs && Font::isCJKIdeographOrSymbol(character))) {
                // Distribute the run's total expansion evenly over all expansion opportunities in the run.
                if (m_expansion) {
                    float previousExpansion = m_expansion;
                    if (!treatAsSpace && !m_isAfterExpansion) {
                        // Take the expansion opportunity before this ideograph.
                        m_expansion -= m_expansionPerOpportunity;
                        float expansionAtThisOpportunity = !m_run.applyWordRounding() ? m_expansionPerOpportunity : roundf(previousExpansion) - roundf(m_expansion);
                        m_runWidthSoFar += expansionAtThisOpportunity;
                        if (glyphBuffer) {
                            if (glyphBuffer->isEmpty()) {
                                if (m_forTextEmphasis)
                                    glyphBuffer->add(fontData->zeroWidthSpaceGlyph(), fontData, m_expansionPerOpportunity, currentCharacter);
                                else
                                    glyphBuffer->add(fontData->spaceGlyph(), fontData, expansionAtThisOpportunity, currentCharacter);
                            } else
                                glyphBuffer->expandLastAdvance(expansionAtThisOpportunity);
                        }
                        previousExpansion = m_expansion;
                    }
                    if (m_run.allowsTrailingExpansion() || (m_run.ltr() && currentCharacter + advanceLength < static_cast<size_t>(m_run.length()))
                        || (m_run.rtl() && currentCharacter)) {
                        m_expansion -= m_expansionPerOpportunity;
                        width += !m_run.applyWordRounding() ? m_expansionPerOpportunity : roundf(previousExpansion) - roundf(m_expansion);
                        m_isAfterExpansion = true;
                    }
                } else
                    m_isAfterExpansion = false;

                // Account for word spacing.
                // We apply additional space between "words" by adding width to the space character.
                if (treatAsSpace && (character != '\t' || !m_run.allowTabs()) && (currentCharacter || character == noBreakSpace) && m_font->wordSpacing())
                    width += m_font->wordSpacing();
            } else
                m_isAfterExpansion = false;
        }

        if (shouldApplyFontTransforms() && glyphBuffer && Font::treatAsSpace(character))
            charactersTreatedAsSpace.append(std::make_pair(glyphBuffer->size(),
                OriginalAdvancesForCharacterTreatedAsSpace(character == ' ', glyphBuffer->size() ? glyphBuffer->advanceAt(glyphBuffer->size() - 1).width() : 0, width)));

        if (m_accountForGlyphBounds) {
            bounds = fontData->boundsForGlyph(glyph);
            if (!currentCharacter)
                m_firstGlyphOverflow = std::max<float>(0, -bounds.x());
        }

        if (m_forTextEmphasis && !Font::canReceiveTextEmphasis(character))
            glyph = 0;

        // Advance past the character we just dealt with.
        textIterator.advance(advanceLength);

        float oldWidth = width;

        // Force characters that are used to determine word boundaries for the rounding hack
        // to be integer width, so following words will start on an integer boundary.
        if (m_run.applyWordRounding() && Font::isRoundingHackCharacter(character)) {
            width = ceilf(width);

            // Since widthSinceLastRounding can lose precision if we include measurements for
            // preceding whitespace, we bypass it here.
            m_runWidthSoFar += width;

            // Since this is a rounding hack character, we should have reset this sum on the previous
            // iteration.
            ASSERT(!widthSinceLastRounding);
        } else {
            // Check to see if the next character is a "rounding hack character", if so, adjust
            // width so that the total run width will be on an integer boundary.
            if ((m_run.applyWordRounding() && textIterator.currentCharacter() < m_run.length() && Font::isRoundingHackCharacter(*(textIterator.characters())))
                || (m_run.applyRunRounding() && textIterator.currentCharacter() >= m_run.length())) {
                float totalWidth = widthSinceLastRounding + width;
                widthSinceLastRounding = ceilf(totalWidth);
                width += widthSinceLastRounding - totalWidth;
                m_runWidthSoFar += widthSinceLastRounding;
                widthSinceLastRounding = 0;
            } else
                widthSinceLastRounding += width;
        }

        if (glyphBuffer)
            glyphBuffer->add(glyph, fontData, (rtl ? oldWidth + lastRoundingWidth : width), currentCharacter);

        lastRoundingWidth = width - oldWidth;

        if (m_accountForGlyphBounds) {
            m_maxGlyphBoundingBoxY = std::max(m_maxGlyphBoundingBoxY, bounds.maxY());
            m_minGlyphBoundingBoxY = std::min(m_minGlyphBoundingBoxY, bounds.y());
            m_lastGlyphOverflow = std::max<float>(0, bounds.maxX() - width);
        }
    }

    if (shouldApplyFontTransforms())
        m_runWidthSoFar += applyFontTransforms(glyphBuffer, m_run.ltr(), lastGlyphCount, lastFontData, *this, m_typesettingFeatures, charactersTreatedAsSpace);

    unsigned consumedCharacters = textIterator.currentCharacter() - m_currentCharacter;
    m_currentCharacter = textIterator.currentCharacter();
    m_runWidthSoFar += widthSinceLastRounding;
    m_finalRoundingWidth = lastRoundingWidth;
    return consumedCharacters;
}
Esempio n. 23
0
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{

	case WM_ACTIVATE:
		{
			KillTimer(hWnd, 0);
			if (!HIWORD(wParam))
				window.isActive = true;
			else
				window.isActive = false;
		}
		return 0;

	case WM_CREATE:
		{
			RAWINPUTDEVICE rid;

			rid.usUsagePage = 0x01;
			rid.usUsage     = 0x05;
			rid.dwFlags     = 0x00;
			rid.hwndTarget  = hWnd;

			if(!RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE)))
				return -1;
		}
		return 0;

	case WM_INPUT:
		{
			PRAWINPUT pRawInput;
			UINT      bufferSize;
			HANDLE    hHeap;

			GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &bufferSize, sizeof(RAWINPUTHEADER));

			hHeap     = GetProcessHeap();
			pRawInput = (PRAWINPUT)HeapAlloc(hHeap, 0, bufferSize);
			if(!pRawInput)
				return 0;

			GetRawInputData((HRAWINPUT)lParam, RID_INPUT, pRawInput, &bufferSize, sizeof(RAWINPUTHEADER));

			if(pRawInput->header.dwType == RIM_TYPEHID) 
			{
				ReadGamePadInput(pRawInput,input.gamepad);
			}

			HeapFree(hHeap, 0, pRawInput);
		}
		return 0;

	case WM_MOUSEWHEEL:
		{
			short zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
			if(zDelta > 0)
				selectedBrush++;
			else
				selectedBrush--;
			selectedBrush = CLAMP(selectedBrush,0,atlas_tile.totalFrames - 1);
			return 0;
		}

	case WM_MOUSEMOVE:
		POINTS point;
		point = MAKEPOINTS(lParam); 
		input.mouse.lX = point.x; 
		input.mouse.lY = point.y; 
		if(bdraggingworld)
		{
			float rx = camera.size.x / client_rect.w;
			float ry = camera.size.y / client_rect.h;
			camera.position += Vector2(-((float)input.mouse.lX - rclick.x) * rx , ((float)input.mouse.lY - rclick.y) * ry);
			rclick = Point(input.mouse.lX, input.mouse.lY);
		}
		else if(bdraggingrmenu)
		{
			float ry = rmenuRect.h / client_rect.h;
			rmenuyoffset += ((float)input.mouse.lY - rclick.y) * ry;
			int min = rmenuRect.h-(ceilf(((float)atlas_tile.totalFrames/tilesperrow))+4)*32.0f;
			rmenuyoffset = CLAMP(rmenuyoffset,min,0.0f);
			rclick = Point(input.mouse.lX, input.mouse.lY);
		}
		return 0;

	case WM_LBUTTONDOWN:
		input.mouse.bButtons[MLBUTTON] = true;
		return 0;
	case WM_LBUTTONUP:
		input.mouse.bButtons[MLBUTTON] = false;
		return 0;

	case WM_MBUTTONDOWN:
		input.mouse.bButtons[MMBUTTON] = true;
		return 0;
	case WM_MBUTTONUP:
		input.mouse.bButtons[MMBUTTON] = false;
		return 0;

	case WM_RBUTTONDOWN:
		SetCapture(hWnd);
		rclick = Point(input.mouse.lX,input.mouse.lY);
		if(PointinRect(rclick,s_dstRect))
			bdraggingworld = true;
		else if(PointinRect(rclick,rmenuRect))
			bdraggingrmenu = true;
		input.mouse.bButtons[MRBUTTON] = true;
		return 0;
	case WM_RBUTTONUP:
		ReleaseCapture(); 
		bdraggingworld = false;
		bdraggingrmenu = false;
		input.mouse.bButtons[MRBUTTON] = false;
		return 0;

	case WM_SIZE:
		R_resize( LOWORD(lParam), HIWORD(lParam));
		return 0;

	case WM_CLOSE:
		PostQuitMessage( 0 );
		return 0;

	case WM_DESTROY:
		return 0;

	case WM_KEYDOWN:
		input.keyboard.bKeys[(unsigned char)wParam] = true;
		return 0;

	case WM_KEYUP:
		input.keyboard.bKeys[(unsigned char)wParam] = false;
		return 0;

	case WM_NCLBUTTONDOWN:
		last_movesize_time = T_GetCurrentTime();
		movesize_time = last_movesize_time - last_game_time;
		SetTimer(hWnd,NULL,1,NULL);
		return DefWindowProc( hWnd, message, wParam, lParam );

	case WM_NCLBUTTONUP:
		KillTimer(hWnd, 0);
		return 0;

	case WM_TIMER:
		{
			double current_time = T_GetCurrentTime();
			movesize_time += current_time - last_movesize_time;
			last_movesize_time = current_time;
		}
		return 0;

	case WM_EXITSIZEMOVE:
		KillTimer(hWnd, 0);
		return 0;

	case WM_COMMAND:
		{
			switch(LOWORD(wParam))
			{
			case ID_EXIT:
				{
					PostQuitMessage( 0 );
				} 
				break;
			case ID_FILE_OPEN_T1:
				{
					D_OpenTileMapDialog(hWnd,1);
				} 
				break;
			case ID_FILE_SAVE_T1:
				{
					D_SaveTileMapDialog(hWnd,1);
				} 
				break;
			case ID_FILE_OPEN_T2:
				{
					D_OpenTileMapDialog(hWnd,2);
				} 
				break;
			case ID_FILE_SAVE_T2:
				{
					D_SaveTileMapDialog(hWnd,2);
				} 
				break;
			case ID_FILE_NEW:
				{
					DialogBox(window.hInstance, MAKEINTRESOURCE(IDD_DLGFIRST),
						hWnd, reinterpret_cast<DLGPROC>(P_DlgProc));
				} 
				break;				
			}
		} 
		return 0;

	default:
		return DefWindowProc( hWnd, message, wParam, lParam );

	}
}
Esempio n. 24
0
void ceil_l_s(float *source,long long *dest)
{
  *dest = ceilf(*source);
}
LayoutUnit LayoutTextControlMultiLine::preferredContentLogicalWidth(float charWidth) const
{
    int factor = toHTMLTextAreaElement(node())->cols();
    return static_cast<LayoutUnit>(ceilf(charWidth * factor)) + scrollbarThickness();
}
Esempio n. 26
0
void ceil_w_s(float *source,int *dest)
{
  *dest = ceilf(*source);
}
Esempio n. 27
0
bool Sample_SoloMesh::handleBuild()
{
	if (!m_geom || !m_geom->getMesh())
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Input mesh is not specified.");
		return false;
	}
	
	cleanup();
	
	const float* bmin = m_geom->getMeshBoundsMin();
	const float* bmax = m_geom->getMeshBoundsMax();
	const float* verts = m_geom->getMesh()->getVerts();
	const int nverts = m_geom->getMesh()->getVertCount();
	const int* tris = m_geom->getMesh()->getTris();
	const int ntris = m_geom->getMesh()->getTriCount();
	
	//
	// Step 1. Initialize build config.
	//
	
	// Init build configuration from GUI
	memset(&m_cfg, 0, sizeof(m_cfg));
	m_cfg.cs = m_cellSize;
	m_cfg.ch = m_cellHeight;
	m_cfg.walkableSlopeAngle = m_agentMaxSlope;
	m_cfg.walkableHeight = (int)ceilf(m_agentHeight / m_cfg.ch);
	m_cfg.walkableClimb = (int)floorf(m_agentMaxClimb / m_cfg.ch);
	m_cfg.walkableRadius = (int)ceilf(m_agentRadius / m_cfg.cs);
	m_cfg.maxEdgeLen = (int)(m_edgeMaxLen / m_cellSize);
	m_cfg.maxSimplificationError = m_edgeMaxError;
	m_cfg.minRegionArea = (int)rcSqr(m_regionMinSize);		// Note: area = size*size
	m_cfg.mergeRegionArea = (int)rcSqr(m_regionMergeSize);	// Note: area = size*size
	m_cfg.maxVertsPerPoly = (int)m_vertsPerPoly;
	m_cfg.detailSampleDist = m_detailSampleDist < 0.9f ? 0 : m_cellSize * m_detailSampleDist;
	m_cfg.detailSampleMaxError = m_cellHeight * m_detailSampleMaxError;
	
	// Set the area where the navigation will be build.
	// Here the bounds of the input mesh are used, but the
	// area could be specified by an user defined box, etc.
	rcVcopy(m_cfg.bmin, bmin);
	rcVcopy(m_cfg.bmax, bmax);
	rcCalcGridSize(m_cfg.bmin, m_cfg.bmax, m_cfg.cs, &m_cfg.width, &m_cfg.height);

	// Reset build times gathering.
	m_ctx->resetTimers();

	// Start the build process.	
	m_ctx->startTimer(RC_TIMER_TOTAL);
	
	m_ctx->log(RC_LOG_PROGRESS, "Building navigation:");
	m_ctx->log(RC_LOG_PROGRESS, " - %d x %d cells", m_cfg.width, m_cfg.height);
	m_ctx->log(RC_LOG_PROGRESS, " - %.1fK verts, %.1fK tris", nverts/1000.0f, ntris/1000.0f);
	
	//
	// Step 2. Rasterize input polygon soup.
	//
	
	// Allocate voxel heightfield where we rasterize our input data to.
	m_solid = rcAllocHeightfield();
	if (!m_solid)
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'solid'.");
		return false;
	}
	if (!rcCreateHeightfield(m_ctx, *m_solid, m_cfg.width, m_cfg.height, m_cfg.bmin, m_cfg.bmax, m_cfg.cs, m_cfg.ch))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not create solid heightfield.");
		return false;
	}
	
	// Allocate array that can hold triangle area types.
	// If you have multiple meshes you need to process, allocate
	// and array which can hold the max number of triangles you need to process.
	m_triareas = new unsigned char[ntris];
	if (!m_triareas)
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'm_triareas' (%d).", ntris);
		return false;
	}
	
	// Find triangles which are walkable based on their slope and rasterize them.
	// If your input data is multiple meshes, you can transform them here, calculate
	// the are type for each of the meshes and rasterize them.
	memset(m_triareas, 0, ntris*sizeof(unsigned char));
	rcMarkWalkableTriangles(m_ctx, m_cfg.walkableSlopeAngle, verts, nverts, tris, ntris, m_triareas);
	rcRasterizeTriangles(m_ctx, verts, nverts, tris, m_triareas, ntris, *m_solid, m_cfg.walkableClimb);

	if (!m_keepInterResults)
	{
		delete [] m_triareas;
		m_triareas = 0;
	}
	
	//
	// Step 3. Filter walkables surfaces.
	//
	
	// Once all geoemtry is rasterized, we do initial pass of filtering to
	// remove unwanted overhangs caused by the conservative rasterization
	// as well as filter spans where the character cannot possibly stand.
	rcFilterLowHangingWalkableObstacles(m_ctx, m_cfg.walkableClimb, *m_solid);
	rcFilterLedgeSpans(m_ctx, m_cfg.walkableHeight, m_cfg.walkableClimb, *m_solid);
	rcFilterWalkableLowHeightSpans(m_ctx, m_cfg.walkableHeight, *m_solid);


	//
	// Step 4. Partition walkable surface to simple regions.
	//

	// Compact the heightfield so that it is faster to handle from now on.
	// This will result more cache coherent data as well as the neighbours
	// between walkable cells will be calculated.
	m_chf = rcAllocCompactHeightfield();
	if (!m_chf)
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'chf'.");
		return false;
	}
	if (!rcBuildCompactHeightfield(m_ctx, m_cfg.walkableHeight, m_cfg.walkableClimb, *m_solid, *m_chf))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build compact data.");
		return false;
	}
	
	if (!m_keepInterResults)
	{
		rcFreeHeightField(m_solid);
		m_solid = 0;
	}
		
	// Erode the walkable area by agent radius.
	if (!rcErodeWalkableArea(m_ctx, m_cfg.walkableRadius, *m_chf))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not erode.");
		return false;
	}

	// (Optional) Mark areas.
	const ConvexVolume* vols = m_geom->getConvexVolumes();
	for (int i  = 0; i < m_geom->getConvexVolumeCount(); ++i)
		rcMarkConvexPolyArea(m_ctx, vols[i].verts, vols[i].nverts, vols[i].hmin, vols[i].hmax, (unsigned char)vols[i].area, *m_chf);
	
	if (m_monotonePartitioning)
	{
		// Partition the walkable surface into simple regions without holes.
		// Monotone partitioning does not need distancefield.
		if (!rcBuildRegionsMonotone(m_ctx, *m_chf, 0, m_cfg.minRegionArea, m_cfg.mergeRegionArea))
		{
			m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build regions.");
			return false;
		}
	}
	else
	{
		// Prepare for region partitioning, by calculating distance field along the walkable surface.
		if (!rcBuildDistanceField(m_ctx, *m_chf))
		{
			m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build distance field.");
			return false;
		}

		// Partition the walkable surface into simple regions without holes.
		if (!rcBuildRegions(m_ctx, *m_chf, 0, m_cfg.minRegionArea, m_cfg.mergeRegionArea))
		{
			m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build regions.");
			return false;
		}
	}

	//
	// Step 5. Trace and simplify region contours.
	//
	
	// Create contours.
	m_cset = rcAllocContourSet();
	if (!m_cset)
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'cset'.");
		return false;
	}
	if (!rcBuildContours(m_ctx, *m_chf, m_cfg.maxSimplificationError, m_cfg.maxEdgeLen, *m_cset))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not create contours.");
		return false;
	}
	
	//
	// Step 6. Build polygons mesh from contours.
	//
	
	// Build polygon navmesh from the contours.
	m_pmesh = rcAllocPolyMesh();
	if (!m_pmesh)
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'pmesh'.");
		return false;
	}
	if (!rcBuildPolyMesh(m_ctx, *m_cset, m_cfg.maxVertsPerPoly, *m_pmesh))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not triangulate contours.");
		return false;
	}
	
	//
	// Step 7. Create detail mesh which allows to access approximate height on each polygon.
	//
	
	m_dmesh = rcAllocPolyMeshDetail();
	if (!m_dmesh)
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Out of memory 'pmdtl'.");
		return false;
	}

	if (!rcBuildPolyMeshDetail(m_ctx, *m_pmesh, *m_chf, m_cfg.detailSampleDist, m_cfg.detailSampleMaxError, *m_dmesh))
	{
		m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build detail mesh.");
		return false;
	}

	if (!m_keepInterResults)
	{
		rcFreeCompactHeightfield(m_chf);
		m_chf = 0;
		rcFreeContourSet(m_cset);
		m_cset = 0;
	}

	// At this point the navigation mesh data is ready, you can access it from m_pmesh.
	// See duDebugDrawPolyMesh or dtCreateNavMeshData as examples how to access the data.
	
	//
	// (Optional) Step 8. Create Detour data from Recast poly mesh.
	//
	
	// The GUI may allow more max points per polygon than Detour can handle.
	// Only build the detour navmesh if we do not exceed the limit.
	if (m_cfg.maxVertsPerPoly <= DT_VERTS_PER_POLYGON)
	{
		unsigned char* navData = 0;
		int navDataSize = 0;

		// Update poly flags from areas.
		for (int i = 0; i < m_pmesh->npolys; ++i)
		{
			if (m_pmesh->areas[i] == RC_WALKABLE_AREA)
				m_pmesh->areas[i] = SAMPLE_POLYAREA_GROUND;
				
			if (m_pmesh->areas[i] == SAMPLE_POLYAREA_GROUND ||
				m_pmesh->areas[i] == SAMPLE_POLYAREA_GRASS ||
				m_pmesh->areas[i] == SAMPLE_POLYAREA_ROAD)
			{
				m_pmesh->flags[i] = SAMPLE_POLYFLAGS_WALK;
			}
			else if (m_pmesh->areas[i] == SAMPLE_POLYAREA_WATER)
			{
				m_pmesh->flags[i] = SAMPLE_POLYFLAGS_SWIM;
			}
			else if (m_pmesh->areas[i] == SAMPLE_POLYAREA_DOOR)
			{
				m_pmesh->flags[i] = SAMPLE_POLYFLAGS_WALK | SAMPLE_POLYFLAGS_DOOR;
			}
		}


		dtNavMeshCreateParams params;
		memset(&params, 0, sizeof(params));
		params.verts = m_pmesh->verts;
		params.vertCount = m_pmesh->nverts;
		params.polys = m_pmesh->polys;
		params.polyAreas = m_pmesh->areas;
		params.polyFlags = m_pmesh->flags;
		params.polyCount = m_pmesh->npolys;
		params.nvp = m_pmesh->nvp;
		params.detailMeshes = m_dmesh->meshes;
		params.detailVerts = m_dmesh->verts;
		params.detailVertsCount = m_dmesh->nverts;
		params.detailTris = m_dmesh->tris;
		params.detailTriCount = m_dmesh->ntris;
		params.offMeshConVerts = m_geom->getOffMeshConnectionVerts();
		params.offMeshConRad = m_geom->getOffMeshConnectionRads();
		params.offMeshConDir = m_geom->getOffMeshConnectionDirs();
		params.offMeshConAreas = m_geom->getOffMeshConnectionAreas();
		params.offMeshConFlags = m_geom->getOffMeshConnectionFlags();
		params.offMeshConUserID = m_geom->getOffMeshConnectionId();
		params.offMeshConCount = m_geom->getOffMeshConnectionCount();
		params.walkableHeight = m_agentHeight;
		params.walkableRadius = m_agentRadius;
		params.walkableClimb = m_agentMaxClimb;
		rcVcopy(params.bmin, m_pmesh->bmin);
		rcVcopy(params.bmax, m_pmesh->bmax);
		params.cs = m_cfg.cs;
		params.ch = m_cfg.ch;
		params.buildBvTree = true;
		
		if (!dtCreateNavMeshData(&params, &navData, &navDataSize))
		{
			m_ctx->log(RC_LOG_ERROR, "Could not build Detour navmesh.");
			return false;
		}
		
		m_navMesh = dtAllocNavMesh();
		if (!m_navMesh)
		{
			dtFree(navData);
			m_ctx->log(RC_LOG_ERROR, "Could not create Detour navmesh");
			return false;
		}
		
		dtStatus status;
		
		status = m_navMesh->init(navData, navDataSize, DT_TILE_FREE_DATA);
		if (dtStatusFailed(status))
		{
			dtFree(navData);
			m_ctx->log(RC_LOG_ERROR, "Could not init Detour navmesh");
			return false;
		}
		
		status = m_navQuery->init(m_navMesh, 2048);
		if (dtStatusFailed(status))
		{
			m_ctx->log(RC_LOG_ERROR, "Could not init Detour navmesh query");
			return false;
		}
	}
	
	m_ctx->stopTimer(RC_TIMER_TOTAL);

	// Show performance stats.
	duLogBuildTimes(*m_ctx, m_ctx->getAccumulatedTime(RC_TIMER_TOTAL));
	m_ctx->log(RC_LOG_PROGRESS, ">> Polymesh: %d vertices  %d polygons", m_pmesh->nverts, m_pmesh->npolys);
	
	m_totalBuildTimeMs = m_ctx->getAccumulatedTime(RC_TIMER_TOTAL)/1000.0f;
	
	if (m_tool)
		m_tool->init(this);

	return true;
}
Esempio n. 28
0
void
xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area,
	char *base_uri, xps_resource *dict, xml_element *root,
	void (*func)(xps_context*, fz_matrix, fz_rect, char*, xps_resource*, xml_element*, void*), void *user)
{
	xml_element *node;
	struct closure c;

	char *opacity_att;
	char *transform_att;
	char *viewbox_att;
	char *viewport_att;
	char *tile_mode_att;
	char *viewbox_units_att;
	char *viewport_units_att;

	xml_element *transform_tag = NULL;

	fz_matrix transform;
	fz_rect viewbox;
	fz_rect viewport;
	float xstep, ystep;
	float xscale, yscale;
	int tile_mode;

	opacity_att = xml_att(root, "Opacity");
	transform_att = xml_att(root, "Transform");
	viewbox_att = xml_att(root, "Viewbox");
	viewport_att = xml_att(root, "Viewport");
	tile_mode_att = xml_att(root, "TileMode");
	viewbox_units_att = xml_att(root, "ViewboxUnits");
	viewport_units_att = xml_att(root, "ViewportUnits");

	c.base_uri = base_uri;
	c.dict = dict;
	c.root = root;
	c.user = user;
	c.func = func;

	for (node = xml_down(root); node; node = xml_next(node))
	{
		if (!strcmp(xml_tag(node), "ImageBrush.Transform"))
			transform_tag = xml_down(node);
		if (!strcmp(xml_tag(node), "VisualBrush.Transform"))
			transform_tag = xml_down(node);
	}

	xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL);

	transform = fz_identity;
	if (transform_att)
		xps_parse_render_transform(ctx, transform_att, &transform);
	if (transform_tag)
		xps_parse_matrix_transform(ctx, transform_tag, &transform);
	ctm = fz_concat(transform, ctm);

	viewbox = fz_unit_rect;
	if (viewbox_att)
		xps_parse_rectangle(ctx, viewbox_att, &viewbox);

	viewport = fz_unit_rect;
	if (viewport_att)
		xps_parse_rectangle(ctx, viewport_att, &viewport);

	/* some sanity checks on the viewport/viewbox size */
	if (fabsf(viewport.x1 - viewport.x0) < 0.01f) return;
	if (fabsf(viewport.y1 - viewport.y0) < 0.01f) return;
	if (fabsf(viewbox.x1 - viewbox.x0) < 0.01f) return;
	if (fabsf(viewbox.y1 - viewbox.y0) < 0.01f) return;

	xstep = viewbox.x1 - viewbox.x0;
	ystep = viewbox.y1 - viewbox.y0;

	xscale = (viewport.x1 - viewport.x0) / xstep;
	yscale = (viewport.y1 - viewport.y0) / ystep;

	tile_mode = TILE_NONE;
	if (tile_mode_att)
	{
		if (!strcmp(tile_mode_att, "None"))
			tile_mode = TILE_NONE;
		if (!strcmp(tile_mode_att, "Tile"))
			tile_mode = TILE_TILE;
		if (!strcmp(tile_mode_att, "FlipX"))
			tile_mode = TILE_FLIP_X;
		if (!strcmp(tile_mode_att, "FlipY"))
			tile_mode = TILE_FLIP_Y;
		if (!strcmp(tile_mode_att, "FlipXY"))
			tile_mode = TILE_FLIP_X_Y;
	}

	if (tile_mode == TILE_FLIP_X || tile_mode == TILE_FLIP_X_Y)
		xstep *= 2;
	if (tile_mode == TILE_FLIP_Y || tile_mode == TILE_FLIP_X_Y)
		ystep *= 2;

	xps_begin_opacity(ctx, ctm, area, base_uri, dict, opacity_att, NULL);

	ctm = fz_concat(fz_translate(viewport.x0, viewport.y0), ctm);
	ctm = fz_concat(fz_scale(xscale, yscale), ctm);
	ctm = fz_concat(fz_translate(-viewbox.x0, -viewbox.y0), ctm);

	if (tile_mode != TILE_NONE)
	{
		int x0, y0, x1, y1;
		fz_matrix invctm = fz_invert_matrix(ctm);
		area = fz_transform_rect(invctm, area);
		x0 = floorf(area.x0 / xstep);
		y0 = floorf(area.y0 / ystep);
		x1 = ceilf(area.x1 / xstep);
		y1 = ceilf(area.y1 / ystep);

#ifdef TILE
		if ((x1 - x0) * (y1 - y0) > 1)
#else
		if (0)
#endif
		{
			fz_rect bigview = viewbox;
			bigview.x1 = bigview.x0 + xstep;
			bigview.y1 = bigview.y0 + ystep;
			fz_begin_tile(ctx->dev, area, bigview, xstep, ystep, ctm);
			xps_paint_tiling_brush(ctx, ctm, viewbox, tile_mode, &c);
			fz_end_tile(ctx->dev);
		}
		else
		{
			int x, y;
			for (y = y0; y < y1; y++)
			{
				for (x = x0; x < x1; x++)
				{
					fz_matrix ttm = fz_concat(fz_translate(xstep * x, ystep * y), ctm);
					xps_paint_tiling_brush(ctx, ttm, viewbox, tile_mode, &c);
				}
			}
		}
	}
	else
	{
		xps_paint_tiling_brush(ctx, ctm, viewbox, tile_mode, &c);
	}

	xps_end_opacity(ctx, base_uri, dict, opacity_att, NULL);
}
Esempio n. 29
0
void TextBlock::CalculateCacheParams()
{
    if (text.empty())
    {
        cacheFinalSize = Vector2(0.f, 0.f);
        cacheW = 0;
        cacheDx = 0;
        cacheDy = 0;

        return;
    }

    bool useJustify = ((align & ALIGN_HJUSTIFY) != 0);
    font->SetSize(originalFontSize);
    Vector2 drawSize = rectSize;
    
    if(requestedSize.dx > 0)
    {
        drawSize.x = requestedSize.dx;
    }
    if(requestedSize.dy > 0)
    {
        drawSize.y = requestedSize.dy;
    }
    
    int32 w = (int32)drawSize.x;
    int32 h = (int32)drawSize.y;
    
    Size2i textSize;
    stringSizes.clear();
    
    // This is a temporary fix to correctly handle long multiline texts
    // which can't be broken to the separate lines.
    if (isMultilineEnabled)
    {
        if(isMultilineBySymbolEnabled)
        {
            font->SplitTextBySymbolsToStrings(text, drawSize, multilineStrings);
        }
        else
        {
            font->SplitTextToStrings(text, drawSize, multilineStrings);
        }
        
        treatMultilineAsSingleLine = multilineStrings.size() == 1;
    }
    
    if(!isMultilineEnabled || treatMultilineAsSingleLine)
    {
        textSize = font->GetStringSize(text);
        pointsStr.clear();
        if(fittingType & FITTING_POINTS)
        {
            if(drawSize.x < textSize.dx)
            {
                Size2i textSizePoints;
                
                int32 length = (int32)text.length();
                for(int32 i = length - 1; i > 0; --i)
                {
                    pointsStr.clear();
                    pointsStr.append(text, 0, i);
                    pointsStr += L"...";
                    
                    textSize = font->GetStringSize(pointsStr);
                    if(textSize.dx <= drawSize.x)
                    {
                        break;
                    }
                }
            }
        }
        else if(!((fittingType & FITTING_REDUCE) || (fittingType & FITTING_ENLARGE)) && (drawSize.x < textSize.dx) && (requestedSize.x >= 0))
        {
            Size2i textSizePoints;
            int32 length = (int32)text.length();
            if(ALIGN_RIGHT & align)
            {
                for(int32 i = 1; i < length - 1; ++i)
                {
                    pointsStr.clear();
                    pointsStr.append(text, i, length - i);
                    
                    textSize = font->GetStringSize(pointsStr);
                    if(textSize.dx <= drawSize.x)
                    {
                        break;
                    }
                }
            }
            else if(ALIGN_HCENTER & align)
            {
                int32 endPos = length / 2;
                int32 startPos = endPos - 1;
                
                int32 count = endPos;
                WideString savedStr = L"";
                
                for(int32 i = 1; i < count; ++i)
                {
                    pointsStr.clear();
                    pointsStr.append(text, startPos, endPos - startPos);
                    
                    textSize = font->GetStringSize(pointsStr);
                    if(drawSize.x <= textSize.dx)
                    {
                        break;
                    }
                    
                    --startPos;
                    ++endPos;
                }
            }
        }
        else if(((fittingType & FITTING_REDUCE) || (fittingType & FITTING_ENLARGE)) && (requestedSize.dy >= 0 || requestedSize.dx >= 0))
        {
            bool isChanged = false;
            float prevFontSize = font->GetRenderSize();
            while (true)
            {
                float yMul = 1.0f;
                float xMul = 1.0f;
                
                bool xBigger = false;
                bool xLower = false;
                bool yBigger = false;
                bool yLower = false;
                if(requestedSize.dy >= 0)
                {
                    h = textSize.dy;
                    if((isChanged || fittingType & FITTING_REDUCE) && textSize.dy > drawSize.y)
                    {
                        if (prevFontSize < font->GetRenderSize())
                        {
                            font->SetRenderSize(prevFontSize);
                            textSize = font->GetStringSize(text);
                            h = textSize.dy;
                            if (requestedSize.dx >= 0)
                            {
                                w = textSize.dx;
                            }
                            break;
                        }
                        yBigger = true;
                        yMul = drawSize.y / textSize.dy;
                    }
                    else if((isChanged || fittingType & FITTING_ENLARGE) && textSize.dy < drawSize.y * 0.9)
                    {
                        yLower = true;
                        yMul = (drawSize.y * 0.9f) / textSize.dy;
                        if(yMul < 1.01f)
                        {
                            yLower = false;
                        }
                    }
                }
                
                if(requestedSize.dx >= 0)
                {
                    w = textSize.dx;
                    if((isChanged || fittingType & FITTING_REDUCE) && textSize.dx > drawSize.x)
                    {
                        if (prevFontSize < font->GetRenderSize())
                        {
                            font->SetRenderSize(prevFontSize);
                            textSize = font->GetStringSize(text);
                            w = textSize.dx;
                            if (requestedSize.dy >= 0)
                            {
                                h = textSize.dy;
                            }
                            break;
                        }
                        xBigger = true;
                        xMul = drawSize.x / textSize.dx;
                    }
                    else if((isChanged || fittingType & FITTING_ENLARGE) && textSize.dx < drawSize.x * 0.95)
                    {
                        xLower = true;
                        xMul = (drawSize.x * 0.95f) / textSize.dx;
                        if(xMul < 1.01f)
                        {
                            xLower = false;
                        }
                    }
                }
                
                
                if((!xBigger && !yBigger) && (!xLower || !yLower))
                {
                    break;
                }
                
                float finalSize = font->GetRenderSize();
                prevFontSize = finalSize;
                isChanged = true;
                if(xMul < yMul)
                {
                    finalSize *= xMul;
                }
                else
                {
                    finalSize *= yMul;
                }
                font->SetRenderSize(finalSize);
                textSize = font->GetStringSize(text);
            };
        }
        
        if (treatMultilineAsSingleLine)
        {
            // Another temporary solution to return correct multiline strings/
            // string sizes.
            multilineStrings.clear();
            stringSizes.clear();
            multilineStrings.push_back(text);
            stringSizes.push_back(font->GetStringSize(text).dx);
        }
    }
    else //if(!isMultilineEnabled)
    {
        if(fittingType && (requestedSize.dy >= 0/* || requestedSize.dx >= 0*/) && text.size() > 3)
        {
            //				Logger::FrameworkDebug("Fitting enabled");
            Vector2 rectSz = rectSize;
            if(requestedSize.dx > 0)
            {
                rectSz.dx = requestedSize.dx;
            }
            if(isMultilineBySymbolEnabled)
                font->SplitTextBySymbolsToStrings(text, rectSz, multilineStrings);
            else
                font->SplitTextToStrings(text, rectSz, multilineStrings);
            
            textSize.dx = 0;
            textSize.dy = 0;
            
            int32 yOffset = font->GetVerticalSpacing();
            //				int32 fontHeight = font->GetFontHeight() + 1 + yOffset;
            //				textSize.dy = yOffset*2 + fontHeight * (int32)multilineStrings.size();
            int32 fontHeight = font->GetFontHeight() + yOffset;
            textSize.dy = fontHeight * (int32)multilineStrings.size() - yOffset;
            float lastSize = font->GetRenderSize();
            float lastHeight = (float32)textSize.dy;
            
            bool isChanged = false;
            while (true)
            {
                float yMul = 1.0f;
                
                bool yBigger = false;
                bool yLower = false;
                if(requestedSize.dy >= 0)
                {
                    h = textSize.dy;
                    if((isChanged || fittingType & FITTING_REDUCE) && textSize.dy > drawSize.y)
                    {
                        yBigger = true;
                        yMul = drawSize.y / textSize.dy;
                        if(lastSize < font->GetRenderSize())
                        {
                            font->SetRenderSize(lastSize);
                            h = (int32)lastHeight;
                            break;
                        }
                    }
                    else if((isChanged || fittingType & FITTING_ENLARGE) && textSize.dy < drawSize.y * 0.95)
                    {
                        yLower = true;
                        if(textSize.dy < drawSize.y * 0.75f)
                        {
                            yMul = (drawSize.y * 0.75f) / textSize.dy;
                        }
                        else if(textSize.dy < drawSize.y * 0.8f)
                        {
                            yMul = (drawSize.y * 0.8f) / textSize.dy;
                        }
                        else if(textSize.dy < drawSize.y * 0.85f)
                        {
                            yMul = (drawSize.y * 0.85f) / textSize.dy;
                        }
                        else if(textSize.dy < drawSize.y * 0.9f)
                        {
                            yMul = (drawSize.y * 0.9f) / textSize.dy;
                        }
                        else
                        {
                            yMul = (drawSize.y * 0.95f) / textSize.dy;
                        }
                        if (yMul == 1.0f)
                        {
                            yMul = 1.05f;
                        }
                    }
                }
                
                if(!yBigger && !yLower)
                {
                    break;
                }
                
                lastHeight = (float32)textSize.dy;
                
                float finalSize = lastSize = font->GetRenderSize();
                isChanged = true;
                finalSize *= yMul;
                
                font->SetRenderSize(finalSize);
                //					textSize = font->GetStringSize(text);
                
                if(isMultilineBySymbolEnabled)
                    font->SplitTextBySymbolsToStrings(text, rectSz, multilineStrings);
                else
                    font->SplitTextToStrings(text, rectSz, multilineStrings);
                
                textSize.dy = 0;
                
                int32 yOffset = font->GetVerticalSpacing();
                //					int32 fontHeight = font->GetFontHeight() + 1 + yOffset;
                //					textSize.dy = yOffset*2 + fontHeight * (int32)multilineStrings.size();
                int32 fontHeight = font->GetFontHeight() + yOffset;
                textSize.dy = fontHeight * (int32)multilineStrings.size() - yOffset;
                
            };
            
        }
        //			Logger::FrameworkDebug("Font size: %.4f", font->GetSize());
        
        
        Vector2 rectSz = rectSize;
        if(requestedSize.dx > 0)
        {
            rectSz.dx = requestedSize.dx;
        }
        if(isMultilineBySymbolEnabled)
            font->SplitTextBySymbolsToStrings(text, rectSz, multilineStrings);
        else
            font->SplitTextToStrings(text, rectSz, multilineStrings);
        
        textSize.dx = 0;
        textSize.dy = 0;
        
        int32 yOffset = font->GetVerticalSpacing();
        //			Logger::FrameworkDebug("yOffset = %.4d", yOffset);
        //			int32 fontHeight = font->GetFontHeight() + 1 + yOffset;
        //			textSize.dy = yOffset*2 + fontHeight * (int32)multilineStrings.size();
        int32 fontHeight = font->GetFontHeight() + yOffset;
        //			Logger::FrameworkDebug("fontHeight = %.4d", fontHeight);
        textSize.dy = fontHeight * (int32)multilineStrings.size() - yOffset;
        
        stringSizes.reserve(multilineStrings.size());
        for (int32 line = 0; line < (int32)multilineStrings.size(); ++line)
        {
            Size2i stringSize = font->GetStringSize(multilineStrings[line]);
            stringSizes.push_back(stringSize.dx);
            if(requestedSize.dx >= 0)
            {
                textSize.dx = Max(textSize.dx, Min(stringSize.dx, (int)drawSize.x));
            }
            else
            {
                textSize.dx = Max(textSize.dx, stringSize.dx);
            }
        }
    }
    
    if(requestedSize.dx == 0)
    {
        w = Min(w, textSize.dx);
        //			Logger::FrameworkDebug("On size not requested: w = %d", w);
    }
    else if(requestedSize.dx < 0)
    {
        w = textSize.dx;
        //			Logger::FrameworkDebug("On size automated: w = %d", w);
    }
    if(requestedSize.dy == 0)
    {
        h = Min(h, textSize.dy);
        //			Logger::FrameworkDebug("On size not requested: h = %d", h);
    }
    else if(requestedSize.dy < 0)
    {
        h = textSize.dy;
        //			Logger::FrameworkDebug("On size automated: h = %d", w);
    }
    
    if (requestedSize.dx >= 0 && useJustify)
    {
        w = (int32)drawSize.dx;
    }
    
    
    
    //calc texture size
    int32 dx = (int32)ceilf(Core::GetVirtualToPhysicalFactor() * w);
    int32 dy = (int32)ceilf(Core::GetVirtualToPhysicalFactor() * h);
    
    cacheUseJustify = useJustify;
    cacheDx = dx;
    EnsurePowerOf2(cacheDx);
    
    cacheDy = dy;
    EnsurePowerOf2(cacheDy);
    
    cacheW = w;
    cacheFinalSize.x = (float32)dx / Core::GetVirtualToPhysicalFactor();
    cacheFinalSize.y = (float32)dy / Core::GetVirtualToPhysicalFactor();
}
Esempio n. 30
0
void process (struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, void *ivoid, void *ovoid, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out)
{
  float *in;
  float *out;
  dt_iop_zonesystem_gui_data_t *g = NULL;
  dt_iop_zonesystem_data_t *data = (dt_iop_zonesystem_data_t*)piece->data;

  guchar *buffer = NULL;
  if( self->dev->gui_attached && piece->pipe->type == DT_DEV_PIXELPIPE_PREVIEW )
  {
    g = (dt_iop_zonesystem_gui_data_t *)self->gui_data;
    dt_pthread_mutex_lock(&g->lock);
    if(g->preview_buffer)
      g_free (g->preview_buffer);

    buffer = g->preview_buffer = g_malloc (roi_in->width*roi_in->height);
    g->preview_width=roi_out->width;
    g->preview_height=roi_out->height;
  }

  /* calculate zonemap */
  const int size = data->size;
  float zonemap[MAX_ZONE_SYSTEM_SIZE]= {-1};
  _iop_zonesystem_calculate_zonemap (data, zonemap);
  const int ch = piece->colors;

  /* if gui and have buffer lets gaussblur and fill buffer with zone indexes */
  if( self->dev->gui_attached && g && buffer)
  {
    /* setup gaussian kernel */
    const int radius = 8;
    const int rad = MIN(radius, ceilf(radius * roi_in->scale / piece->iscale));
    const int wd = 2*rad+1;
    float mat[wd*wd];
    float *m;
    const float sigma2 = (2.5*2.5)*(radius*roi_in->scale/piece->iscale)*(radius*roi_in->scale/piece->iscale);
    float weight = 0.0f;

    memset(mat, 0, wd*wd*sizeof(float));

    m = mat;
    for(int l=-rad; l<=rad; l++) for(int k=-rad; k<=rad; k++,m++)
        weight += *m = expf(- (l*l + k*k)/(2.f*sigma2));
    m = mat;
    for(int l=-rad; l<=rad; l++) for(int k=-rad; k<=rad; k++,m++)
        *m /= weight;

    /* gauss blur the L channel */
#ifdef _OPENMP
    #pragma omp parallel for default(none) private(in, out, m) shared(mat, ivoid, ovoid, roi_out, roi_in) schedule(static)
#endif
    for(int j=rad; j<roi_out->height-rad; j++)
    {
      in  = ((float *)ivoid) + ch*(j*roi_in->width  + rad);
      out = ((float *)ovoid) + ch*(j*roi_out->width + rad);
      for(int i=rad; i<roi_out->width-rad; i++)
      {
        for(int c=0; c<3; c++) out[c] = 0.0f;
        float sum = 0.0;
        m = mat;
        for(int l=-rad; l<=rad; l++)
        {
          float *inrow = in + ch*(l*roi_in->width-rad);
          for(int k=-rad; k<=rad; k++,inrow+=ch,m++)
            sum += *m * inrow[0];
        }
        out[0] = sum;
        out += ch;
        in += ch;
      }
    }

    /* create zonemap preview */
//     in  = (float *)ivoid;
    out = (float *)ovoid;
#ifdef _OPENMP
    #pragma omp parallel for default(none) shared(roi_out,out,buffer,g,zonemap) schedule(static)
#endif
    for (int k=0; k<roi_out->width*roi_out->height; k++)
    {
      buffer[k] = _iop_zonesystem_zone_index_from_lightness (out[ch*k]/100.0f, zonemap, size);
    }

    dt_pthread_mutex_unlock(&g->lock);
  }

  /* process the image */
  in  = (float *)ivoid;
  out = (float *)ovoid;

  const float rzscale = (size-1)/100.0f;

  float zonemap_offset[MAX_ZONE_SYSTEM_SIZE]= {-1};
  float zonemap_scale[MAX_ZONE_SYSTEM_SIZE]= {-1};

  // precompute scale and offset
  for (int k=0; k < size-1; k++) zonemap_scale[k]  = (zonemap[k+1]-zonemap[k])*(size-1);
  for (int k=0; k < size-1; k++) zonemap_offset[k] = 100.0f * ((k+1)*zonemap[k] - k*zonemap[k+1]) ;

#ifdef _OPENMP
  #pragma omp parallel for default(none) shared(roi_out, in, out, zonemap_scale,zonemap_offset) schedule(static)
#endif
  for (int j=0; j<roi_out->height; j++)
    for (int i=0; i<roi_out->width; i++)
    {
      /* remap lightness into zonemap and apply lightness */
      const float *inp = in + ch*(j*roi_out->width+i);
      float *outp = out + ch*(j*roi_out->width+i);

      const int rz = CLAMPS(inp[0]*rzscale, 0, size-2);  // zone index

      const float zs = ((rz > 0) ? (zonemap_offset[rz]/inp[0]) : 0) + zonemap_scale[rz];

      _mm_stream_ps(outp,_mm_mul_ps(_mm_load_ps(inp),_mm_set1_ps(zs)));
    }

  _mm_sfence();

  if(piece->pipe->mask_display)
    dt_iop_alpha_copy(ivoid, ovoid, roi_out->width, roi_out->height);
}