Grouping points after cut plane three js with new library - three.js

Regarding the discussion in this link, where the object is a THREE.Geometry(), anyone has any idea to implement this code:
function getContours(points, contours, firstRun) {
//console.log("firstRun:", firstRun);
let contour = [];
// find first line for the contour
let firstPointIndex = 0;
let secondPointIndex = 0;
let firstPoint, secondPoint;
for (let i = 0; i < points.length; i++) {
if (points[i].checked == true) continue;
firstPointIndex = i;
firstPoint = points[firstPointIndex];
firstPoint.checked = true;
secondPointIndex = getPairIndex(firstPoint, firstPointIndex, points);
secondPoint = points[secondPointIndex];
secondPoint.checked = true;
contour.push(firstPoint.clone());
contour.push(secondPoint.clone());
break;
}
contour = getContour(secondPoint, points, contour);
contours.push(contour);
let allChecked = 0;
points.forEach(p => { allChecked += p.checked == true ? 1 : 0; });
console.log("allChecked: ", allChecked == points.length);
if (allChecked != points.length) { return getContours(points, contours, false); }
return contours;
}
function getContour(currentPoint, points, contour){
let p1Index = getNearestPointIndex(currentPoint, points);
let p1 = points[p1Index];
p1.checked = true;
let p2Index = getPairIndex(p1, p1Index, points);
let p2 = points[p2Index];
p2.checked = true;
let isClosed = p2.equals(contour[0], tolerance);
if (!isClosed) {
contour.push(p2.clone());
return getContour(p2, points, contour);
} else {
contour.push(contour[0].clone());
return contour;
}
}
function getNearestPointIndex(point, points){
let index = 0;
for (let i = 0; i < points.length; i++){
let p = points[i];
if (p.checked == false && p.equals(point, tolerance)){
index = i;
break;
}
}
return index;
}
function getPairIndex(point, pointIndex, points) {
let index = 0;
for (let i = 0; i < points.length; i++) {
let p = points[i];
if (i != pointIndex && p.checked == false && p.faceIndex == point.faceIndex) {
index = i;
break;
}
}
return index;
}
With new three library the object is a THREE.BufferGeometry() that has no face(s) and no checked.
I need to connect the points between themselves (separate arrays) where the plane passes.

Related

Updating sand simulation in grid doesn't work

I want to make a falling sand simulation using cellular automata, but when I update it, nothing happens, and when I want to do a line of diffrent material using lineDrawing() this material appear in random cells. This is update code:
void update()
{
for (int i = verticalNumberOfCells - 1; i > 0; i--)
{
for (int j = 0; j < horizontalNumberOfCells; j++)
{
world[j][i].update(false);
}
}
for (int y = verticalNumberOfCells - 1; y > 0; y--)
{
for (int x = 0; x < horizontalNumberOfCells; x++)
{
if (world[x][y].hasMoved) continue;
if (world[x][y].state == 0 && world[x][y].state == 1) continue;
if (canMove(world[x][y].state, x, y + 1))
{
move(x, y, x, y + 1);
}
}
}
}
The auxiliary functions that I use to check if the contents of a cell can change and to change the contents of a cell look like this:
boolean canMove(int state, int positionX, int positionY)
{
if (positionX < 0 || positionX >= horizontalNumberOfCells || positionY < 0 || positionY >= verticalNumberOfCells) return false;
int otherSubstance = world[positionX][positionY].state;
if (state == 5) return (otherSubstance == 4);
if (otherSubstance == 0) return true;
if (state == 2 && otherSubstance == 3 && random(1f) < 0.5f) return true;
return false;
}
void move(int fromX, int fromY, int toX, int toY)
{
Cells otherSubstance = world[toX][toY];
world[toX][toY] = world[fromX][fromY];
world[fromX][fromY] = otherSubstance;
world[fromX][fromY].hasMoved = true;
world[toX][toY].hasMoved = true;
world[fromX][fromY].velocityX = 0;
world[fromX][fromY].velocityY = 0;
if (toX > fromX)
{
world[toX][toY].velocityX = 1;
} else if (toX < fromX)
{
world[toX][toY].velocityX = -1;
} else
{
world[toX][toY].velocityX = 0;
}
if (toY > fromY)
{
world[toX][toY].velocityY = 1;
} else if (toY < fromY)
{
world[toX][toY].velocityY = -1;
} else
{
world[toX][toY].velocityY = 0;
}
}
I was able to fix this problem. The thing was, copying a cell in the move function didn't work. Here is the wrong version of the code:
Cells otherSubstance = world[toX][toY];
world[toX][toY] = world[fromX][fromY];
world[fromX][fromY] = otherSubstance;
and here is right version of the code:
int oldState = world[toX][toY].state;
world[toX][toY].state = world[fromX][fromY].state;
world[fromX][fromY].state = oldState;

