Algorithm to create a "scruffy" paper effect for UML Diagrams? - uml

I like the scruffy paper effect of http://yuml.me UML diagrams, is there an algorithm for that preferably not in Ruby but in PHP, java or C#, I would like to see if It's easy to do the same thing in Rebol:
http://reboltutorial.com/blog/easy-yuml-dialect-for-mere-mortals2/

The effect combines
a diagonal gradient fill
a drop shadow
lines which, rather than being straight, have some small apparently random deviations in them, which gives a 'scruffy' feel.
You can seed your random number generator with a hash of the input so you get the same image each time.
This seems to work OK for scruffing up lines:
public class ScruffyLines {
static final double WOBBLE_SIZE = 0.5;
static final double WOBBLE_INTERVAL = 16.0;
Random random;
ScruffyLines ( long seed ) {
random = new Random(seed);
}
public Point2D.Double[] scruffUpPolygon ( Point2D.Double[] polygon ) {
ArrayList<Point2D.Double> points = new ArrayList<Point2D.Double>();
Point2D.Double prev = polygon[0];
points.add ( prev ); // no wobble on first point
for ( int index = 1; index < polygon.length; ++index ) {
final Point2D.Double point = polygon[index];
final double dist = prev.distance ( point );
// interpolate between prev and current point if they are more
// than a certain distance apart, adding in extra points to make
// longer lines wobbly
if ( dist > WOBBLE_INTERVAL ) {
int stepCount = ( int ) Math.floor ( dist / WOBBLE_INTERVAL );
double step = dist / stepCount;
double x = prev.x;
double y = prev.y;
double dx = ( point.x - prev.x ) / stepCount;
double dy = ( point.y - prev.y ) / stepCount;
for ( int count = 1; count < stepCount; ++count ) {
x += dx;
y += dy;
points.add ( perturb ( x, y ) );
}
}
points.add ( perturb ( point.x, point.y ) );
prev = point;
}
return points.toArray ( new Point2D.Double[ points.size() ] );
}
Point2D.Double perturb ( double x, double y ) {
return new Point2D.Double (
x + random.nextGaussian() * WOBBLE_SIZE,
y + random.nextGaussian() * WOBBLE_SIZE );
}
}
example scruffed up rectangle http://img34.imageshack.us/img34/4743/screenshotgh.png

Related

Optimize quadratic curve tracing using numeric methods

