Advertisement

is there any easy way to slice polygon?

Started by November 07, 2020 01:21 PM
4 comments, last by JoeJ 4 years, 2 months ago

i'm just trying to make simple version of fruits ninja by opengl.

all i need to do is slice rectangle (it has 4 vertex)

but i'm really stuck in this bad code

can anyone help me? here's my codes

vertex Shader

#version 330

layout(location = 0)in vec3 in_Position;
layout(location = 1)in vec3 in_Color;

uniform mat4 modelTransform;
uniform mat4 projectionTransform;
uniform mat4 viewTransform;

out vec3 ex_Color;

void main(void)
{
	gl_Position = vec4(in_Position, 1.0);
	ex_Color = in_Color;
}

Frag Shader

#version 330

in vec3 ex_Color;

out vec4 gl_FragColor;

void main(void)
{
	gl_FragColor = vec4(ex_Color,1.0);
}
#include <fstream>
#include <iostream>
#include <string>

#include <gl/glew.h>
#include <gl/freeglut.h>
#include <gl/freeglut_ext.h>

#include <glm.hpp>
#include <ext.hpp>
#include <gtc/matrix_transform.hpp>

#include <time.h>
#include <stdlib.h>
#include <vector>
#include <math.h>


using namespace std;

class Point
{
public:
	float x;
	float y;
};

class Piece
{
public:
	float x, y;
	float dx, dy;
	float Vert[4][3];
	float Color[4][3];

	int ID;

	GLuint VAO;
	GLuint VBO[2];

	void Reshape()
	{
		glGenVertexArrays(1, &VAO);
		glBindVertexArray(VAO);
		glGenBuffers(2, VBO);

		glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
		glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), Vert, GL_STATIC_DRAW);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(0);

		glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
		glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), Color, GL_STATIC_DRAW);
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(1);
	}
	Piece()
	{
		x = NULL;
		y = NULL;
		dx = NULL;
		dy = NULL;

		ID = NULL;
	}

	Piece(int id, float deltax, float deltay)
	{
		x = -1.1f;
		y = 0.5f;

		for (int i = 0; i < 4; ++i)
		{
			Color[i][0] = 1;
			Color[i][1] = 0;
			Color[i][2] = 1;
		}

		Vert[0][0] = x - 0.1f;
		Vert[0][1] = y + 0.1f;
		Vert[0][2] = 0;

		Vert[1][0] = x - 0.1f;
		Vert[1][1] = y - 0.1f;
		Vert[1][2] = 0;

		Vert[2][0] = x + 0.1f;
		Vert[2][1] = y + 0.1f;
		Vert[2][2] = 0;

		Vert[3][0] = x + 0.1f;
		Vert[3][1] = y - 0.1f;
		Vert[3][2] = 0;



		Reshape();

		ID = id;
		dx = deltax;
		dy = deltay;
	}

	Piece(int id, float deltax, float deltay, float v0[3], float v1[3], float v2[3], float v3[3])
	{
		ID = id;

		dx = deltax;
		dy = deltay;

		for (int i = 0; i < 4; ++i)
		{
			Color[i][0] = 1;
			Color[i][1] = 0;
			Color[i][2] = 1;
		}

		for (int i = 0; i < 3; ++i)
		{
			Vert[0][i] = v0[i];
			Vert[1][i] = v1[i];
			Vert[2][i] = v2[i];
			Vert[3][i] = v3[i];
		}

		x = Vert[2][0] - Vert[0][0];
		y = Vert[2][1] = Vert[0][1];

		glGenVertexArrays(1, &VAO);
		glBindVertexArray(VAO);
		glGenBuffers(2, VBO);

		glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
		glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), Vert, GL_STATIC_DRAW);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(0);

		glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
		glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), Color, GL_STATIC_DRAW);
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(1);
	}
};

int cid = 0;
int delay = 0;

const float length = 0.5;

char* arr;

bool isClick = 0;


GLuint vertexShader;
GLuint fragmentShader;

GLuint ShaderProgram;

GLuint HLineVAO[3];
GLuint VLineVAO[6];
GLuint VBO[2];

GLuint MouseVAO;
float MouseLine[2][3];
float MouseLineColor[2][3] = {
	{0, 0, 0},
	{0, 0, 0}
};