Remove particle from box2d.world.getParticlePositionBuffer()

How to remove a particle from box2d.world when it get out of screen?
Currently, I have this code from Nature of Code - LiquidFunTest example:
Vec2[] positionBuffer = box2d.world.getParticlePositionBuffer();
if (positionBuffer != null) {
for (int i = 0; i < positionBuffer.length; i++) {
Vec2 pos = box2d.coordWorldToPixels(positionBuffer[i]);
pg.stroke(255);
pg.strokeWeight(3);
pg.point(pos.x, pos.y);
}
}
I've changed the code to:
Vec2[] positionBuffer = box2d.world.getParticlePositionBuffer();
if (positionBuffer != null) {
for (int i = 0; i < positionBuffer.length; i++) {
Vec2 pos = box2d.coordWorldToPixels(positionBuffer[i]);
if(pos.y > height){
box2d.world.destroyParticle(i);
} else {
pg.stroke(255);
pg.strokeWeight(3);
pg.point(pos.x, pos.y);
}
}
}
But destroyParticle() method doesn't have the same index as getParticlePositionBuffer()

Is the cuda kernel limited by memory usage per thread/block

I have a kernel code that executes properly
runnable code
__global__ static void CalcSTLDistance_Kernel(Integer ComputeParticleNumber)
{
//const Integer TID = CudaGetTargetID();
const Integer ID =CudaGetTargetID();
/*if(ID >= ComputeParticleNumber)
{
return ;
}*/
CDistance NearestDistance;
Integer NearestID = -1;
NearestDistance.Magnitude = 1e8;
NearestDistance.Direction.x = 0;
NearestDistance.Direction.y = 0;
NearestDistance.Direction.z = 0;//make_Scalar3(0,0,0);
//if(c_daOutputParticleID[ID] < -1)
//{
// c_daSTLDistance[ID] = NearestDistance;
// c_daSTLID[ID] = NearestID;
// return;
//}
//Scalar3 TargetPosition = c_daParticlePosition[ID];
Integer TriangleID;
Integer CIDX, CIDY, CIDZ;
Integer CID = GetCellID(&CONSTANT_BOUNDINGBOX,&c_daParticlePosition[ID],CIDX, CIDY, CIDZ);
if(CID >=0 && CID < c_CellNum)
{
//Integer Range = 1;
for(Integer k = -1; k <= 1; ++k)
{
for(Integer j = -1; j <= 1; ++j)
{
for(Integer i = -1; i <= 1; ++i)
{
Integer MCID = GetCellID(&CONSTANT_BOUNDINGBOX,CIDX +i, CIDY + j,CIDZ + k);
if(MCID < 0 || MCID >= c_CellNum)
{
continue;
}
unsigned int TriangleNum = c_daCell[MCID].m_TriangleNum;
for(unsigned int l = 0; l < TriangleNum; ++l)
{
TriangleID = c_daCell[MCID].m_TriangleID[l];
/*if(c_daTrianglesParameters[c_daTriangles[TriangleID].ModelIDNumber].isDrag)
{
continue;
}*/
if( TriangleID >= 0 && TriangleID < c_TriangleNum && TriangleID != NearestID)// No need to calculate again for the same triangle
{
CDistance Distance ;
Distance.Magnitude = CalcDistance(&c_daTriangles[TriangleID], &c_daParticlePosition[ID], &Distance.Direction);
if(Distance.Magnitude < NearestDistance.Magnitude)
{
NearestDistance = Distance;
NearestID = TriangleID;
}
}
}
}
}
}
}
c_daSTLDistance[ID] = NearestDistance;
c_daSTLID[ID] = NearestID;
}
and when I add any basic variables or perform any checking operation, it gives unknown error and while checking wih cuda-memcheck, it suggests memory read error.
here in the changed code, i tried to check the previously calculated part and tried to skip the redundant calculation. for this I tried to perform basic check operation in array but it throws memory error.
error raising code
__global__ static void CalcSTLDistance_Kernel(Integer ComputeParticleNumber)
{
//const Integer TID = CudaGetTargetID();
const Integer ID =CudaGetTargetID();
/*if(ID >= ComputeParticleNumber)
{
return ;
}*/
CDistance NearestDistance;
Integer NearestID = -1;
NearestDistance.Magnitude = 1e8;
NearestDistance.Direction.x = 0;
NearestDistance.Direction.y = 0;
NearestDistance.Direction.z = 0;//make_Scalar3(0,0,0);
//if(c_daOutputParticleID[ID] < -1)
//{
// c_daSTLDistance[ID] = NearestDistance;
// c_daSTLID[ID] = NearestID;
// return;
//}
//Scalar3 TargetPosition = c_daParticlePosition[ID];
Integer TriangleID;
Integer CIDX, CIDY, CIDZ;
Integer CID = GetCellID(&CONSTANT_BOUNDINGBOX,&c_daParticlePosition[ID],CIDX, CIDY, CIDZ);
int len=0;
int td[100];
for(int m=0;m<100;m++)
{
td[m]=-1;
}
if(CID >=0 && CID < c_CellNum)
{
//Integer Range = 1;
for(Integer k = -1; k <= 1; ++k)
{
for(Integer j = -1; j <= 1; ++j)
{
for(Integer i = -1; i <= 1; ++i)
{
Integer MCID = GetCellID(&CONSTANT_BOUNDINGBOX,CIDX +i, CIDY + j,CIDZ + k);
if(MCID < 0 || MCID >= c_CellNum)
{
continue;
}
unsigned int TriangleNum = c_daCell[MCID].m_TriangleNum;
bool flag = false;
//len=len+TriangleNum ;
for(unsigned int l = 0; l < TriangleNum; ++l)
{
TriangleID = c_daCell[MCID].m_TriangleID[l];
//tem[l] = c_daCell[MCID].m_TriangleID[l];
for(int m=0;m<100;m++)
{
if(TriangleID ==td[m])
{
flag= true;
}
if(flag == true)
break;
}
if(flag == true)
continue;
else
{
td[len] = TriangleID;
len= len+1;
if( TriangleID >= 0 && TriangleID < c_TriangleNum && TriangleID != NearestID)// No need to calculate again for the same triangle
{
CDistance Distance ;
Distance.Magnitude = CalcDistance(&c_daTriangles[TriangleID], &c_daParticlePosition[ID], &Distance.Direction);
if(Distance.Magnitude < NearestDistance.Magnitude)
{
NearestDistance = Distance;
NearestID = TriangleID;
}
}
}
}
}
}
}
}
c_daSTLDistance[ID] = NearestDistance;
c_daSTLID[ID] = NearestID;
}
this problem arises whenever I tried to add any piece of code,thus I suspects that this block of kernel is not allowing me to add any further code due to memory over use.
is there any memory violation rule per block or thread??
how to find the total memory usuage per kernel ?? is there any way??