I am trying to trace quadratic bezier curves, placing "markers" at a given step length distance. Tried to do it a naive way:
const p = toPoint(map, points[section + 1]);
const p2 = toPoint(map, points[section]);
const {x: cx, y: cy} = toPoint(map, cp);
const ll1 = toLatLng(map, p),
ll2 = toLatLng(map, p2),
llc = toLatLng(map, { x: cx, y: cy });
const lineLength = quadraticBezierLength(
ll1.lat,
ll1.lng,
llc.lat,
llc.lng,
ll2.lat,
ll2.lng
);
for (let index = 0; index < Math.floor(lineLength / distance); index++) {
const t = distance / lineLength;
const markerPoint = getQuadraticPoint(
t * index,
p.x,
p.y,
cx,
cy,
p2.x,
p2.y
);
const markerLatLng = toLatLng(map, markerPoint);
markers.push(markerLatLng);
}
This approach does not work since the correlation of a quadratic curve between t and L is not linear. I could not find a formula, that would give me a good approximation, so looking at solving this problem using numeric methods [Newton]. One simple option that I am considering is to split the curve into x [for instance 10] times more pieces than needed. After that, using the same quadraticBezierLength() function calculate the distance to each of those points. After this, chose the point so that the length is closest to the distance * index.
This however would be a huge overkill in terms of algorithm complexity. I could probably start comparing points for index + 1 from the subset after/without the point I selected already, thus skipping the beginning of the set. This would lower the complexity some, yet still very inefficient.
Any ideas and/or suggestions?
Ideally, I want a function that would take d - distance along the curve, p0, cp, p1 - three points defining a quadratic bezier curve and return an array of coordinates, implemented with the least complexity possible.
OK I found analytic formula for 2D quadratic bezier curve in here:
Calculate the length of a segment of a quadratic bezier
So the idea is simply binary search the parameter t until analytically obtained arclength matches wanted length...
C++ code:
//---------------------------------------------------------------------------
float x0,x1,x2,y0,y1,y2; // control points
float ax[3],ay[3]; // coefficients
//---------------------------------------------------------------------------
void get_xy(float &x,float &y,float t) // get point on curve from parameter t=<0,1>
{
float tt=t*t;
x=ax[0]+(ax[1]*t)+(ax[2]*tt);
y=ay[0]+(ay[1]*t)+(ay[2]*tt);
}
//---------------------------------------------------------------------------
float get_l_naive(float t) // get arclength from parameter t=<0,1>
{
// naive iteration
float x0,x1,y0,y1,dx,dy,l=0.0,dt=0.001;
get_xy(x1,y1,t);
for (int e=1;e;)
{
t-=dt; if (t<0.0){ e=0; t=0.0; }
x0=x1; y0=y1; get_xy(x1,y1,t);
dx=x1-x0; dy=y1-y0;
l+=sqrt((dx*dx)+(dy*dy));
}
return l;
}
//---------------------------------------------------------------------------
float get_l(float t) // get arclength from parameter t=<0,1>
{
// analytic fomula from: https://stackoverflow.com/a/11857788/2521214
float ax,ay,bx,by,A,B,C,b,c,u,k,cu,cb;
ax=x0-x1-x1+x2;
ay=y0-y1-y1+y2;
bx=x1+x1-x0-x0;
by=y1+y1-y0-y0;
A=4.0*((ax*ax)+(ay*ay));
B=4.0*((ax*bx)+(ay*by));
C= (bx*bx)+(by*by);
b=B/(2.0*A);
c=C/A;
u=t+b;
k=c-(b*b);
cu=sqrt((u*u)+k);
cb=sqrt((b*b)+k);
return 0.5*sqrt(A)*((u*cu)-(b*cb)+(k*log(fabs((u+cu))/(b+cb))));
}
//---------------------------------------------------------------------------
float get_t(float l0) // get parameter t=<0,1> from arclength
{
float t0,t,dt,l;
for (t=0.0,dt=0.5;dt>1e-10;dt*=0.5)
{
t0=t; t+=dt;
l=get_l(t);
if (l>l0) t=t0;
}
return t;
}
//---------------------------------------------------------------------------
void set_coef() // compute coefficients from control points
{
ax[0]= ( x0);
ax[1]= +(2.0*x1)-(2.0*x0);
ax[2]=( x2)-(2.0*x1)+( x0);
ay[0]= ( y0);
ay[1]= +(2.0*y1)-(2.0*y0);
ay[2]=( y2)-(2.0*y1)+( y0);
}
//---------------------------------------------------------------------------
Usage:
set control points x0,y0,...
then you can use t=get_t(wanted_arclength) freely
In case you want to use get_t_naive and or get_xy you have to call set_coef first
In case you want to tweak speed/accuracy you can play with the target accuracy of binsearch currently set to1e-10
Here optimized (merged get_l,get_t functions) version:
//---------------------------------------------------------------------------
float get_t(float l0) // get parameter t=<0,1> from arclength
{
float t0,t,dt,l;
float ax,ay,bx,by,A,B,C,b,c,u,k,cu,cb,cA;
// precompute get_l(t) constants
ax=x0-x1-x1+x2;
ay=y0-y1-y1+y2;
bx=x1+x1-x0-x0;
by=y1+y1-y0-y0;
A=4.0*((ax*ax)+(ay*ay));
B=4.0*((ax*bx)+(ay*by));
C= (bx*bx)+(by*by);
b=B/(2.0*A);
c=C/A;
k=c-(b*b);
cb=sqrt((b*b)+k);
cA=0.5*sqrt(A);
// bin search t so get_l == l0
for (t=0.0,dt=0.5;dt>1e-10;dt*=0.5)
{
t0=t; t+=dt;
// l=get_l(t);
u=t+b; cu=sqrt((u*u)+k);
l=cA*((u*cu)-(b*cb)+(k*log(fabs((u+cu))/(b+cb))));
if (l>l0) t=t0;
}
return t;
}
//---------------------------------------------------------------------------
For now, I came up with the below:
for (let index = 0; index < Math.floor(numFloat * times); index++) {
const t = distance / lineLength / times;
const l1 = toLatLng(map, p), lcp = toLatLng(map, new L.Point(cx, cy));
const lutPoint = getQuadraticPoint(
t * index,
p.x,
p.y,
cx,
cy,
p2.x,
p2.y
);
const lutLatLng = toLatLng(map, lutPoint);
const length = quadraticBezierLength(l1.lat, l1.lng, lcp.lat, lcp.lng, lutLatLng.lat, lutLatLng.lng);
lut.push({t: t * index, length});
}
const lut1 = lut.filter(({length}) => !isNaN(length));
console.log('lookup table:', lut1);
for (let index = 0; index < Math.floor(numFloat); index++) {
const t = distance / lineLength;
// find t closest to distance * index
const markerT = lut1.reduce((a, b) => {
return a.t && Math.abs(b.length - distance * index) < Math.abs(a.length - distance * index) ? b.t : a.t || 0;
});
const markerPoint = getQuadraticPoint(
markerT,
p.x,
p.y,
cx,
cy,
p2.x,
p2.y
);
const markerLatLng = toLatLng(map, markerPoint);
}
I think only that my Bezier curve length is not working as I expected.
function quadraticBezierLength(x1, y1, x2, y2, x3, y3) {
let a, b, c, d, e, u, a1, e1, c1, d1, u1, v1x, v1y;
v1x = x2 * 2;
v1y = y2 * 2;
d = x1 - v1x + x3;
d1 = y1 - v1y + y3;
e = v1x - 2 * x1;
e1 = v1y - 2 * y1;
c1 = a = 4 * (d * d + d1 * d1);
c1 += b = 4 * (d * e + d1 * e1);
c1 += c = e * e + e1 * e1;
c1 = 2 * Math.sqrt(c1);
a1 = 2 * a * (u = Math.sqrt(a));
u1 = b / u;
a = 4 * c * a - b * b;
c = 2 * Math.sqrt(c);
return (
(a1 * c1 + u * b * (c1 - c) + a * Math.log((2 * u + u1 + c1) / (u1 + c))) /
(4 * a1)
);
}
I believe that the full curve length is correct, but the partial length that is being calculated for the lookup table is wrong.
If I am right, you want points at equally spaced points in terms of curvilinear abscissa (rather than in terms of constant Euclidean distance, which would be a very different problem).
Computing the curvilinear abscissa s as a function of the curve parameter t is indeed an option, but that leads you to the resolution of the equation s(t) = Sk/n for integer k, where S is the total length (or s(t) = kd if a step is imposed). This is not convenient because s(t) is not available as a simple function and is transcendental.
A better method is to solve the differential equation
dt/ds = 1/(ds/dt) = 1/√(dx/dt)²+(dy/dt)²
using your preferred ODE solver (RK4). This lets you impose your fixed step on s and is computationally efficient.

