예제 #1
0
파일: gl_warp.cpp 프로젝트: TeamNyx/gdk
/*
=================
R_DrawSkyChain
=================
*/
void R_DrawSkyChain (msurface_t *s)
{
    msurface_t  *fa;

    int     i;
    vec3_t  verts[MAX_CLIP_VERTS];
    glpoly_t    *p;

    c_sky = 0;
    GL_Bind(solidskytexture);

    // calculate vertex values for sky box

    for (fa=s ; fa ; fa=fa->texturechain)
    {
        for (p=fa->polys ; p ; p=p->next)
        {
            for (i=0 ; i<p->numverts ; i++)
            {
                VectorSubtract (p->verts[i], r_origin, verts[i]);
            }
            ClipSkyPolygon (p->numverts, verts[0], 0);
        }
    }
}
예제 #2
0
파일: gl_warp.c 프로젝트: chrisnew/quake2
/*
=================
R_AddSkySurface
=================
*/
void R_AddSkySurface (const msurface_t *fa)
{
	int			i;
	vec3_t		verts[MAX_CLIP_VERTS];
	const glpoly_t	*p;

	// calculate vertex values for sky box
	for (i = 0, p = fa->polys; i < p->numverts; i++)
		VectorSubtract (p->verts[i], r_origin, verts[i]);

	ClipSkyPolygon (p->numverts, verts[0], 0);
}
예제 #3
0
파일: tr_sky.cpp 프로젝트: DaTa-/cnq3x
static void RB_ClipSkyPolygons( const shaderCommands_t* input )
{
	vec3_t p[4];	// need one extra point for clipping

	ClearSkyBox();

	for ( int i = 0; i < input->numIndexes; i += 3 ) {
		VectorSubtract( input->xyz[input->indexes[i+0]], backEnd.viewParms.or.origin, p[0] );
		VectorSubtract( input->xyz[input->indexes[i+1]], backEnd.viewParms.or.origin, p[1] );
		VectorSubtract( input->xyz[input->indexes[i+2]], backEnd.viewParms.or.origin, p[2] );
		ClipSkyPolygon( 3, p[0], 0 );
	}
}
예제 #4
0
파일: sky.c 프로젝트: icanhas/yantar
/*
 * RB_ClipSkyPolygons
 */