simulating centipede finite state machine

I'm trying to write a centipede game clone, and I have written a node class which is basically a circle.
I'm trying to write an FSM to simulate node movements and bouncing with bricks or the screen, but the problem, that the FSM conflicts with other conditions. How would I resolve it ? For example one of the nodes can be at x <0 but they have y > 800.
public function gameLoop(event:Event):void
{
for (var i:int = 0; i < m_nodes.length; i++)
{
if (m_nodes[i].x > 750)
{
m_nodes[i].current_dir = Node.Direction_RIGHT;
}
else if (m_nodes[i].x < 10)
{
m_nodes[i].current_dir = Node.Direction_UP;
}
if ( m_nodes[i].y < 0 )
{
m_nodes[i].current_dir = Node.Direction_RIGHT;
}
else if ( m_nodes[i].y > 590 )
{
m_nodes[i].current_dir =Node.Direction_LEFT;
}
if (m_nodes[i].hitTestObject(m_bricks[i]))
{
//m_nodes[i].current_dir = Node.Direction_RIGHT;
}
if (m_nodes[i].current_dir == Node.Direction_LEFT)
{
m_nodes[i].vx = -5;
m_nodes[i].vy = 0;
}
if (m_nodes[i].current_dir == Node.Direction_RIGHT)
{
m_nodes[i].vx = 0;
m_nodes[i].vy = 5;
}
if (m_nodes[i].current_dir == Node.Direction_UP)
{
m_nodes[i].vx = 0;
m_nodes[i].vy = -5;
}
m_nodes[i].x += m_nodes[i].vx;
m_nodes[i].y += m_nodes[i].vy;
}
}
Update: new updated code, with fixing the logic, but collision detects fails, the state machines have conflict states.
for (var i:int = 0; i < m_nodes.length; i++)
{
if (m_nodes[i].x > 750)
{
m_nodes[i].current_dir = Node.Direction_DOWN;
}
else if (m_nodes[i].x < 40 && m_nodes[i].y < 600)
{
if (!m_nodes[i].current_dir == Node.Direction_RIGHT)
{
m_nodes[i].current_dir = Node.Direction_UP;
trace("dir up");
}
}
if (m_nodes[i].hitTestObject(m_bricks[i]) )
{
trace("hit");
m_nodes[i].vx = 0;
m_nodes[i].vy = 5;
}
if (m_nodes[i].y < 40 && m_nodes[i].x < 40)
{
m_nodes[i].current_dir = Node.Direction_RIGHT;
}
else if (m_nodes[i].y > 560 && m_nodes[i].x > 40)
{
m_nodes[i].current_dir = Node.Direction_LEFT;
}
if (m_nodes[i].current_dir == Node.Direction_LEFT)
{
m_nodes[i].vx = -5;
m_nodes[i].vy = 0;
}
else if (m_nodes[i].current_dir == Node.Direction_DOWN)
{
m_nodes[i].vx = 0;
m_nodes[i].vy = 5;
}
else if (m_nodes[i].current_dir == Node.Direction_RIGHT)
{
m_nodes[i].vx = 5;
m_nodes[i].vy = 0;
}
if (m_nodes[i].current_dir == Node.Direction_UP)
{
m_nodes[i].vx = 0;
m_nodes[i].vy = -5;
}
m_nodes[i].x += m_nodes[i].vx;
m_nodes[i].y += m_nodes[i].vy;
}