How to make shadow softer?

my result , but the shadow is so hard.
for (SceneLight* light : scene->lights)
{
Vector3D dir_to_light;
float dist_to_light;
float pdf;
int num_light_samples = light->is_delta_light() ? 1 : ns_area_light;
double scale = 1.0 / num_light_samples;
for (int i = 0; i < num_light_samples; i++) {
Spectrum light_L = light->sample_L(hit_p, &dir_to_light, &dist_to_light, &pdf);
Vector3D w_in = w2o * dir_to_light;
double cos_theta = std::max(0.0, w_in[2]);
Spectrum f = isect.bsdf->f(w_out, w_in);
Ray shadow_ray(hit_p + EPS_D * dir_to_light, dir_to_light, dist_to_light - (EPS_D * dir_to_light).norm(), 0);
if (!bvh->intersect(shadow_ray))
{
L_out += (f * light_L * (cos_theta * scale / pdf));
}
}
}
**
abolve is my some code and render result. The shadow looks so hard.If i want to make the shadow softer, What can I do? I am writing path tracing.
Thanks.**

Converting an svg arc to lines

I am trying to convert an SVG arc to a series of line segments. The background is, that I want to draw an arc using (reportlab)[http://www.reportlab.com/].
The svg gives me these parameters (accoring to here).
rx,ry,x-axis-rotation,large-arc-flag,sweep-flag,dx,dy
Now I need to determine lines following this arcs. But I do not understand how I can convert this to something geometrical more usable.
How would I determine the center of the ellipse arc and its rotation?
SVG elliptic arcs are really tricky and took me a while to implement it (even following the SVG specs). I ended up with something like this in C++:
//---------------------------------------------------------------------------
class svg_usek // virtual class for svg_line types
{
public:
int pat; // svg::pat[] index
virtual void reset(){};
virtual double getl (double mx,double my){ return 1.0; };
virtual double getdt(double dl,double mx,double my){ return 0.1; };
virtual void getpnt(double &x,double &y,double t){};
virtual void compute(){};
virtual void getcfg(AnsiString &nam,AnsiString &dtp,AnsiString &val){};
virtual void setcfg(AnsiString &nam,AnsiString &dtp,AnsiString &val,int &an,int &ad,int &av){};
};
//---------------------------------------------------------------------------
class svg_ela:public svg_usek // sweep = 0 arc goes from line p0->p1 CW
{ // sweep = 1 arc goes from line p0->p1 CCW
public: // larc is unused if |da|=PI
double x0,y0,x1,y1,a,b,alfa; int sweep,larc;
double sx,sy,a0,a1,da,ang; // sx,sy rotated center by ang
double cx,cy; // real center
void reset() { x0=0; y0=0; x1=0; y1=0; a=0; b=0; alfa=0; sweep=false; larc=false; compute(); }
double getl (double mx,double my);
// double getdt(double dl,double mx,double my);
double getdt(double dl,double mx,double my) { int n; double dt; dt=divide(dl,getl(mx,my)); n=floor(divide(1.0,dt)); if (n<1) n=1; return divide(1.0,n); }
void getpnt(double &x,double &y,double t);
void compute();
void getcfg(AnsiString &nam,AnsiString &dtp,AnsiString &val);
void setcfg(AnsiString &nam,AnsiString &dtp,AnsiString &val,int &an,int &ad,int &av);
svg_ela() {}
svg_ela(svg_ela& a) { *this=a; }
~svg_ela() {}
svg_ela* operator = (const svg_ela *a) { *this=*a; return this; }
//svg_ela* operator = (const svg_ela &a) { ...copy... return this; }
};
//---------------------------------------------------------------------------
void svg_ela::getpnt(double &x,double &y,double t)
{
double c,s,xx,yy;
t=a0+(da*t);
xx=sx+a*cos(t);
yy=sy+b*sin(t);
c=cos(-ang);
s=sin(-ang);
x=xx*c-yy*s;
y=xx*s+yy*c;
}
//---------------------------------------------------------------------------
void svg_ela::compute()
{
double ax,ay,bx,by; // body
double vx,vy,l,db;
int _sweep;
double c,s,e;
ang=pi-alfa;
_sweep=sweep;
if (larc) _sweep=!_sweep;
e=divide(a,b);
c=cos(ang);
s=sin(ang);
ax=x0*c-y0*s;
ay=x0*s+y0*c;
bx=x1*c-y1*s;
by=x1*s+y1*c;
ay*=e; // transform to circle
by*=e;
sx=0.5*(ax+bx); // mid point between A,B
sy=0.5*(ay+by);
vx=(ay-by);
vy=(bx-ax);
l=divide(a*a,(vx*vx)+(vy*vy))-0.25;
if (l<0) l=0;
l=sqrt(l);
vx*=l;
vy*=l;
if (_sweep)
{
sx+=vx;
sy+=vy;
}
else{
sx-=vx;
sy-=vy;
}
a0=atanxy(ax-sx,ay-sy);
a1=atanxy(bx-sx,by-sy);
// ay=divide(ay,e);
// by=divide(by,e);
sy=divide(sy,e);
da=a1-a0;
if (fabs(fabs(da)-pi)<=_acc_zero_ang) // half arc is without larc and sweep is not working instead change a0,a1
{
db=(0.5*(a0+a1))-atanxy(bx-ax,by-ay);
while (db<-pi) db+=pi2; // db<0 CCW ... sweep=1
while (db>+pi) db-=pi2; // db>0 CW ... sweep=0
_sweep=0;
if ((db<0.0)&&(!sweep)) _sweep=1;
if ((db>0.0)&&( sweep)) _sweep=1;
if (_sweep)
{
// a=0; b=0;
if (da>=0.0) a1-=pi2;
if (da< 0.0) a0-=pi2;
}
}
else if (larc) // big arc
{
if ((da< pi)&&(da>=0.0)) a1-=pi2;
if ((da>-pi)&&(da< 0.0)) a0-=pi2;
}
else{ // small arc
if (da>+pi) a1-=pi2;
if (da<-pi) a0-=pi2;
}
da=a1-a0;
// realny stred
c=cos(+ang);
s=sin(+ang);
cx=sx*c-sy*s;
cy=sx*s+sy*c;
}
//---------------------------------------------------------------------------
The atanxy(x,y) is the same as atan2(y,x). You can ignore class svg_usek. Usage of svg_ela is simple first feed the SVG parameters to it:
x0,y0 is start point (from previous <path> element)
x1,y1 is endpoint (x0+dx,y0+dy)
a,b are as yours rx,ry
alfa rotation angle [rad] so you need to convert from degrees...
sweep,larc are as yours.
And then call svg_ela::compute(); that will compute all variables needed for interpolation. When this initialization is done then to obtain any point from the arc just call svg_ela::getpnt(x,y,t); where x,y is the returned coordinate and t=<0,1> is input parameter. All the other methods are not important for you. To render your ARC just do this:
svg_ela arc; // your initialized arc here
int e; double x,y,t;
arc.getpnt(x,y,0.0);
Canvas->MoveTo(x,y);
for (e=1,t=0.0;e;t+=0.02)
{
if (t>=1.0) { t=1.0; e=0; }
arc.getpnt(x,y,t);
Canvas->LineTo(x,y);
}
Do not forget that SVG <g> and <path> can have transform matrices so you should apply them after each svg_ela::getpnt(x,y,t) call.
If you are interested how the stuff works compute() simply:
rotates the space so the ellipse semi-axises are axis aligned.
scale the space so ellipse becomes circle.
compute center point for circle
center lies on line that is perpendicular to line (x0,y0),(x1,y1) and also lies on its midpoint. The distance is computed by Pytagoras and direction from sweep and larc combination.
scale back to ellipse
rotate back
Now we have real center position so also compute the real endpoint angles relative to it. Now for each point on ellipse it is enough to compute it by standard parametric equation of ellipse and rotate to desired position which is what getpnt(x,y,t) does.
Hope it helps a bit.
Here related QA:
Express SVG arc as series of curves
with some images explaining the math behind SVG arcs (using the same variable names as here)
For my Java SVG application I needed a conversion of path arc to lines. I used the above code and converted it into a Java class and performed some cleanup.
package de.berndbock.tinysvg.helper;
/**
* Breaks down SVG arcs into line segments.
*
* #author Bernd Bock <chef#bernd-bock.de>
*/
public class ArcSegmenter {
private static final double PI2 = Math.PI * 2;
private static final double ACC_ZERO_ANG = 0.000001 * Math.PI / 180.0;
private final double x0;
private final double y0;
private final double x1;
private final double y1;
private final double a;
private final double b;
private final double alfa;
private final boolean sweep;
private final boolean larc;
private double sx, sy, a0, a1, da, ang; // sx, sy rotated center by ang
// private double cx, cy; // real center
public ArcSegmenter(double x0, double y0, double x1, double y1 , double a, double b, double alfa, int sweep, int larc) {
this.x0 = x0;
this.y0 = y0;
this.x1 = x1;
this.y1 = y1;
this.a = a;
this.b = b;
this.alfa = alfa;
this.sweep = sweep != 0;
this.larc = larc != 0;
compute();
}
private void compute() {
double ax, ay, bx, by; // body
double vx, vy, l, db;
boolean _sweep;
double c, s, e;
ang = Math.PI - alfa;
_sweep = sweep;
if (larc) {
_sweep = !_sweep;
}
e = a / b;
c = Math.cos(ang);
s = Math.sin(ang);
ax = x0 * c - y0 * s;
ay = x0 * s + y0 * c;
bx = x1 * c - y1 * s;
by = x1 * s + y1 * c;
ay *= e; // transform to circle
by *= e;
sx = 0.5 * (ax + bx); // mid point between A,B
sy = 0.5 * (ay + by);
vx = (ay - by);
vy = (bx - ax);
l = a * a / (vx * vx + vy * vy) - 0.25;
if (l < 0) {
l = 0;
}
l = Math.sqrt(l);
vx *= l;
vy *= l;
if (_sweep) {
sx += vx;
sy += vy;
}
else {
sx -= vx;
sy -= vy;
}
a0 = Math.atan2(ay - sy, ax - sx);
a1 = Math.atan2(by - sy, bx - sx);
sy = sy / e;
da = a1 - a0;
if (Math.abs(Math.abs(da) - Math.PI) <= ACC_ZERO_ANG) { // half arc is without larc and sweep is not working instead change a0,a1
db = (0.5 * (a0 + a1)) - Math.atan2(by - ay, bx - ax);
while (db < -Math.PI) {
db += PI2; // db<0 CCW ... sweep=1
}
while (db > Math.PI) {
db -= PI2; // db>0 CW ... sweep=0
}
_sweep = false;
if ((db < 0.0) && (!sweep)) {
_sweep = true;
}
if ((db > 0.0) && ( sweep)) {
_sweep = true;
}
if (_sweep) {
if (da >= 0.0) {
a1 -= PI2;
}
if (da < 0.0) {
a0 -= PI2;
}
}
}
else if (larc) { // big arc
if ((da < Math.PI) && (da >= 0.0)) {
a1 -= PI2;
}
if ((da > -Math.PI) && (da < 0.0)) {
a0 -= PI2;
}
}
else { // small arc
if (da > Math.PI) {
a1 -= PI2;
}
if (da < -Math.PI) {
a0 -= PI2;
}
}
da = a1 - a0;
// center point calculation:
// c = Math.cos(ang);
// s = Math.sin(ang);
// cx = sx * c - sy * s;
// cy = sx * s + sy * c;
}
public Point getpnt(double t) {
Point result = new Point();
double c, s, x, y;
t = a0 + da * t;
x = sx + a * Math.cos(t);
y = sy + b * Math.sin(t);
c = Math.cos(-ang);
s = Math.sin(-ang);
result.x = x * c - y * s;
result.y = x * s + y * c;
return result;
}
// public Point getCenterPoint() {
// return new Point(cx, cy);
// }
}
If you need the center point, then uncomment the respective lines.
Sample code to give you an idea of the usage:
ArcSegmenter segmenter = new ArcSegmenter(currentPoint.x, currentPoint.y, endPoint.x, endPoint.y, rx, ry, phi, sf, lf);
Point p1, p2;
p1 = segmenter.getpnt(0.0);
Line line;
for (double t = increment; t < 1.000001f; t += increment) {
p2 = segmenter.getpnt(t);
line = new Line(null, parent, p1.x, p1.y, p2.x, p2.y);
elements.add(line);
p1 = p2;
}

Draw Sphere - order of vertices

I would like draw sphere in pure OpenGL ES 2.0 without any engines. I write next code:
int GenerateSphere (int Slices, float radius, GLfloat **vertices, GLfloat **colors) {
srand(time(NULL));
int i=0, j = 0;
int Parallels = Slices ;
float tempColor = 0.0f;
int VerticesCount = ( Parallels + 1 ) * ( Slices + 1 );
float angleStep = (2.0f * M_PI) / ((float) Slices);
// Allocate memory for buffers
if ( vertices != NULL ) {
*vertices = malloc ( sizeof(GLfloat) * 3 * VerticesCount );
}
if ( colors != NULL) {
*colors = malloc( sizeof(GLfloat) * 4 * VerticesCount);
}
for ( i = 0; i < Parallels+1; i++ ) {
for ( j = 0; j < Slices+1 ; j++ ) {
int vertex = ( i * (Slices + 1) + j ) * 3;
(*vertices)[vertex + 0] = radius * sinf ( angleStep * (float)i ) *
sinf ( angleStep * (float)j );
(*vertices)[vertex + 1] = radius * cosf ( angleStep * (float)i );
(*vertices)[vertex + 2] = radius * sinf ( angleStep * (float)i ) *
cosf ( angleStep * (float)j );
if ( colors ) {
int colorIndex = ( i * (Slices + 1) + j ) * 4;
tempColor = (float)(rand()%100)/100.0f;
(*colors)[colorIndex + 0] = 0.0f;
(*colors)[colorIndex + 1] = 0.0f;
(*colors)[colorIndex + 2] = 0.0f;
(*colors)[colorIndex + (rand()%4)] = tempColor;
(*colors)[colorIndex + 3] = 1.0f;
}
}
}
return VerticesCount;
}
I'm drawing it with using next code:
glDrawArrays(GL_TRIANGLE_STRIP, 0, userData->numVertices);
Where userData->numVertices - VerticesCount from function GenerateSphere.
But on screen draws series triangles, these aren't sphere approximation!
I think, I need to numerate vertices and use OpenGL ES 2.0 function glDrawElements() (with array, contained number vertices). But series of triangles drawn on the screen is not a sphere approximation.
How can I draw sphere approximation? How specify order vertices (indices in OpenGL ES 2.0 terms)?
Before you start with anything in OpenGL ES, here is some advice:
Avoid bloating CPU/GPU performance
Removing intense cycles of calculations by rendering the shapes offline using another program will surely help. These programs will provide additional details about the shapes/meshes apart from exporting the resultant collection of points [x,y,z] comprising the shapes etc.
I went through all this pain way back, because I kept trying to search for algorithms to render spheres etc and then trying to optimize them. I just wanted to save your time in the future. Just use Blender and then your favorite programming language to parse the obj files that are exported from Blender, I use Perl. Here are the steps to render sphere: (use glDrawElements because the obj file contains the array of indices)
1) Download and install Blender.
2) From the menu, add sphere and then reduce the number of rings and segments.
3) Select the entire shape and triangulate it.
4) Export an obj file and parse it for the meshes.
You should be able to grasp the logic to render sphere from this file: http://pastebin.com/4esQdVPP. It is for Android, but the concepts are same.
Hope this helps.
I struggled with spheres and other geometric shapes. I worked at it a while and created an Objective-C class to create coordinates, normals, and texture coordinates both using indexed and non-indexed mechanisms, the class is here:
http://www.whynotsometime.com/Why_Not_Sometime/Code_Snippets.html
What is interesting to see the resulting triangles representing the geometry is to reduce the resolution (set the resolution property before generating the coordinates). Also, you can use GL_LINE_STRIP instead of GL_TRIANGLES to see a bit more.
I agree with the comment from wimp that since calculating the coordinates generally happens once, not many CPU cycles are used. Also, sometimes one does want to draw only a ball or world or...