vector<Piece> RectList;
vector<Point> LineList;

void convertXY(int w, int h, int x, int y, float& ox, float& oy)
{
	ox = (float)(x - (float)w / 2.0) * (float)(1.0 / (float)(w / 2.0));
	oy = -(float)(y - (float)h / 2.0) * (float)(1.0 / (float)(h / 2.0));
}


GLchar* filetobuf(const char* filename)
{
	string tmp;
	string Source;
	ifstream readFile;

	readFile.open(filename);

	readFile.seekg(0, ios::end);
	Source.reserve(readFile.tellg());
	readFile.seekg(0, ios::beg);

	Source.assign((istreambuf_iterator<char>(readFile)), istreambuf_iterator<char>());

	arr = new char[Source.length() + 2];

	strcpy_s(arr, Source.length() + 1, Source.c_str());

	arr[Source.length() + 1] = '\0';

	return arr;
}

void make_vertexShaders()
{
	GLchar* vertexShaderSource = filetobuf("Vertex.glsl");

	//--- 버텍스 세이더 읽어 저장하고 컴파일 하기
	vertexShader = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
	glCompileShader(vertexShader);
	delete[] arr;

	GLint result;
	GLchar errorLog[512];

	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &result);
	if (!result)
	{
		glGetShaderInfoLog(vertexShader, 512, NULL, errorLog);
		cerr << "ERROR: vertex shader 컴파일 실패\n" << errorLog << endl;
		return;
	}
}

void make_fragmentShaders()
{
	GLchar* fragmentShaderSource = filetobuf("Fragment.glsl");;

	//--- 프래그먼트 세이더 읽어 저장하고 컴파일하기
	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
	glCompileShader(fragmentShader);
	delete[] arr;

	GLint result;
	GLchar errorLog[512];

	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &result);
	if (!result)
	{
		glGetShaderInfoLog(fragmentShader, 512, NULL, errorLog);
		cerr << "ERROR: fragment shader 컴파일 실패\n" << errorLog << endl;
		return;
	}
}

void InitBuffer()
{
	float HLine[3][2][3];
	float HLineColor[2][3] = {
		{ 0.0f, 0.0f, 1.0f },
		{ 0.0f, 0.0f, 1.0f }
	};
	float VLine[6][2][3];
	float VLineColor[2][3] = {
		{ 0.0f, 0.0f, 1.0f },
		{ 0.0f, 0.0f, 1.0f }
	};

	for(int i = 0; i < 3; ++i)
	{
		HLine[i][0][0] = -1.0f;
		HLine[i][0][1] = -0.7 - 0.1 * i;
		HLine[i][0][2] = 0;

		HLine[i][1][0] = 1.0f;
		HLine[i][1][1] = -0.7 - 0.1 * i;
		HLine[i][1][2] = 0;
	}

	for (int i = 0; i < 3; ++i)
	{
		glGenVertexArrays(1, &HLineVAO[i]);
		glBindVertexArray(HLineVAO[i]);
		glGenBuffers(2, VBO);

		glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
		glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(GLfloat), HLine[i], GL_STATIC_DRAW);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(0);

		glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
		glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(GLfloat), HLineColor, GL_STATIC_DRAW);
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(1);
	}

	for (int i = 0; i < 6; ++i)
	{
		VLine[i][0][0] = -1.0f + (2.0f / 6) * i;
		VLine[i][0][1] = -0.7f;
		VLine[i][0][2] = 0;

		VLine[i][1][0] = -1.0f + (2.0f / 6) * i;
		VLine[i][1][1] = -1.0f;
		VLine[i][1][2] = 0;
	}

	for (int i = 0; i < 6; ++i)
	{
		glGenVertexArrays(1, &VLineVAO[i]);
		glBindVertexArray(VLineVAO[i]);
		glGenBuffers(2, VBO);

		glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
		glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(GLfloat), VLine[i], GL_STATIC_DRAW);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(0);

		glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
		glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(GLfloat), VLineColor, GL_STATIC_DRAW);
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(1);
	}
}

void InitShader()
{
	make_vertexShaders();
	make_fragmentShaders();

	//-- shader Program
	ShaderProgram = glCreateProgram();
	glAttachShader(ShaderProgram, vertexShader);
	glAttachShader(ShaderProgram, fragmentShader);
	glLinkProgram(ShaderProgram);

	//--- 세이더 삭제하기
	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);
	//--- Shader Program 사용하기
	glUseProgram(ShaderProgram);
}