Given a position in matrix [i, j], find the block it belongs to

Well, I am dealing with sudoku solving algorithm and generation but stuck at rather simple task. I have made the check, whether a number is really fit in the position row-wise and column-wise. But what it is driving me mad is block check, ie, whether the number is really fit in the 3x3 block.
It must be simple enough but I can't really arrive at the solution. In short, I want to know the 3x3 block to which a position in matrix belongs. Here are some of the assert cases. The block no, row no and col no indexing starts from 0.
assert("x( 0, 8 ) === 2");
assert("x( 8, 8 ) === 8");
assert("x( 3, 3 ) === 4");
assert("x( 3, 7 ) === 5");
assert("x( 7, 1 ) === 6");
x( i , j ) returns the block number where i = row and j = col.
Isn't it just:
block = 3 * (i / 3) + (j / 3)
(assumes integer operations).
I would code a check, something like this (in pseudo C++)
// row = row to check
// col = column to check
// checkNum = number we are thinking of inserting
bool check(int row, int col, int checkNum)
{
int blockRow = 3 * (row/3);
int blockCol = 3 * (col/3);
for(int i = 0 ; i < 9 ; i++)
{
if(grid[row][i] == checkNum) return false; // number exists in the row.
if(grid[i][col] == checkNum) return false; // number exists in the col.
if(grid[blockRow + i/3][blockCol + i%3] == checkNum) return false; // number exists in the block.
}
return true;
}
Here is a sudoku solver in javascript. Taken from DSSudokuSolver, that I created.
The CleanElements function does something similar to what you are asking for.
CleanElements = function(comp_ary, Qsudoku){
for(i=0; i<9; i++){
for(j=0; j<9; j++){
/*if(Qsudoku[i][j] != ""){
comp_ary[i][j]=[];
}*/
for(k=0; k<9; k++){
i_index = comp_ary[i][k].indexOf(Qsudoku[i][j]);
if(i_index != -1){
comp_ary[i][k].splice(i_index, 1);
}
j_index = comp_ary[k][j].indexOf(Qsudoku[i][j]);
if(j_index != -1){
comp_ary[k][j].splice(j_index, 1);
}
}
if(i < 3){
i_min = 0;
i_max = 2;
}
else if(i < 6){
i_min = 3;
i_max = 5;
}
else{
i_min = 6;
i_max = 8;
}
if(j < 3){
j_min = 0;
j_max = 2;
}
else if(j < 6){
j_min = 3;
j_max = 5;
}
else{
j_min = 6;
j_max = 8;
}
for(i_box=i_min; i_box<=i_max; i_box++){
for(j_box=j_min; j_box<=j_max; j_box++){
index = comp_ary[i_box][j_box].indexOf(Qsudoku[i][j]);
if(index != -1){
comp_ary[i_box][j_box].splice(index, 1);
}
}
}
}
}
return comp_ary;
}
FindElements = function(comp_ary, Qsudoku){
for(i=0; i<9; i++){
for(j=0; j<9; j++){
if(comp_ary[i][j].length == 1){
if (Qsudoku[i][j] == ""){
Qsudoku[i][j] = comp_ary[i][j][0];
comp_ary[i][j] = [];
}
}
}
}
return Qsudoku;
}
IsThereNullElement = function(Qsudoku){
for(i=0; i<9; i++){
for(j=0; j<9; j++){
if(Qsudoku[i][j] == ""){
return false;
}
}
}
return true;
}
InitEmptyArray = function(){
empty_ary = Array();
for(i=0; i<9; i++){
empty_ary[i] = Array();
for(j=0; j<9; j++){
empty_ary[i][j] = Array();
for(k=0; k<9; k++){
empty_ary[i][j][k] = (k+1).toString();
}
}
}
return empty_ary;
}
DSSolve = function(Qsudoku){
comp_ary = InitEmptyArray(); //Complementary Array
window.comp_ary_old = comp_ary;
IterationMax = 5000;
while(true){
IterationMax -= 1;
comp_ary = CleanElements(comp_ary, Qsudoku);
console.log(comp_ary);
if(window.comp_ary_old == comp_ary){
//implement this.
}
else{
window.comp_ary_old = comp_ary;
}
Qsudoku = FindElements(comp_ary, Qsudoku);
//console.log(Qsudoku);
if(IsThereNullElement(Qsudoku)){
return Qsudoku;
}
if(IterationMax == 0){
return null;
}
}
}

Resources