void
RB_ClipSkyPolygons(shaderCommands_t *input)
{
	Vec3	p[5];	/* need one extra point for clipping */
	int	i, j;

	ClearSkyBox();

	for(i = 0; i < input->numIndexes; i += 3){
		for(j = 0; j < 3; j++)
			subv3(input->xyz[input->indexes[i+j]],
				backEnd.viewParms.or.origin,
				p[j]);
		ClipSkyPolygon(3, p[0], 0);
	}
}
예제 #5
0
/*
================
Tess_ClipSkyPolygons
================
*/
void Tess_ClipSkyPolygons()
{
	vec3_t p[ 5 ]; // need one extra point for clipping
	unsigned int i, j;

	ClearSkyBox();

	for ( i = 0; i < tess.numIndexes; i += 3 )
	{
		for ( j = 0; j < 3; j++ )
		{
			VectorSubtract( tess.xyz[ tess.indexes[ i + j ] ], backEnd.viewParms.orientation.origin, p[ j ] );
		}

		ClipSkyPolygon( 3, p[ 0 ], 0 );
	}
}
예제 #6
0
파일: tr_sky.c 프로젝트: Razish/QtZ
void RB_ClipSkyPolygons( shaderCommands_t *input ) {
    vector3		p[5];	// need one extra point for clipping
    int			i, j;

    ClearSkyBox();

    for ( i = 0; i < input->numIndexes; i += 3 )
    {
        for (j = 0 ; j < 3 ; j++)
        {
            VectorSubtract( &input->xyz[input->indexes[i+j]],
                            &backEnd.viewParms.or.origin,
                            &p[j] );
        }
        ClipSkyPolygon( 3, &p[0], 0 );
    }
}
예제 #7
0
파일: gl_warp.c 프로젝트: luaman/qforge-old
/*
	R_DrawSkyChain
*/
void
R_DrawSkyChain ( msurface_t *s )
{
	msurface_t	*fa;

	int		i;
	vec3_t	verts[MAX_CLIP_VERTS];
	glpoly_t	*p;

	if (r_sky->value) {
		c_sky = 0;
		GL_Bind(solidskytexture);

		// calculate vertex values for sky box
		for (fa=s ; fa ; fa=fa->texturechain) {
			for (p=fa->polys ; p ; p=p->next) {
				for (i=0 ; i<p->numverts ; i++) {
					VectorSubtract (p->verts[i], r_origin, verts[i]);
				}
				ClipSkyPolygon (p->numverts, verts[0], 0);
			}
		}
	} else {
		GL_DisableMultitexture();

		// used when gl_texsort is on
		GL_Bind(solidskytexture);
		speedscale = realtime*8;
		speedscale -= (int)speedscale & ~127 ;

		for (fa=s ; fa ; fa=fa->texturechain)
			EmitSkyPolys (fa);

		glEnable (GL_BLEND);
		GL_Bind (alphaskytexture);
		speedscale = realtime*16;
		speedscale -= (int)speedscale & ~127 ;

		for ( fa=s ; fa != NULL ; fa = fa->texturechain )
			EmitSkyPolys (fa);

		glDisable (GL_BLEND);
	}
}
예제 #8
0
파일: gl_sky.c 프로젝트: Bad-ptr/q2pro
/*
=================
R_AddSkySurface
=================
*/
void R_AddSkySurface( mface_t *fa ) {
    int         i;
    vec3_t      verts[MAX_CLIP_VERTS];
    msurfedge_t *surfedge;
    mvertex_t   *vert;
    medge_t     *edge;

    if( fa->numsurfedges > MAX_CLIP_VERTS ) {
        Com_Error( ERR_DROP, "%s: too many verts", __func__ );
    }

    // calculate vertex values for sky box
    surfedge = fa->firstsurfedge;
    for( i = 0; i < fa->numsurfedges; i++, surfedge++ ) {
        edge = surfedge->edge;
        vert = edge->v[surfedge->vert];
        VectorSubtract (vert->point, glr.fd.vieworg, verts[i]);
    }
    ClipSkyPolygon (fa->numsurfedges, verts[0], 0);
}
예제 #9
0
파일: r_sky.c 프로젝트: adem4ik/qfusion
/*
* R_ClipSkySurface
*/
bool R_ClipSkySurface( drawSurfaceSky_t *drawSurf, const msurface_t *surf ) {
	int i;
	const vec4_t *vert;
	const elem_t *elem;
	const mesh_t *mesh;
	vec3_t verts[4];
	int axis = -1;

	// calculate vertex values for sky box
	mesh = &surf->mesh;
	elem = mesh->elems;
	vert = mesh->xyzArray;
	for( i = 0; i < mesh->numElems; i += 3, elem += 3 ) {
		VectorSubtract( vert[elem[0]], rn.viewOrigin, verts[0] );
		VectorSubtract( vert[elem[1]], rn.viewOrigin, verts[1] );
		VectorSubtract( vert[elem[2]], rn.viewOrigin, verts[2] );
		ClipSkyPolygon( drawSurf, 3, verts[0], 0, &axis );
	}

	return axis != -1;
}
예제 #10
0
/*
* R_AddSkyToDrawList
*/
void R_AddSkyToDrawList( const msurface_t *fa )
{
	int i;
	vec3_t *vert;
	elem_t	*elem;
	mesh_t *mesh;
	vec3_t verts[4];

	// calculate vertex values for sky box
	r_warpFace = fa;
	r_warpFaceVis = qfalse;

	mesh = fa->mesh;
	elem = mesh->elems;
	vert = mesh->xyzArray;
	for( i = 0; i < mesh->numElems; i += 3, elem += 3 )
	{
		VectorSubtract( vert[elem[0]], rn.viewOrigin, verts[0] );
		VectorSubtract( vert[elem[1]], rn.viewOrigin, verts[1] );
		VectorSubtract( vert[elem[2]], rn.viewOrigin, verts[2] );
		ClipSkyPolygon( 3, verts[0], 0 );
	}

	if( r_warpFaceVis ) {
		if( fa->fog ) {
			rn.skyFog = fa->fog;
		} else if( r_worldbrushmodel->globalfog ) {
			rn.skyFog = r_worldbrushmodel->globalfog;
		}

		// there should be only one sky drawSurf in the list
		if( !rn.skyShader ) {
			rn.skyShader = fa->shader;
			R_AddDSurfToDrawList( rsc.worldent, NULL, fa->shader, 0, r_warpFaceAxis, NULL, &r_skySurf );
		}
	}
}
예제 #11
0
파일: tr_sky.cpp 프로젝트: Jsoucek/q3ce
/*
================
ClipSkyPolygon
================
*/
static void ClipSkyPolygon (int nump, bvec3_t vecs, int stage) 
{
	bfixed	*norm;
	bfixed	*v;
	qboolean	front, back;
	bfixed	d, e;
	bfixed	dists[MAX_CLIP_VERTS];
	int		sides[MAX_CLIP_VERTS];
	bvec3_t	newv[2][MAX_CLIP_VERTS];
	int		newc[2];
	int		i, j;

	if (nump > MAX_CLIP_VERTS-2)
		ri.Error (ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS");
	if (stage == 6)
	{	// fully clipped, so draw it
		AddSkyPolygon (nump, vecs);
		return;
	}

	front = back = qfalse;
	norm = sky_clip[stage];
	for (i=0, v = vecs ; i<nump ; i++, v+=3)
	{
		d = FIXED_VEC3DOT (v, norm);
		if (d > ON_EPSILON)
		{
			front = qtrue;
			sides[i] = SIDE_FRONT;
		}
		else if (d < -ON_EPSILON)
		{
			back = qtrue;
			sides[i] = SIDE_BACK;
		}
		else
			sides[i] = SIDE_ON;
		dists[i] = d;
	}

	if (!front || !back)
	{	// not clipped
		ClipSkyPolygon (nump, vecs, stage+1);
		return;
	}

	// clip it
	sides[i] = sides[0];
	dists[i] = dists[0];
	VectorCopy (vecs, (vecs+(i*3)) );
	newc[0] = newc[1] = 0;

	for (i=0, v = vecs ; i<nump ; i++, v+=3)
	{
		switch (sides[i])
		{
		case SIDE_FRONT:
			VectorCopy (v, newv[0][newc[0]]);
			newc[0]++;
			break;
		case SIDE_BACK:
			VectorCopy (v, newv[1][newc[1]]);
			newc[1]++;
			break;
		case SIDE_ON:
			VectorCopy (v, newv[0][newc[0]]);
			newc[0]++;
			VectorCopy (v, newv[1][newc[1]]);
			newc[1]++;
			break;
		}

		if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
			continue;

		d = dists[i] / (dists[i] - dists[i+1]);
		for (j=0 ; j<3 ; j++)
		{
			e = v[j] + d*(v[j+3] - v[j]);
			newv[0][newc[0]][j] = e;
			newv[1][newc[1]][j] = e;
		}
		newc[0]++;
		newc[1]++;
	}

	// continue
	ClipSkyPolygon (newc[0], newv[0][0], stage+1);
	ClipSkyPolygon (newc[1], newv[1][0], stage+1);
}
예제 #12
0
static void ClipSkyPolygon (int nump, vec3_t vecs, int stage)
{
	float	*norm;
	float	*v;
	qboolean	front, back;
	float	d, e;
	float	dists[MAX_CLIP_VERTS];
	int		sides[MAX_CLIP_VERTS];
	vec3_t	newv[2][MAX_CLIP_VERTS];
	int		newc[2];
	int		i, j;

	if (nump > MAX_CLIP_VERTS-2)
		Sys_Error ("%s: MAX_CLIP_VERTS", __thisfunc__);
	if (stage == 6)
	{	// fully clipped, so draw it
		DrawSkyPolygon (nump, vecs);
		return;
	}

	front = back = false;
	norm = skyclip[stage];
	for (i = 0, v = vecs; i < nump; i++, v += 3)
	{
		d = DotProduct (v, norm);
		if (d > ON_EPSILON)
		{
			front = true;
			sides[i] = SIDE_FRONT;
		}
		else if (d < ON_EPSILON)
		{
			back = true;
			sides[i] = SIDE_BACK;
		}
		else
			sides[i] = SIDE_ON;
		dists[i] = d;
	}

	if (!front || !back)
	{	// not clipped
		ClipSkyPolygon (nump, vecs, stage+1);
		return;
	}

	// clip it
	sides[i] = sides[0];
	dists[i] = dists[0];
	VectorCopy (vecs, (vecs+(i*3)) );
	newc[0] = newc[1] = 0;

	for (i = 0, v = vecs; i < nump; i++, v += 3)
	{
		switch (sides[i])
		{
		case SIDE_FRONT:
			VectorCopy (v, newv[0][newc[0]]);
			newc[0]++;
			break;
		case SIDE_BACK:
			VectorCopy (v, newv[1][newc[1]]);
			newc[1]++;
			break;
		case SIDE_ON:
			VectorCopy (v, newv[0][newc[0]]);
			newc[0]++;
			VectorCopy (v, newv[1][newc[1]]);
			newc[1]++;
			break;
		}

		if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
			continue;

		d = dists[i] / (dists[i] - dists[i+1]);
		for (j = 0; j < 3; j++)
		{
			e = v[j] + d*(v[j+3] - v[j]);
			newv[0][newc[0]][j] = e;
			newv[1][newc[1]][j] = e;
		}
		newc[0]++;
		newc[1]++;
	}

	// continue
	ClipSkyPolygon (newc[0], newv[0][0], stage+1);
	ClipSkyPolygon (newc[1], newv[1][0], stage+1);
}
예제 #13
0
void Sky_Render(DrawCallList *drawCallList, vec3 cameraPosition, float zMax, const SkySurface &surface)
{
	assert(drawCallList);

	const bool shouldDrawSkyBox = surface.material->sky.outerbox[0] && surface.material->sky.outerbox[0] != Texture::getDefault();
	const bool shouldDrawCloudBox = surface.material->sky.cloudHeight > 0 && surface.material->stages[0].active;

	if (!shouldDrawSkyBox && !shouldDrawCloudBox)
		return;

	// Clear sky box.
	for (size_t i = 0; i < 6; i++)
	{
		sky_mins[0][i] = sky_mins[1][i] = 9999;
		sky_maxs[0][i] = sky_maxs[1][i] = -9999;
	}

	// Clip sky polygons.
	for (size_t i = 0; i < surface.vertices.size(); i += 3)
	{
		vec3 p[5]; // need one extra point for clipping

		for (size_t j = 0 ; j < 3 ; j++) 
		{
			p[j] = surface.vertices[i + j].pos - cameraPosition;
		}

		ClipSkyPolygon(3, p, 0);
	}

	// Draw the skybox.
	if (shouldDrawSkyBox)
	{
		for (int i = 0; i < 6; i++)
		{
			uint32_t nVertices, nIndices;
			sky_min = 0;
			sky_max = 1;
			memset( s_skyTexCoords, 0, sizeof( s_skyTexCoords ) );

			if (!TessellateSkyBoxSide(i, nullptr, nullptr, &nVertices, &nIndices, cameraPosition, zMax))
				continue;

			DrawCall dc;

			if (!bgfx::allocTransientBuffers(&dc.vb.transientHandle, Vertex::decl, nVertices, &dc.ib.transientHandle, nIndices)) 
			{
				WarnOnce(WarnOnceId::TransientBuffer);
				return;
			}

			sky_min = 0;
			sky_max = 1;
			memset( s_skyTexCoords, 0, sizeof( s_skyTexCoords ) );
			TessellateSkyBoxSide(i, (Vertex *)dc.vb.transientHandle.data, (uint16_t *)dc.ib.transientHandle.data, nullptr, nullptr, cameraPosition, zMax);
			dc.vb.type = dc.ib.type = DrawCall::BufferType::Transient;
			dc.vb.nVertices = nVertices;
			dc.ib.nIndices = nIndices;
			dc.flags = DrawCallFlags::Sky | DrawCallFlags::Skybox;
			dc.material = surface.material;
			dc.skyboxSide = i;
			dc.state |= BGFX_STATE_DEPTH_TEST_LEQUAL;

			// Write depth as 1.
			dc.zOffset = 1.0f;
			dc.zScale = 0.0f;
			drawCallList->push_back(dc);
		}
	}

	// Draw the clouds.
	if (shouldDrawCloudBox)
	{
		uint32_t nVertices, nIndices;
		TessellateCloudBox(nullptr, nullptr, &nVertices, &nIndices, cameraPosition, zMax);
		DrawCall dc;

		if (!bgfx::allocTransientBuffers(&dc.vb.transientHandle, Vertex::decl, nVertices, &dc.ib.transientHandle, nIndices)) 
		{
			WarnOnce(WarnOnceId::TransientBuffer);
			return;
		}

		TessellateCloudBox((Vertex *)dc.vb.transientHandle.data, (uint16_t *)dc.ib.transientHandle.data, nullptr, nullptr, cameraPosition, zMax);
		dc.vb.type = dc.ib.type = DrawCall::BufferType::Transient;
		dc.vb.nVertices = nVertices;
		dc.ib.nIndices = nIndices;
		dc.flags = DrawCallFlags::Sky;
		dc.material = surface.material;
		dc.sort = 1; // Render after the skybox.

		// Write depth as 1.
		dc.zOffset = 1.0f;
		dc.zScale = 0.0f;
		drawCallList->push_back(dc);
	}
}
예제 #14
0
static void ClipSkyPolygon(int nump, vec3 *vecs, int stage) 
{
	bool front, back;
	float	d, e;
	float	dists[MAX_CLIP_VERTS];
	int		sides[MAX_CLIP_VERTS];
	vec3	newv[2][MAX_CLIP_VERTS];
	int		newc[2];
	int		i, j;

	if (nump > MAX_CLIP_VERTS-2)
		interface::Error("ClipSkyPolygon: MAX_CLIP_VERTS");
	if (stage == 6)
	{	// fully clipped, so draw it
		AddSkyPolygon (nump, vecs);
		return;
	}

	front = back = false;

	for (i=0; i<nump ; i++)
	{
		d = vec3::dotProduct(vecs[i], sky_clip[stage]);
		if (d > ON_EPSILON)
		{
			front = true;
			sides[i] = SIDE_FRONT;
		}
		else if (d < -ON_EPSILON)
		{
			back = true;
			sides[i] = SIDE_BACK;
		}
		else
			sides[i] = SIDE_ON;
		dists[i] = d;
	}

	if (!front || !back)
	{	// not clipped
		ClipSkyPolygon (nump, vecs, stage+1);
		return;
	}

	// clip it
	sides[i] = sides[0];
	dists[i] = dists[0];
	vecs[i] = vecs[0];
	newc[0] = newc[1] = 0;

	for (i=0; i<nump ; i++)
	{
		const vec3 &v = vecs[i];

		switch (sides[i])
		{
		case SIDE_FRONT:
			newv[0][newc[0]] = v;
			newc[0]++;
			break;
		case SIDE_BACK:
			newv[1][newc[1]] = v;
			newc[1]++;
			break;
		case SIDE_ON:
			newv[0][newc[0]] = v;
			newc[0]++;
			newv[1][newc[1]] = v;
			newc[1]++;
			break;
		}

		if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
			continue;

		d = dists[i] / (dists[i] - dists[i+1]);
		for (j=0 ; j<3 ; j++)
		{
			e = v[j] + d*(vecs[i + 1][j] - v[j]);
			newv[0][newc[0]][j] = e;
			newv[1][newc[1]][j] = e;
		}
		newc[0]++;
		newc[1]++;
	}

	// continue
	ClipSkyPolygon(newc[0], &newv[0][0], stage+1);
	ClipSkyPolygon(newc[1], &newv[1][0], stage+1);
}
예제 #15
0
파일: r_sky.c 프로젝트: adem4ik/qfusion
/*
* ClipSkyPolygon
*/
static void ClipSkyPolygon( drawSurfaceSky_t *drawSurf, int nump, vec_t *vecs, int stage, int *visAxis ) {
	const float *norm;
	float *v;
	bool front, back;
	float d, e;
	float dists[MAX_CLIP_VERTS + 1];
	int sides[MAX_CLIP_VERTS + 1];
	vec3_t newv[2][MAX_CLIP_VERTS + 1];
	int newc[2];
	int i, j;

	if( nump > MAX_CLIP_VERTS ) {
		ri.Com_Error( ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS" );
		return;
	}

loc1:
	if( stage == 6 ) {
		// fully clipped, so draw it
		DrawSkyPolygon( drawSurf, nump, vecs, visAxis );
		return;
	}

	front = back = false;
	norm = skyclip[stage];
	for( i = 0, v = vecs; i < nump; i++, v += 3 ) {
		d = DotProduct( v, norm );
		if( d > ON_EPSILON ) {
			front = true;
			sides[i] = SIDE_FRONT;
		} else if( d < -ON_EPSILON ) {
			back = true;
			sides[i] = SIDE_BACK;
		} else {
			sides[i] = SIDE_ON;
		}
		dists[i] = d;
	}

	if( !front || !back ) { // not clipped
		stage++;
		goto loc1;
	}

	// clip it
	sides[i] = sides[0];
	dists[i] = dists[0];
	VectorCopy( vecs, ( vecs + ( i * 3 ) ) );
	newc[0] = newc[1] = 0;

	for( i = 0, v = vecs; i < nump; i++, v += 3 ) {
		switch( sides[i] ) {
			case SIDE_FRONT:
				VectorCopy( v, newv[0][newc[0]] );
				newc[0]++;
				break;
			case SIDE_BACK:
				VectorCopy( v, newv[1][newc[1]] );
				newc[1]++;
				break;
			case SIDE_ON:
				VectorCopy( v, newv[0][newc[0]] );
				newc[0]++;
				VectorCopy( v, newv[1][newc[1]] );
				newc[1]++;
				break;
		}

		if( sides[i] == SIDE_ON || sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i] ) {
			continue;
		}

		d = dists[i] / ( dists[i] - dists[i + 1] );
		for( j = 0; j < 3; j++ ) {
			e = v[j] + d * ( v[j + 3] - v[j] );
			newv[0][newc[0]][j] = e;
			newv[1][newc[1]][j] = e;
		}
		newc[0]++;
		newc[1]++;
	}

	// continue
	ClipSkyPolygon( drawSurf, newc[0], newv[0][0], stage + 1, visAxis );
	ClipSkyPolygon( drawSurf, newc[1], newv[1][0], stage + 1, visAxis );
}
예제 #16
0
파일: sky.c 프로젝트: icanhas/yantar
/*
 * ClipSkyPolygon
 */
static void
ClipSkyPolygon(int nump, Vec3 vecs, int stage)
{
	float *norm;
	float *v;
	qbool		front, back;
	float		d, e;
	float		dists[MAX_CLIP_VERTS];
	int		sides[MAX_CLIP_VERTS];
	Vec3		newv[2][MAX_CLIP_VERTS];
	int		newc[2];
	int		i, j;

	if(nump > MAX_CLIP_VERTS-2)
		ri.Error (ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS");
	if(stage == 6){	/* fully clipped, so draw it */
		AddSkyPolygon (nump, vecs);
		return;
	}

	front	= back = qfalse;
	norm	= sky_clip[stage];
	for(i=0, v = vecs; i<nump; i++, v+=3){
		d = dotv3 (v, norm);
		if(d > ON_EPSILON){
			front = qtrue;
			sides[i] = SIDE_FRONT;
		}else if(d < -ON_EPSILON){
			back = qtrue;
			sides[i] = SIDE_BACK;
		}else
			sides[i] = SIDE_ON;
		dists[i] = d;
	}

	if(!front || !back){	/* not clipped */
		ClipSkyPolygon (nump, vecs, stage+1);
		return;
	}

	/* clip it */
	sides[i] = sides[0];
	dists[i] = dists[0];
	copyv3 (vecs, (vecs+(i*3)));
	newc[0] = newc[1] = 0;

	for(i=0, v = vecs; i<nump; i++, v+=3){
		switch(sides[i]){
		case SIDE_FRONT:
			copyv3 (v, newv[0][newc[0]]);
			newc[0]++;
			break;
		case SIDE_BACK:
			copyv3 (v, newv[1][newc[1]]);
			newc[1]++;
			break;
		case SIDE_ON:
			copyv3 (v, newv[0][newc[0]]);
			newc[0]++;
			copyv3 (v, newv[1][newc[1]]);
			newc[1]++;
			break;
		}

		if(sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
			continue;

		d = dists[i] / (dists[i] - dists[i+1]);
		for(j=0; j<3; j++){
			e = v[j] + d*(v[j+3] - v[j]);
			newv[0][newc[0]][j] = e;
			newv[1][newc[1]][j] = e;
		}
		newc[0]++;
		newc[1]++;
	}

	/* continue */
	ClipSkyPolygon (newc[0], newv[0][0], stage+1);
	ClipSkyPolygon (newc[1], newv[1][0], stage+1);
}