GLvoid drawScene() //--- 콜백 함수: 그리기 콜백 함수
{
	glClearColor(1, 1, 1, 1);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	if (isClick)
	{
		glBindVertexArray(MouseVAO);
		glDrawArrays(GL_LINES, 0, 2);
	}

	for (int i = 0; i < 6; ++i)
	{
		glBindVertexArray(VLineVAO[i]);
		glDrawArrays(GL_LINES, 0, 2);
	}

	for (int i = 0; i < 3; ++i)
	{
		glBindVertexArray(HLineVAO[i]);
		glDrawArrays(GL_LINES, 0, 2);
	}
	

	vector<Piece>::iterator iter = RectList.begin();

	for (; iter != RectList.end(); iter++)
	{
		for (int i = 0; i < 4; ++i)
		{
			iter->Vert[i][0] += iter->dx;
			iter->Vert[i][1] += iter->dy;
		}

		iter->Reshape();

		glBindVertexArray(iter->VAO);
		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	}


	glutSwapBuffers(); // 화면에 출력하기
}

GLvoid Keyboard(unsigned char key, int x, int y)
{
	switch (key)
	{
	case 'q':
		exit(0);
		break;
	case 'Q':
		exit(0);
		break;
	}
}

GLvoid Mouse(int button, int state, int x, int y)
{
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
	{
		float ox, oy;

		convertXY(1000, 1000, x, y, ox, oy);

		MouseLine[0][0] = ox;
		MouseLine[0][1] = oy;
		MouseLine[0][2] = 0;
	}

	else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
	{
		if (MouseLine[0][0] != MouseLine[1][0])
		{
			vector<Piece>::iterator Riter = RectList.begin();

			for (; Riter != RectList.end();)
			{
				int cnt = 0;
				float Cutted[2][3];
				Piece r1;
				Piece r2;

				bool isSet = 0;

				vector<Point>::iterator Piter = LineList.begin();

				for (; Piter != LineList.end(); ++Piter)
				{
					if (cnt == 0 && Piter->x > Riter->Vert[0][0] && Piter->x < Riter->Vert[3][0] && Piter->y < Riter->Vert[0][1] && Piter->y > Riter->Vert[3][1])
					{
						Cutted[0][0] = Piter->x;
						Cutted[0][1] = Piter->y;
						Cutted[0][2] = 0;
						cnt++;
					}
					else if (cnt == 1 && (Piter->x < Riter->Vert[0][0] || Piter->x > Riter->Vert[3][0] || Piter->y > Riter->Vert[0][1] || Piter->y < Riter->Vert[3][1]))
					{
						Cutted[1][0] = Piter->x;
						Cutted[1][1] = Piter->y;
						Cutted[1][2] = 0;
						break;
					}
				}

				if (Cutted[0][0] < Riter->Vert[0][0] + 0.05 && Cutted[0][0] > Riter->Vert[0][0] - 0.05 && Cutted[0][1] < Riter->Vert[0][1] && Cutted[0][1] > Riter->Vert[1][1])
				{
					r1 = Piece(cid, -0.001f, -0.005f, Riter->Vert[0], Cutted[0], Riter->Vert[2], Cutted[1]);
					cid++;
					r2 = Piece(cid, 0.001f, -0.005f, Cutted[0], Riter->Vert[1], Cutted[1], Riter->Vert[3]);
					Riter = RectList.erase(Riter);
					isSet = 1;
				}
				else if (Cutted[0][0] < Riter->Vert[2][0] + 0.05 && Cutted[0][0] > Riter->Vert[2][0] - 0.05 && Cutted[0][1] < Riter->Vert[2][1] && Cutted[0][1] > Riter->Vert[3][1])
				{
					r1 = Piece(cid, -0.001f, -0.005f, Riter->Vert[0], Cutted[1], Riter->Vert[2], Cutted[0]);
					cid++;
					r2 = Piece(cid, 0.001f, -0.005f, Cutted[1], Riter->Vert[1], Cutted[0], Riter->Vert[3]);
					Riter = RectList.erase(Riter);
					isSet = 1;
				}
				else if (Cutted[0][1] < Riter->Vert[1][1] + 0.05 && Cutted[0][1] > Riter->Vert[1][1] - 0.05 && Cutted[0][0] < Riter->Vert[1][0] && Cutted[0][0] > Riter->Vert[3][0])
				{
					r1 = Piece(cid, -0.001f, -0.005f, Riter->Vert[0], Riter->Vert[1], Cutted[1], Cutted[0]);
					cid++; 
					r2 = Piece(cid, 0.001f, -0.005f, Cutted[1], Cutted[0], Riter->Vert[2], Riter->Vert[3]);
					Riter = RectList.erase(Riter);
					isSet = 1;
				}
				else if (Cutted[0][1] < Riter->Vert[0][1] + 0.05 && Cutted[0][1] > Riter->Vert[0][1] - 0.05 && Cutted[0][0] < Riter->Vert[0][0] && Cutted[0][0] > Riter->Vert[2][0])
				{
					r1 = Piece(cid, -0.001f, -0.005f, Riter->Vert[0], Riter->Vert[1], Cutted[0], Cutted[1]);
					cid++;
					r2 = Piece(cid, 0.001f, -0.005f, Cutted[0], Cutted[1], Riter->Vert[2], Riter->Vert[3]);
					Riter = RectList.erase(Riter);
					isSet = 1;
				}
				else
				{
					Riter++;
				}

				if(isSet)
				{
					RectList.push_back(r1);
					RectList.push_back(r2);
					break;
				}
			}
		}
	}

	isClick = 0;
	LineList.clear();
}