Circle-Rectangle collision detection finished exampe

I need a algorithm for detecting if a circle has hit a square, and I saw this post:
Circle-Rectangle collision detection (intersection)
It looks like I should go for ShreevatsaR's answer, but I am a math fool, and I have no idea how to finish the algorithm. Could anyone find the time to make a complete example for me please, I have searched the net for this, and have yet found no working example.
Thank you very much
Soeren
EDIT:
Ok here is my attempt. It is not working, it never detects any collisions.
typedef struct {
double x;
double y;
} point;
typedef struct {
point one;
point two;
} segment;
typedef struct {
point center;
double radius;
} circle;
typedef struct {
point p;
int width;
int height;
point a;
point b;
point c;
point d;
} rectangle;
double slope(point one, point two) {
return (double)(one.y-two.y)/(one.x-two.x);
}
double distance(point p, segment s) {
// Line one is the original line that was specified, and line two is
// the line we're constructing that runs through the specified point,
// at a right angle to line one.
//
// if it's a vertical line return the horizontal distance
if ( s.one.x == s.two.x)
return fabs(s.one.x - p.x);
// if it's a horizontal line return the vertical distance
if ( s.one.y == s.two.y )
return fabs(s.one.y - p.y);
// otherwise, find the slope of the line
double m_one = slope(s.one, s.two);
// the other slope is at a right angle.
double m_two = -1.0 / m_one;
// find the y-intercepts.
double b_one = s.one.y - s.one.x * m_one;
double b_two = p.y - p.x * m_two;
// find the point of intersection
double x = (b_two - b_one) / (m_one - m_two);
double y = m_one * x + b_one;
// find the x and y distances
double x_dist = x - p.x;
double y_dist = y - p.y;
// and return the total distance.
return sqrt(x_dist * x_dist + y_dist * y_dist);
}
bool intersectsCircle(segment s, circle c) {
return distance(c.center, s) <= c.radius;
}
bool pointInRectangle(point p, rectangle r)
{
float right = r.p.x + r.width;
float left = r.p.x - r.width;
float top = r.p.y + r.height;
float bottom = r.p.y - r.height;
return ((left <= p.x && p.x <= right) && (top <= p.y && p.y <= bottom));
}
bool intersect(circle c, rectangle r) {
segment ab;
ab.one = r.a;
ab.two = r.b;
segment bc;
ab.one = r.b;
ab.two = r.c;
segment cd;
ab.one = r.c;
ab.two = r.d;
segment da;
ab.one = r.d;
ab.two = r.a;
return pointInRectangle(c.center, r) ||
intersectsCircle(ab, c) ||
intersectsCircle(bc, c) ||
intersectsCircle(cd, c) ||
intersectsCircle(da, c);
}
The primary part he seems to have left is the InteresectsCircle(line, circle).
#include <math.h>
typedef struct {
double x;
double y;
} point;
typedef struct {
point one;
point two;
} segment;
typedef struct {
point center;
double radius;
} circle;
double slope(point &one, point &two) {
return (double)(one.y-two.y)/(one.x-two.x);
}
double distance(point &p, segment &s) {
// Line one is the original line that was specified, and line two is
// the line we're constructing that runs through the specified point,
// at a right angle to line one.
//
// if it's a vertical line return the horizontal distance
if ( s.one.x == s.two.x)
return fabs(s.one.x - p.x);
// if it's a horizontal line return the vertical distance
if ( s.one.y == s.two.y )
return fabs(s.one.y - p.y);
// otherwise, find the slope of the line
double m_one = slope(s.one, s.two);
// the other slope is at a right angle.
double m_two = -1.0 / m_one;
// find the y-intercepts.
double b_one = s.one.y - s.one.x * m_one;
double b_two = p.y - p.x * m_two;
// find the point of intersection
double x = (b_two - b_one) / (m_one - m_two);
double y = m_one * x + b_one;
// find the x and y distances
double x_dist = x - p.x;
double y_dist = y - p.y;
// and return the total distance.
return sqrt(x_dist * x_dist + y_dist * y_dist);
}
bool IntersectsCircle(segment s, circle c) {
return distance(circle.center, s) <= circle.radius;
}
I have some code in C++ (lightly templated) that should do these intersection tests, but I haven't had time to test them yet. In particular, I have the segment-circle intersection test as well as parallelogram-circle intersection, which is supposed to compute the intersection area and intersection points. Again, this is completely untested as of the writing of this comment, so you will need to test/adapt them to your needs.

Resources