I am a lot of confused about how i create a complex 3d model in javafx.
More specifically, I want create a spiral or helix which is a group of many cubes.
I have the mathematical type to create my points for the mesh:
for (int i = 0; i < 20; i++) {
v1=Math.sin(pi*i*0.125)*150;
v2=i*50;
v3=Math.cos(pi*i*0.125)*150;
mesh.getPoints().addAll((float)v1,(float) v2,(float) v3);
mesh.getPoints().addAll((float)v1,(float) v2,(float) - v3);
mesh.getPoints().addAll((float)v1,(float) -v2,(float) v3);
mesh.getPoints().addAll((float)v1,(float) -v2,(float)- v3);
mesh.getPoints().addAll((float)-v1,(float) v2,(float) v3);
mesh.getPoints().addAll((float)-v1,(float) v2,(float) -v3);
mesh.getPoints().addAll((float)-v1,(float) -v2,(float) v3);
mesh.getPoints().addAll((float)-v1,(float) -v2,(float) -v3);
}
But when i try to write the faces , output is awful.
How faces must be written?
What you have shown are just the points. What about the faces?
Have a look here: https://github.com/FXyz/FXyz
This may help to get you going.
Related
I am making a simple editor where the user can click on points of an image and crop out a shape. My implementation is terribly inefficient and as I'm new to qt, I have trouble deciphering all the functions on qt's docs.
QPolygonF polygon(points);
std::map<std::string, int> map = pointsHandler.getOutsideVals();
for(int i = map["Left"]; i < map["Right"]; i++){
for(int j = map["Top"]; j < map["Bottom"]; j++){
for(int n = 0; n < points.size(); n++){
if(polygon.containsPoint(QPointF(i,j), Qt::OddEvenFill)){
image.setPixelColor(QPoint(i - xOffset, j - yOffset), Qt::transparent);
}
}
}
}
painter.drawImage(xOffset,yOffset, image);
Currently how I'm doing it is looping through a rectangle given by the outer most points of the polygon. If a point is in the polygon or not I change the pixel value to be transparent. The polygon is made from the users clicked points which I then store the outer most values in a map. When I crop out large portions, it takes far to long and was I looking for some advice to make this more efficient. Thank you.
EDIT
I am now using setClipPath mentioned by G.M. and have no performance issues, however the way I found to get the job done now seems like a waste of memory. Using setClipPath(...) the best work around I found was to make multiple Qt class objects on the stack, it works great just seems like I'm working around to much stuff. Here's the updated code.
QPolygon clipPolygon = QPolygonF(points).toPolygon();
QRegion clippedRegion(clipPolygon, Qt::OddEvenFill);
QRect translatedImageRect = image.rect().translated(QPoint(xOffset, yOffset));
QRegion unClippedRegion = QRegion(translatedImageRect).subtracted(clippedRegion);
painter.save();
painter.setClipRegion(unClippedRegion, Qt::ReplaceClip);
painter.drawImage(xOffset, yOffset, image);
painter.restore();
It works great, just feel like I'm wasting memory.
You can use QPainter to make a rectangle of your image transparent.
QImage image("/home/tim/Bilder/Example.png");
QPainter painter(&image);
painter.setCompositionMode(QPainter::CompositionMode_Source);
painter.fillRect(0, 0, 10, 10, Qt::transparent);
painter.end();
image.save("/home/tim/Bilder/changed.png", "PNG");
I have a QGraphicsView in my Qt application on which user can draw curves. Curves consist of QGraphicsEllipseItem's and QGraphicsPathItem's, which connect the adjacent ellipses.
I want to get a list of QPoint's which satisfy the given curve. I tried creating local QPainterPath for this procedure which would represent the whole curve and iterating over all the points from it's rectangle to see which ones satisfy this curve. The code looks like:
QPainterPath curvePath = edges[index]->at(0)->path();
qreal left, right, bottom, top;
for(int i=1;i<edges[index]->size();i++)
{
curvePath.connectPath(edges[index]->at(i)->path());
}
QRectF curveRect = curvePath.boundingRect();
left = curveRect.left();
right = curveRect.right();
top = curveRect.top();
bottom = curveRect.bottom();
for(qreal i = left;i<right;i++)
for(qreal j = top;j<bottom;j++)
{
QPointF pointToCheck(i, j);
if(curvePath.contains(pointToCheck))
list.append(pointToCheck);
}
where edges is QList of QLists of QGraphicsPathItem's. It works fine in case of calculations (the point of applying this is to increase precision of calculation), but it really slows down my application since those calculations are made quite often.
Is there more efficient way to implement this?
i am trying to create a kind of metaball, nice curves between two circles.
Something like the image, the lines are drawn straight but can also be more curved. I need them as a vector in Processing. Does anyone can help me?
thanks in advance!
Example in paperjs:
http://paperjs.org/examples/meta-balls/
image:
http://www.smeulders.biz/tmp/metaballs.png
void setup() {
size(500,500);
ellipse(100, 250, 100, 100);
ellipse(350, 250, 200, 200);
}
void draw() {}
With a bit of math (to workout distance between circles) and a bit of pixel manipulation to set pixel colours based on these calculated distances, you can render 2D metaballs and there plenty of examples
For fun however I decided to take a stab at making a very hacky version of the example you shared by simply rendering ellipses into an image, then filtering the image at the end:
PGraphics pg;//a separate layer to render into
int dilateAmt = 3;
PImage grid;//pixels of the grid alone, minus the 'cursor'
void setup(){
size(400,400);
//create a new layer
pg = createGraphics(width,height);
pg.beginDraw();
//draw a di-grid inside
pg.background(255);
pg.noStroke();pg.fill(0);
for(int y = 0 ; y < 5; y++)
for(int x = 0 ; x < 5; x++)
pg.ellipse((y%2==0?40:0)+(x * 80),40+(y * 80), 40, 40);
pg.endDraw();
//grab a snapshot for later re-use
grid = pg.get();
}
void draw(){
pg.beginDraw();
//draw the cached grid (no need to loop and re-render circles)
pg.image(grid,0,0);
//and the cursor into the layer
pg.ellipse(mouseX,mouseY,60,60);
pg.endDraw();
//since PGraphics extends PImage, you can filter, so we dilate
for(int i = 0; i < dilateAmt; i++) pg.filter(DILATE);
//finally render the result
image(pg,0,0);
}
void keyPressed(){
if(keyCode == UP) dilateAmt++;
if(keyCode == DOWN) dilateAmt--;
if(dilateAmt < 1) dilateAmt = 1;
println(dilateAmt);
}
Note that the end result is raster, not vector.
If you want to achieve the exact effect you will need to port your example from JavaScript to Java. The source code is available.
If you like Processing the above example you could use plain javascript using p5.js. You'll find most of the familiar functions from Processing, but also directly use the paper.js library.
I'm developing a simulator gui in which the user clicks on different points of the map and the program connects these points to each other however the connection should be somehow curved (but preferably the curve should pass from the given points) I can't find a decent way to implement this.
A similar solution which I could not figure out
I have seen similar problems and often they are solved using QPainterPath or implementing a bezier curve. Or should I just compute the control points of the bezier curve (if so, how?) ?
Any help would be appreciated,
Thank you in advance
A cubic Bézier curve consists of 4 points: Start, End, Control1 and Control2. Depending on the two control points the curve can have different shapes. Since you don't have the control points you should calculate them in some way.
This gives a nice description of how to calculate the control points if you only know the start point, end point and one other point on the curve. In your case the point on the curve could be the mid point between start and end.
void Beziertest::Bezier2D(QList<QPoint> points)
{
QImage area(600,700,QImage::Format_RGB32);
int n=points.length()-1;
for(double u = 0.0 ; u <= 1.0 ; u += 0.001)
{
//calculate x coordinate
double xu=0.0;
for (int i = n; i >= 0; i--) {
xu+=points[i].x()*((factorial(n)/(factorial(i)*factorial((n-i))))*pow(u,i)*pow((1-u),(n-i)));
}
//calculate y coordinate
double yu=0.0;
for (int i = n; i >= 0; i--) {
yu+=points[i].y()*((factorial(n)/(factorial(i)*factorial((n-i))))*pow(u,i)*pow((1-u),(n-i)));
}
area.setPixel((int)xu , (int)yu , deger);
setPixmap(QPixmap::fromImage(res));//set image to label
}
}
I render isosurfaces with marching cubes, (or perhaps marching squares as this is 2D) and I want to do set operations like set difference, intersection and union. I thought this was easy to implement, by simply choosing between two vertex scalars from two different implicit surfaces, but it is not.
For my initial testing, I tried with two spheres circles, and the set operation difference. i.e A - B. One circle is moving and the other one is stationary. Here's the approach I tried when picking vertex scalars and when classifying corner vertices as inside or outside. The code is written in C++. OpenGL is used for rendering, but that's not important. Normal rendering without any CSG operations does give the expected result.
void march(const vec2& cmin, //min x and y for the grid cell
const vec2& cmax, //max x and y for the grid cell
std::vector<vec2>& tri,
float iso,
float (*cmp1)(const vec2&), //distance from stationary circle
float (*cmp2)(const vec2&) //distance from moving circle
)
{
unsigned int squareindex = 0;
float scalar[4];
vec2 verts[8];
/* initial setup of the grid cell */
verts[0] = vec2(cmax.x, cmax.y);
verts[2] = vec2(cmin.x, cmax.y);
verts[4] = vec2(cmin.x, cmin.y);
verts[6] = vec2(cmax.x, cmin.y);
float s1,s2;
/**********************************
********For-loop of interest******
*******Set difference between ****
*******two implicit surfaces******
**********************************/
for(int i=0,j=0; i<4; ++i, j+=2){
s1 = cmp1(verts[j]);
s2 = cmp2(verts[j]);
if((s1 < iso)){ //if inside circle1
if((s2 < iso)){ //if inside circle2
scalar[i] = s2; //then set the scalar to the moving circle
} else {
scalar[i] = s1; //only inside circle1
squareindex |= (1<<i); //mark as inside
}
}
else {
scalar[i] = s1; //inside neither circle
}
}
if(squareindex == 0)
return;
/* Usual interpolation between edge points to compute
the new intersection points */
verts[1] = mix(iso, verts[0], verts[2], scalar[0], scalar[1]);
verts[3] = mix(iso, verts[2], verts[4], scalar[1], scalar[2]);
verts[5] = mix(iso, verts[4], verts[6], scalar[2], scalar[3]);
verts[7] = mix(iso, verts[6], verts[0], scalar[3], scalar[0]);
for(int i=0; i<10; ++i){ //10 = maxmimum 3 triangles, + one end token
int index = triTable[squareindex][i]; //look up our indices for triangulation
if(index == -1)
break;
tri.push_back(verts[index]);
}
}
This gives me weird jaggies:
(source: mechcore.net)
It looks like the CSG operation is done without interpolation. It just "discards" the whole triangle. Do I need to interpolate in some other way, or combine the vertex scalar values? I'd love some help with this.
A full testcase can be downloaded HERE
EDIT: Basically, my implementation of marching squares works fine. It is my scalar field which is broken, and I wonder what the correct way would look like. Preferably I'm looking for a general approach to implement the three set operations I discussed above, for the usual primitives (circle, rectangle/square, plane)
EDIT 2: Here are some new images after implementing the answerer's whitepaper:
1.Difference
2.Intersection
3.Union
EDIT 3: I implemented this in 3D too, with proper shading/lighting:
1.Difference between a greater sphere and a smaller sphere
2.Difference between a greater sphere and a smaller sphere in the center, clipped by two planes on both sides, and then union with a sphere in the center.
3.Union between two cylinders.
This is not how you mix the scalar fields. Your scalars say one thing, but your flags whether you are inside or not say another. First merge the fields, then render as if you were doing a single compound object:
for(int i=0,j=0; i<4; ++i, j+=2){
s1 = cmp1(verts[j]);
s2 = cmp2(verts[j]);
s = max(s1, iso-s2); // This is the secret sauce
if(s < iso) { // inside circle1, but not inside circle2
squareindex |= (1<<i);
}
scalar[i] = s;
}
This article might be helpful: Combining CSG modeling with soft blending using
Lipschitz-based implicit surfaces.