GLvoid Motion(int x, int y)
{
	float ox, oy;

	isClick = 1;

	convertXY(1000, 1000, x, y, ox, oy);

	MouseLine[1][0] = ox;
	MouseLine[1][1] = oy;
	MouseLine[1][2] = 0;

	Point p;
	p.x = ox;
	p.y = oy;

	LineList.push_back(p);

	glGenVertexArrays(1, &MouseVAO);
	glBindVertexArray(MouseVAO);
	glGenBuffers(2, VBO);

	glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
	glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(GLfloat), MouseLine, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);

	glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
	glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(GLfloat), MouseLineColor, GL_STATIC_DRAW);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(1);
}


GLvoid Timer(int Value)
{
	if (Value == 500)
	{
		Piece r = Piece(cid, 0.005f, -0.001f);
		cid++;
		RectList.push_back(r);
		delay = 0;
	}

	delay++;

	glutPostRedisplay();
	glutTimerFunc(1, Timer, delay);
}

int main(int argc, char** argv)
{
	srand((unsigned int)time(NULL));

	GLint width = 1000;
	GLint height = 1000;

	glutInit(&argc, argv);// glut 초기화
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(width, height);
	glutCreateWindow("Example1");
	glewExperimental = GL_TRUE;

	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	glFrontFace(GL_CCW);
	glewInit();

	InitShader();
	InitBuffer();

	glutTimerFunc(1, Timer, delay);
	glutKeyboardFunc(Keyboard);
	glutMouseFunc(Mouse);
	glutMotionFunc(Motion);
	glutDisplayFunc(drawScene);
	glutMainLoop();
}

To anyone answer your question you need at least to describe how the code works in your meaning. Showing i want to slice polygon and giving hundreds line of code doesn't work.

To slice a polygon you need to define a slicing plane vec3 n and float d. After that you will have to iterate through each polygon edges and produce new vertices. if polygon lies at one side of the cut plane then you leave it. Well in your case you dont leave it but pass it to one o two buffers. (left v right buffer)

To cut an edge, either you use ray/plane intersection algorithm or you use some fancy clipedge function with few dots subtraction and addition…

Anyway you would like to perserve texture coordinates. which goes like this since edge has two vertices v1 and v2 and they have their tex coords then depending on which vertex you actually cut out (say its v2) you have new_txcoord = asblength(vatcutplane-v1) / abslength(v2-v1/*irrevelant order*/) * v2.texcoord

not to mention you have somehow to know the depth texcoordinate so you will see the interior textured

something like that

you could also use gpu csg operations (was a nvidia paper on this?) this at least wont force you to recompute the shape.

heres a sample code of splitting a polygon


