Beispiel #1
0
/**
 * \brief Sets the vertex offsets of the stick.
 *
 * The values chosen are the minimum of the current ones and those given in
 * the slope argument.
 *
 * \param self Stick.
 * \param slope List of four floats.
 * \param offset Extra offset to add to the slope values.
 */
void liext_terrain_stick_set_vertices_min (
	LIExtTerrainStick* self,
	const float*       slope,
	float              offset)
{
	if (self == NULL)
		return;
	self->vertices[0][0].offset = LIMAT_MIN (self->vertices[0][0].offset, slope[0] + offset);
	self->vertices[1][0].offset = LIMAT_MIN (self->vertices[1][0].offset, slope[1] + offset);
	self->vertices[0][1].offset = LIMAT_MIN (self->vertices[0][1].offset, slope[2] + offset);
	self->vertices[1][1].offset = LIMAT_MIN (self->vertices[1][1].offset, slope[3] + offset);
}
/**
 * \brief Resizes the framebuffer.
 * \param self Framebuffer.
 * \param width New width.
 * \param height New height.
 * \param samples Number of multisamples.
 * \param hdr Nonzero to use floating point framebuffer to enable HDR.
 * \return Nonzero on success.
 */
int liren_framebuffer32_resize (
    LIRenFramebuffer32* self,
    int                 width,
    int                 height,
    int                 samples,
    int                 hdr)
{
    int max;
    int request;
    GLint max_color;
    GLint max_depth;

    /* Make sure that the sample count is valid. */
    /* The sample count must not be greater than the maximum sample count.
       It must also be a power of two and greater than zero. */
    glGetIntegerv (GL_MAX_COLOR_TEXTURE_SAMPLES, &max_color);
    glGetIntegerv (GL_MAX_DEPTH_TEXTURE_SAMPLES, &max_depth);
    request = samples;
    max = LIMAT_MIN (max_color, max_depth);
    for (samples = 1 ; samples < max && samples < request ; samples <<= 1) {}
    samples = LIMAT_MIN (samples, max);

    /* Check if a resize is actually needed. */
    if (self->hdr == hdr && self->width == width && self->height == height && self->samples == samples)
        return 1;

    /* Recreate the framebuffer objects. */
    /* If the driver fails to create an HDR framebuffer, we fall back to a non-HDR
       one. To avoid retrying in the next frame, the HDR flag is set regardless. */
    if (private_rebuild (self, width, height, samples, hdr) ||
            private_rebuild (self, width, height, samples, 0))
    {
        self->width = width;
        self->height = height;
        self->samples = samples;
        self->hdr = hdr;
        return 1;
    }

    return 0;
}
Beispiel #3
0
static void private_clamp_vertices (
	LIExtTerrainStick* self,
	LIExtTerrainStick* next)
{
	int x;
	int z;

	if (next != NULL)
	{
		for (z = 0 ; z < 2 ; z++)
		{
			for (x = 0 ; x < 2 ; x++)
			{
				self->vertices[x][z].offset = LIMAT_MIN (
					self->vertices[x][z].offset,
					next->vertices[x][z].offset + next->height);
			}
		}
	}
}
void LIRenImageOverlay::updatePositionGeometry ()
{
	// Prevent divide by zero.
	if (!mPixelWidth || !mPixelHeight)
	{
		render_op.vertexData->vertexCount = 0;
		return;
	}

	// Calculate offset and dimensions.
	float left = _getDerivedLeft() * 2.0f - 1.0f;
	float top = 1.0f - _getDerivedTop() * 2.0f;
	float xscale = 2.0f * mWidth / mPixelWidth;
	float yscale = 2.0f * mHeight / mPixelHeight;
	float xtile = xscale * src_tiling[1];
	float ytile = yscale * src_tiling[4];

	// Ogre seems to divide by zero during startup when the viewport
	// hasn't been initialized. Refuse to do anything if that happened.
	if (!limat_number_is_finite (left) || !limat_number_is_finite (top))
	{
		render_op.vertexData->vertexCount = 0;
		return;
	}

	// Calculate vertex coordinates.
	float x[4] =
	{
		left,
		left + xscale * src_tiling[0],
		left + xscale * (mPixelWidth - src_tiling[2]),
		left + xscale * mPixelWidth
	};
	float y[4] =
	{
		top,
		top - yscale * src_tiling[3],
		top - yscale * (mPixelHeight - src_tiling[5]),
		top - yscale * mPixelHeight
	};

	/* Calculate texture coordinates. */
	float uscale = 1.0f / src_size[0];
	float vscale = 1.0f / src_size[1];
	float u[4] =
	{
		uscale * (src_pos[0]),
		uscale * (src_pos[0] + src_tiling[0]),
		uscale * (src_pos[0] + src_tiling[0] + src_tiling[1]),
		uscale * (src_pos[0] + src_tiling[0] + src_tiling[1] + src_tiling[2])
	};
	float v[4] =
	{
		vscale * (src_pos[1]),
		vscale * (src_pos[1] + src_tiling[3]),
		vscale * (src_pos[1] + src_tiling[3] + src_tiling[4]),
		vscale * (src_pos[1] + src_tiling[3] + src_tiling[4] + src_tiling[5])
	};

	/* Setup vertex packing. */
	float z = Ogre::Root::getSingleton().getRenderSystem()->getMaximumDepthInputValue ();
	LIRenTilePacker packer (z);
	float color_[4] = { color[0], color[1], color[2], color[3] * alpha };
	packer.set_color (color_);
	if (rotation_angle != 0.0f)
	{
		float cx = left + xscale * rotation_center[0];
		float cy = top - yscale * rotation_center[1];
		packer.set_rotation (rotation_angle, cx, cy, xscale / yscale);
	}
	float clip[4];
	if (clipping)
	{
		clip[0] = left + xscale * dst_clip[0];
		clip[1] = top - yscale * (dst_clip[1] + dst_clip[3]);
		clip[2] = xscale * dst_clip[2];
		clip[3] = yscale * dst_clip[3];
		packer.set_clipping (clip);
	}

	/* Add corners. */
	packer.add_quad (x[0], y[0], u[0], v[0], x[1], y[1], u[1], v[1]);
	packer.add_quad (x[2], y[0], u[2], v[0], x[3], y[1], u[3], v[1]);
	packer.add_quad (x[2], y[2], u[2], v[2], x[3], y[3], u[3], v[3]);
	packer.add_quad (x[0], y[2], u[0], v[2], x[1], y[3], u[1], v[3]);

	/* Add top and bottom borders. */
	for (float i = x[1] ; i < x[2] ; i += xtile)
	{
		float wtile = LIMAT_MIN (x[2] - i, xtile);
		float xe = i + wtile;
		float ue = u[1] + (u[2] - u[1]) * (wtile / xtile);
		packer.add_quad (i, y[0], u[1], v[0], xe, y[1], ue, v[1]);
		packer.add_quad (i, y[2], u[1], v[2], xe, y[3], ue, v[3]);
	}

	/* Add left and right borders. */
	for (float j = y[1] ; j > y[2] ; j -= ytile)
	{
		float htile = LIMAT_MIN (j - y[2], ytile);
		float ye = j - htile;
		float ve = v[1] + (v[2] - v[1]) * (htile / ytile);
		packer.add_quad (x[0], j, u[0], v[1], x[1], ye, u[1], ve);
		packer.add_quad (x[2], j, u[2], v[1], x[3], ye, u[3], ve);
	}

	/* Add the filling. */
	for (float i = x[1] ; i < x[2] ; i += xtile)
	{
		float wtile = LIMAT_MIN (x[2] - i, xtile);
		float xe = i + wtile;
		float ue = u[1] + (u[2] - u[1]) * (wtile / xtile);
		for (float j = y[1] ; j > y[2] ; j -= ytile)
		{
			float htile = LIMAT_MIN (j - y[2], ytile);
			float ye = j - htile;
			float ve = v[1] + (v[2] - v[1]) * (htile / ytile);
			packer.add_quad (i, j, u[1], v[1], xe, ye, ue, ve);
		}
	}

	/* Update vertex buffer. */
	lisys_assert (packer.pos <= 6 * VERTEX_COUNT_MAX);
	if (vbuf->getNumVertices () < (size_t)(packer.pos / 6))
	{
		vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer (
			VERTEX_SIZE, packer.pos / 6, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
		render_op.vertexData->vertexBufferBinding->setBinding (0, vbuf);
	}
	vbuf->writeData (0, vbuf->getSizeInBytes (), packer.verts);

	/* Bind the vertex buffer. */
	render_op.useIndexes = false;
	render_op.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
	render_op.vertexData->vertexCount = packer.pos / 6;
}
static LIMdlEdge* private_extract_edges (
	LIMdlBuilder*    self,
	LIMdlBuilderLod* lod,
	int              index_count,
	int*             edge_count)
{
	int i;
	int j;
	int k;
	uint32_t i1;
	uint32_t i2;
	uint32_t index;
	uint32_t face[4];
	LIAlgU32dic* dict;
	LIMdlEdge* edge;
	LIMdlEdge* edges;
	LIMdlBuilderFaces* group;

	/* Allocate the edge list. */
	edges = lisys_calloc (index_count, sizeof (LIMdlEdge));
	if (edges == NULL)
		return NULL;
	*edge_count = 0;

	/* Allocate a temporary lookup table. */
	dict = lialg_u32dic_new ();
	if (dict == NULL)
	{
		lisys_free (edges);
		return NULL;
	}

	/* Extract the edges using the index lists. */
	for (i = 0 ; i < lod->face_groups.count ; i++)
	{
		group = lod->face_groups.array + i;
		for (j = 0 ; j < group->indices.count ; j += 3)
		{
			face[0] = group->indices.array[j];
			face[1] = group->indices.array[j + 1];
			face[2] = group->indices.array[j + 2];
			face[3] = face[0];
			for (k = 0 ; k < 3 ; k++)
			{
				i1 = LIMAT_MIN (face[k], face[k + 1]);
				i2 = LIMAT_MAX (face[k], face[k + 1]);
				index = i1 + i2 * index_count;
				edge = lialg_u32dic_find (dict, index);
				if (edge == NULL)
				{
					edge = edges + *edge_count;
					edge->i1 = i1;
					edge->i2 = i2;
					edge->users = 1;
					lialg_u32dic_insert (dict, index, edge);
					*edge_count += 1;
				}
				else
					edge->users++;
			}
		}
	}

	/* Free the lookup table. */
	lialg_u32dic_free (dict);

	return edges;
}
Beispiel #6
0
static void Terrain_count_column_materials (LIScrArgs* args)
{
	int grid_x;
	int grid_z;
	float y;
	float min;
	float max;
	float length;
	float start = 0.0f;
	float height = -1.0f;
	LIExtTerrainColumn* column;
	LIExtTerrainStick* stick;

	/* Get the arguments. */
	if (!liscr_args_geti_int (args, 0, &grid_x) || grid_x < 0)
		return;
	if (!liscr_args_geti_int (args, 1, &grid_z) || grid_z < 0)
		return;
	if (liscr_args_geti_float (args, 2, &start))
		start = LIMAT_MAX (0.0f, start);
	if (liscr_args_geti_float (args, 3, &height))
		height = LIMAT_MAX (0.0f, height);
	if (!liscr_args_geti_table (args, 4))
		return;

	/* Get the column. */
	column = liext_terrain_get_column (args->self, grid_x, grid_z);
	if (column == NULL)
		return;

	/* Count the materials and add the counts to the table. */
	for (y = 0.0f, stick = column->sticks ; stick != NULL ; y += stick->height, stick = stick->next)
	{
		if (height >= 0.0f)
		{
			min = LIMAT_MAX (y, start);
			max = LIMAT_MIN (y + stick->height, start + height);
		}
		else
		{
			min = LIMAT_MAX (y, start);
			max = y + stick->height;
		}
		length = max - min;
		if (length > 0.0f)
		{
			lua_pushnumber (args->lua, stick->material);
			lua_pushnumber (args->lua, stick->material);
			lua_gettable (args->lua, -3);
			if (lua_type (args->lua, -1) == LUA_TNUMBER)
				length += lua_tonumber (args->lua, -1);
			lua_pop (args->lua, 1);
			lua_pushnumber (args->lua, length);
			lua_settable (args->lua, -3);
		}
	}

	/* Add the remainder if the range was given. */
	if (height >= 0.0f)
	{
		length = start + height - y;
		if (length > 0.0f)
		{
			lua_pushnumber (args->lua, 0);
			lua_pushnumber (args->lua, 0);
			lua_gettable (args->lua, -3);
			if (lua_type (args->lua, -1) == LUA_TNUMBER)
				length += lua_tonumber (args->lua, -1);
			lua_pop (args->lua, 1);
			lua_pushnumber (args->lua, length);
			lua_settable (args->lua, -3);
		}
	}
}
Beispiel #7
0
static void Voxel_find_blocks (LIScrArgs* args)
{
	int sx;
	int sy;
	int sz;
	int index;
	int line;
	int stamp;
	float radius;
	LIAlgRange sectors;
	LIAlgRange blocks;
	LIAlgRange range;
	LIAlgRangeIter iter0;
	LIAlgRangeIter iter1;
	LIExtModule* module;
	LIMatVector min;
	LIMatVector max;
	LIMatVector point;
	LIMatVector size;
	LIVoxBlock* block;
	LIVoxSector* sector;

	/* Initialize arguments. */
	if (!liscr_args_gets_vector (args, "point", &point))
		return;
	liscr_args_gets_float (args, "radius", &radius);
	liscr_args_set_output (args, LISCR_ARGS_OUTPUT_TABLE_FORCE);
	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_VOXEL);
	line = module->voxels->blocks_per_line * module->voxels->sectors->count;

	/* Calculate sight volume. */
	size = limat_vector_init (radius, radius, radius);
	min = limat_vector_subtract (point, size);
	max = limat_vector_add (point, size);
	sectors = lialg_range_new_from_aabb (&min, &max, module->voxels->sectors->width);
	sectors = lialg_range_clamp (sectors, 0, module->voxels->sectors->count - 1);
	blocks = lialg_range_new_from_aabb (&min, &max, module->voxels->sectors->width / module->voxels->blocks_per_line);
	blocks = lialg_range_clamp (blocks, 0, module->voxels->blocks_per_line * module->voxels->sectors->count - 1);

	/* Loop through visible sectors. */
	LIALG_RANGE_FOREACH (iter0, sectors)
	{
		/* Get voxel sector. */
		sector = lialg_sectors_data_index (module->voxels->sectors, LIALG_SECTORS_CONTENT_VOXEL, iter0.index, 0);
		if (sector == NULL)
			continue;

		/* Calculate visible block range. */
		livox_sector_get_offset (sector, &sx, &sy, &sz);
		sx *= module->voxels->blocks_per_line;
		sy *= module->voxels->blocks_per_line;
		sz *= module->voxels->blocks_per_line;
		range.min = 0;
		range.max = module->voxels->blocks_per_line;
		range.minx = LIMAT_MAX (blocks.minx - sx, 0);
		range.miny = LIMAT_MAX (blocks.miny - sy, 0);
		range.minz = LIMAT_MAX (blocks.minz - sz, 0);
		range.maxx = LIMAT_MIN (blocks.maxx - sx, module->voxels->blocks_per_line - 1);
		range.maxy = LIMAT_MIN (blocks.maxy - sy, module->voxels->blocks_per_line - 1);
		range.maxz = LIMAT_MIN (blocks.maxz - sz, module->voxels->blocks_per_line - 1);

		/* Loop through visible blocks. */
		LIALG_RANGE_FOREACH (iter1, range)
		{
			block = livox_sector_get_block (sector, iter1.x, iter1.y, iter1.z);
			stamp = livox_block_get_stamp (block);
			index = (sx + iter1.x) + (sy + iter1.y) * line + (sz + iter1.z) * line * line;
			liscr_args_setf_float (args, index, stamp);
		}
Beispiel #8
0
/**
 * \brief Subtracts a stick from this one.
 * \param self Terrain stick.
 * \param y Vertical offset of the subtracted stick, relative to the stick bottom.
 * \param h Height of the subtracted stick.
 * \param bot00 Bottom surface vertex offsets, relative to the bottom of the subtracted stick.
 * \param bot10 Bottom surface vertex offsets, relative to the bottom of the subtracted stick.
 * \param bot01 Bottom surface vertex offsets, relative to the bottom of the subtracted stick.
 * \param bot11 Bottom surface vertex offsets, relative to the bottom of the subtracted stick.
 * \param top00 Top surface vertex offsets, relative to the top of the subtracted stick.
 * \param top10 Top surface vertex offsets, relative to the top of the subtracted stick.
 * \param top01 Top surface vertex offsets, relative to the top of the subtracted stick.
 * \param top11 Top surface vertex offsets, relative to the top of the subtracted stick.
 * \return Number between 1-6, or 0 if ran out of memory.
 */
int liext_terrain_stick_subtract (
	LIExtTerrainStick* self,
	float              y,
	float              h,
	float              bot00,
	float              bot10,
	float              bot01,
	float              bot11,
	float              top00,
	float              top10,
	float              top01,
	float              top11)
{
	LIExtTerrainStick* stick;

	/* A) Is the stick completely below us?
	 *
	 * .....SSSSSSSSSS.....
	 * XXX??...............
	 */
	if (y + h <= 0.0f)
	{
		/* In this case, nothing is done. The vertices of the stick may still
		   overlap with us, but that should be handled by calling this
		   function for the previous stick. */
		return 1;
	}

	/* B) Is the stick completely above us?
	 *
	 * .....SSSSSSSSSS.....
	 * ...............??XXX
	 */
	if (y >= self->height)
	{
		/* In this case, only the vertices of the stick may change, but the
		   height and position remain the same. The vertices are clipped so
		   that they stay below the bottom of the subtracted stick, in the
		   manner similar to case E. */
		self->vertices[0][0].offset = LIMAT_MIN (self->vertices[0][0].offset, y + bot00 - self->height);
		self->vertices[1][0].offset = LIMAT_MIN (self->vertices[1][0].offset, y + bot10 - self->height);
		self->vertices[0][1].offset = LIMAT_MIN (self->vertices[0][1].offset, y + bot01 - self->height);
		self->vertices[1][1].offset = LIMAT_MIN (self->vertices[1][1].offset, y + bot11 - self->height);
		return 2;
	}

	/* C) Does the stick replace us completely?
	 *
	 * .....SSSSSSSSSS.....
	 * ..???XXXXXXXXXX???..
	 */
	if (y <= 0.0f && y + h >= self->height)
	{
		/* In this case, the stick would become degenerate since its height
		   becomes zero. We just indicate that with the return value. The
		   caller should decide what to do about degenerate sticks. */
		return 3;
	}

	/* D) Does the stick replace part of the bottom?
	 *
	 * .....SSSSSSSSSS.....
	 * ..???XXXXX..........
	 */
	if (y <= 0.0f)
	{
		/* In this case, the stick is shortened by the length of the
		   intersection. As we assume that this function has been called
		   for the previous stick, we also adjust the top surface so that
		   the vertices are above the vertices of the previous stick. */
		/* Note the the Y offset of this stick is considered to increase
		   the same amount as its height decreases, meaning that the vertices
		   technically remain at the same absolute positions. This means that
		   the original original absolute Y coordinates must be used when
		   fixing the offsets of the surface vertices. */
		self->vertices[0][0].offset = LIMAT_MAX (self->vertices[0][0].offset, y + h + top00 - self->height);
		self->vertices[1][0].offset = LIMAT_MAX (self->vertices[1][0].offset, y + h + top10 - self->height);
		self->vertices[0][1].offset = LIMAT_MAX (self->vertices[0][1].offset, y + h + top01 - self->height);
		self->vertices[1][1].offset = LIMAT_MAX (self->vertices[1][1].offset, y + h + top11 - self->height);
		self->height -= y + h;
		private_clamp_vertices (self, self->next);
		return 4;
	}

	/* E) Does the stick replace part of the top?
	 *
	 * .....SSSSSSSSSS.....
	 * ..........XXXXX???..
	 */
	if (y + h >= self->height)
	{
		/* In this case, the stick is shortened by the length of the
		   intersection. The vertices are first raised by the length of
		   the intersection so that they will be at the original absolute
		   Y offsets. Then, they are clamped to be below the bottom vertices
		   of the subtracted stick, similar to case B. */
		self->vertices[0][0].offset += self->height - y;
		self->vertices[1][0].offset += self->height - y;
		self->vertices[0][1].offset += self->height - y;
		self->vertices[1][1].offset += self->height - y;
		self->height = y;
		self->vertices[0][0].offset = LIMAT_MIN (self->vertices[0][0].offset, y + bot00 - self->height);
		self->vertices[1][0].offset = LIMAT_MIN (self->vertices[1][0].offset, y + bot10 - self->height);
		self->vertices[0][1].offset = LIMAT_MIN (self->vertices[0][1].offset, y + bot01 - self->height);
		self->vertices[1][1].offset = LIMAT_MIN (self->vertices[1][1].offset, y + bot11 - self->height);
		return 5;
	}

	/* F) Does the stick replace part of the middle?
	 *
	 * .....SSSSSSSSSS.....
	 * ........XXXX........
	 */
	if (y > 0.0f && y + h < self->height)
	{
		/* In this case, the stick is split in two parts so that the split
		   point lies at the start of the subtracted stick. The second part
		   of the stick is allocated and inserted after this stick. After
		   that, the vertices of this stick are modified similar to case E.
		   The vertices of the next stick are clamped so that they will be
		   above the top vertices of the subtracted stick. */
		stick = liext_terrain_stick_new (self->material, self->height - y - h);
		if (stick == NULL)
			return 0;
		stick->vertices[0][0].offset = LIMAT_MAX (self->vertices[0][0].offset, y + h + top00 - self->height);
		stick->vertices[1][0].offset = LIMAT_MAX (self->vertices[1][0].offset, y + h + top10 - self->height);
		stick->vertices[0][1].offset = LIMAT_MAX (self->vertices[0][1].offset, y + h + top01 - self->height);
		stick->vertices[1][1].offset = LIMAT_MAX (self->vertices[1][1].offset, y + h + top11 - self->height);
		private_clamp_vertices (stick, self->next);
		stick->next = self->next;
		self->next = stick;
		self->vertices[0][0].offset += self->height - y;
		self->vertices[1][0].offset += self->height - y;
		self->vertices[0][1].offset += self->height - y;
		self->vertices[1][1].offset += self->height - y;
		self->height = y;
		self->vertices[0][0].offset = LIMAT_MIN (self->vertices[0][0].offset, y + bot00 - self->height);
		self->vertices[1][0].offset = LIMAT_MIN (self->vertices[1][0].offset, y + bot10 - self->height);
		self->vertices[0][1].offset = LIMAT_MIN (self->vertices[0][1].offset, y + bot01 - self->height);
		self->vertices[1][1].offset = LIMAT_MIN (self->vertices[1][1].offset, y + bot11 - self->height);
		return 6;
	}

	/* Only the above six cases are possible. */
	lisys_assert (0);

	return 0;
}