TCSGInfo SplitPolyByPlane(t3dpoint<float> n, float d, TPolygon<float> CuttedPoly, int leave_side)
{

	TCSGInfo result;
CuttedPoly.CalcPlane();

		t3dpoint<float> A; t3dpoint<float> B;
		vec2 At, Bt;
bool wascut = false;
		int next;
bool onplane = true;
bool partiallyonplane = false;
for (int i=0; i < CuttedPoly.Count; i++)
if (classifyapointagainstaplane(CuttedPoly.V[i], n,  d) != isOnPlane)
{
	onplane = false;
	partiallyonplane = true;
	break;
}
	
	
if (onplane)
{

//		ALOG("WHOLE POLY ON PLANE");
	for (int i=0; i < CuttedPoly.Count; i++)
	{
	result.ToBeCutPoly.AddVertex(CuttedPoly.V[i], CuttedPoly.t[i]);
//	ALOG("V: "+vec3tostr(CuttedPoly.V[i])+"  v: "+vec3tostr(vec3(CuttedPoly.t[i])));
	}
return result;
}


		for (int i=0; i < CuttedPoly.Count; i++)
		{
			A = CuttedPoly.V[i];
			At = CuttedPoly.t[i];
			if (i != CuttedPoly.Count-1) next = i + 1; else next = 0;
CAN_LOG = (isdesiredpoint(A));
			B = CuttedPoly.V[next];
			Bt = CuttedPoly.t[next];
			
			int Aside = classifyapointagainstaplane(A, n,  d);
			int Bside = classifyapointagainstaplane(B, n,  d);
//ALOG("A: "+vec3tostr(A)+" B: "+vec3tostr(B));
if (Aside == isOnPlane)
{
//	ALOG("ASIDE ON PLANE: v: "+vec3tostr(A)+"  t: "+vec3tostr(vec3(At)));
result.ToBeCutPoly.AddVertex(A,At);
result.LeavePoly.AddVertex(A,At);
result.DepthPoly.AddVertex(A,At);
wascut = true;
continue; //seems to be an optimization to not bother with segment plane intersection cause its the same case but avoid unnecessary calculations...
}


	t3dpoint<float> output;
	bool cut = SegmentPlaneIntersection(n, d, A, B, output);
/*if ((cut) && (absnf(output.z) > 100.0))
{
	ALOG("N: "+vec3tostr(n)+" D: "+CFloatToStr(d));
	cut = SPI(n, d, A, B, output);
}
*/


if ((Aside == leave_side) )
{
	ALOG("leave v: "+vec3tostr(A)+"  t: "+vec3tostr(vec3(At)));

result.LeavePoly.AddVertex(A,At);
}
else
{
		ALOG("tobecut: v: "+vec3tostr(A)+"  t: "+vec3tostr(vec3(At)));

result.ToBeCutPoly.AddVertex(A,At);

}
	if (cut)
	{
		if (isdesiredpoint(output)) CAN_LOG = true;
		wascut = true;
//ALOG("CUT OUTPUT: "+vec3tostr(output));
vec3 vt = vectorAB(vec3(At), vec3(Bt));
vec3 vd = vectorAB(A, B);
vec3 vo = vectorAB(A, output);
vec3 fn = CuttedPoly.normal;
	fn.x = absnf(fn.x);
	fn.y = absnf(fn.y);
	fn.z = absnf(fn.z);

int fdir = X;

	if ( (fn.x >= fn.y) && (fn.x >= fn.z) ) fdir = X;
	if ( (fn.y >= fn.x) && (fn.y >= fn.z) ) fdir = Y;
	if ( (fn.z >= fn.y) && (fn.z >= fn.x) ) fdir = Z;

if (absnf(vd.x) < close_to_zero) vd.x = 0.0;
else vd.x = vo.x / vd.x;
if (absnf(vd.y) < close_to_zero) vd.y = 0.0;
else vd.y = vo.y / vd.y;
if (absnf(vd.z) < close_to_zero) vd.z = 0.0;
else vd.z = vo.z / vd.z;

if (fdir == X) vd = vec3(vd.z, vd.y, 0.0);
if (fdir == Y) vd = vec3(vd.x, vd.z, 0.0);
if (fdir == Z) vd = vec3(vd.x, vd.y, 0.0);

vt = vt & vd;
vec2 nvt = vec2(At.x, At.y) + vec2(vt.x, vt.y);

	ALOG("depth, leave,tobecut v: "+vec3tostr(output)+"  t: "+vec3tostr(vec3(nvt)));

	

	
if (output == A)
if ((Aside == leave_side) )
result.LeavePoly.t[result.LeavePoly.Count-1] = nvt;
else
result.ToBeCutPoly.t[result.ToBeCutPoly.Count-1] = nvt;

result.LeavePoly.AddVertex(output, nvt);
result.DepthPoly.AddVertex(output, nvt);
result.ToBeCutPoly.AddVertex(output, nvt);
		}
	
	}//eof through all sides
	


result.ToBeCutPoly.DiscardDuplicatedVertices();
result.LeavePoly.DiscardDuplicatedVertices();
if (wascut)//now after some time this code looks ridicilous, cause we only cut one face at a time so it should output max 2 verts.....
{
	if (result.ToBeCutPoly.Count >= 1)
	SortPoly(result.ToBeCutPoly);
	if (result.LeavePoly.Count >=1)
	SortPoly(result.LeavePoly);
}

if (result.DepthPoly.Count > 0) result.DepthPoly.ApplySingleTexCoords(640.0);

result.ToBeCutPoly.algined = CuttedPoly.algined;
result.LeavePoly.algined = CuttedPoly.algined;
result.DepthPoly.algined = CuttedPoly.algined;


return result;
}


Advertisement

@sharkbladder yes you kinda need to explain what your code dump's doing, now i'm not terribly encouraged to wade through without some hint about what it's doing -lol-;

anyways, help yourself: https://www.geometrictools.com/Documentation/ClipConvexPolygonByHyperplane.pdf

see page 3;

have fun ?

The main problem with slicing a mesh is the remaining holes. E.g. if you slice an orange, you want to cap the two holes and show the inner fruit texture.

I think one trick games are using is to use the back faces. If back face fragments are visible, project them to the slicing plane and generate texture coords etc. procedurally.

To do it ‘correctly’, i would do it on CPU, using a mesh data structure with adjacency information. Then the cap can be found quickly by traversing an open edge until the loop closes, and generating new triangles while doing so. That's much harder to implement but you can avoid a need to iterate over all triangles.

SharkBladder said:
all i need to do is slice rectangle (it has 4 vertex)

oh… sounds you want a 2d fruit ninja version, maybe?

Then no problem with holes, and the usual poly clipper is enough.

I used this for polygons with 2 UV channels:

int32_t ClipTexmapPolygon (const TexmapPolygon *pin, const vec &plane, TexmapPolygon *pout, const int32_t space)
	{
		int32_t i, curin, nextin;
		float curdot, nextdot, scale;
		TexmapPolygon::Vertex *pinvert, *poutvert, *nextvert;

		pinvert = pin->vertices;
		poutvert = pout->vertices;
		curdot = pinvert->puv[space].Dot (plane);
		curin = (curdot >= plane[3]);
	
		int32_t ret = -1; // assume inside

		for (i=0; i<pin->numVertices; i++)
		{
			nextvert = &pin->vertices[(i+1) % pin->numVertices];
			// keep if inside	
			if (curin) 
			{
				*poutvert++ = *pinvert;
			}
		
			nextdot = nextvert->puv[space].Dot (plane);
			nextin = (nextdot >= plane[3]);
			
			if (curin!=nextin) // add clipped vertex if plane splits edge
			{
				assert (fabs(nextdot - curdot) > FP_EPSILON);
				ret = 1; // clipped or outside
				scale = (plane[3] - curdot) / (nextdot - curdot);

				for (int32_t c=0; c<3; c++)
					poutvert->puv[c] = pinvert->puv[c] + (nextvert->puv[c] - pinvert->puv[c]) * scale; // puv[3]: {position, uv channel 0, uv channel 1}

				poutvert++;
			}

			curdot = nextdot;
			curin = nextin;
			pinvert++;
		}

		pout->numVertices = int32_t(poutvert - pout->vertices);
		if (pout->numVertices < 3) return 0; // outside
	
		return ret;
	}

Pretty much a copy of Michael Abrashs code. I think it works the same no matter if vec is vec3 or vec2.

This topic is closed to new replies.

Advertisement