Ejemplo n.º 1
0
Archivo: mesh.c Proyecto: prideout/tol
parg_mesh* parg_mesh_knot(int slices, int stacks, float major, float minor)
{
    parg_mesh* surf = malloc(sizeof(struct parg_mesh_s));
    float ds = 1.0f / slices;
    float dt = 1.0f / stacks;
    int vertexCount = slices * stacks * 3;
    int vertexStride = sizeof(float) * 3;
    surf->coords =
        parg_buffer_alloc(vertexCount * vertexStride, PARG_GPU_ARRAY);
    surf->normals =
        parg_buffer_alloc(vertexCount * vertexStride, PARG_GPU_ARRAY);
    surf->uvs = 0;
    Point3* position = (Point3*) parg_buffer_lock(surf->coords, PARG_WRITE);
    Vector3* normal = (Vector3*) parg_buffer_lock(surf->normals, PARG_WRITE);
    for (float s = 0; s < 1 - ds / 2; s += ds) {
        for (float t = 0; t < 1 - dt / 2; t += dt) {
            const float E = 0.01f;
            Point3 p = knot_fn(s, t);
            Vector3 u = P3Sub(knot_fn(s + E, t), p);
            Vector3 v = P3Sub(knot_fn(s, t + E), p);
            Vector3 n = V3Normalize(V3Cross(u, v));
            *position++ = p;
            *normal++ = n;
        }
    }
    parg_buffer_unlock(surf->coords);
    parg_buffer_unlock(surf->normals);

    surf->ntriangles = slices * stacks * 2;
    int indexCount = surf->ntriangles * 3;
    surf->indices = parg_buffer_alloc(indexCount * 2, PARG_GPU_ELEMENTS);
    uint16_t* index = (uint16_t*) parg_buffer_lock(surf->indices, PARG_WRITE);
    int v = 0;
    for (int i = 0; i < slices - 1; i++) {
        for (int j = 0; j < stacks; j++) {
            int next = (j + 1) % stacks;
            *index++ = v + next + stacks;
            *index++ = v + next;
            *index++ = v + j;
            *index++ = v + j;
            *index++ = v + j + stacks;
            *index++ = v + next + stacks;
        }
        v += stacks;
    }
    for (int j = 0; j < stacks; j++) {
        int next = (j + 1) % stacks;
        *index++ = next;
        *index++ = v + next;
        *index++ = v + j;
        *index++ = v + j;
        *index++ = j;
        *index++ = next;
    }
    parg_buffer_unlock(surf->indices);
    return surf;
}
Ejemplo n.º 2
0
Quat fromAxisAngle( Vector3 axis, float angle )
{
	V3Normalize( axis );
	angle /= 2 * RADTODEG;
	float s = sinf( angle );
	return Quat( cosf( angle ),
				 axis.x * s,
				 axis.y * s,
				 axis.z * s );
}
Ejemplo n.º 3
0
Plane *CalcMiddlePlane(Point3 *p1, Point3 *p2, Plane *p)
{Point3 m0;

 V3Add(p1,p2,&m0);
 m0.x/=2;m0.y/=2;m0.z/=2;
 V3Sub(p1,p2,&(p->N));
 V3Normalize(&(p->N));
 p->off = V3Dot(&m0,&(p->N));

 return p;
}
Ejemplo n.º 4
0
Archivo: Blob.c Proyecto: oleavitt/gem
int Ray_BlobAddPlane(Object *obj, Vec3 *pt, Vec3 *dir,
	double dist, double field)
{
	Bloblet *be;
	BlobData *blob = obj->data.blob;
	Vec3 Pt;

	assert(obj != NULL);
	assert(blob != NULL);
	
	if ((be = (Bloblet *)Malloc(sizeof(Bloblet))) == NULL)
		return 0;

	be->next = NULL;
	V3Copy(&be->loc, pt);
	V3Copy(&be->dir, dir);
	be->rad = dist;
	be->field = field;

	/*
	 * Normalize the normal vector.
	 * Invalid normals should be checked for during parse.
	 */
	V3Normalize(&be->dir);

	/* Get "d" coeff. for plane that bounds plane's interval. */
	Pt.x = be->dir.x * be->rad;
	Pt.y = be->dir.y * be->rad;
	Pt.z = be->dir.z * be->rad;
	be->d1 = -V3Dot(&be->dir, &Pt);

	/*
	 * Pre-compute constants for the density eq. in standard form.
	 * Radii that are too small shoud be checked for during parse.
	 */
	be->rsq = be->rad * be->rad;
	be->r2 = - (2.0 * be->field) / be->rsq;
	be->r4 = be->field / (be->rsq * be->rsq);
	be->type = BLOB_PLANE;

	/* Add the new plane element to the blob. */
	if (blob->elems != NULL)
	{
		Bloblet *lastbe;
		for (lastbe = blob->elems; lastbe->next != NULL; lastbe = lastbe->next)
			; /* Seek last element added to list. */
		/* Append our new one. */
		lastbe->next = be;
	}
	else
		blob->elems = be;

	return 1;
}
Ejemplo n.º 5
0
Point3 *CalcSphereCenter(Point3 *v0, Point3 *v1, Point3 *v2, Point3 *v3,Point3 *c)
{
    Vector3 d1, d2, d3;

    Plane p1,p2,p3;

    V3Add(v0, v1, &d1);
    V3Add(v0, v2, &d2);
    V3Add(v0, v3, &d3);

    d1.x/=2;
    d1.y/=2;
    d1.z/=2;
    d2.x/=2;
    d2.y/=2;
    d2.z/=2;
    d3.x/=2;
    d3.y/=2;
    d3.z/=2;

    V3Sub(v0, v1, &(p1.N));
    V3Sub(v0, v2, &(p2.N));
    V3Sub(v0, v3, &(p3.N));

    V3Normalize(&(p1.N));
    V3Normalize(&(p2.N));
    V3Normalize(&(p3.N));

    p1.off = V3Dot(&(p1.N), &d1);
    p2.off = V3Dot(&(p2.N), &d2);
    p3.off = V3Dot(&(p3.N), &d3);


    if(CalcPlaneInter(&p1, &p2, &p3, c)) return c;
    else  return NULL;

}
Ejemplo n.º 6
0
Plane *CalcPlane(Vector3 *p0, Vector3 *p1, Vector3 *p2, Plane *p )
{
 Vector3 v1,v2;
 Vector3 *N;
 N=&(p->N);


 V3Sub(p1,p0,&v1);
 V3Sub(p2,p0,&v2);
 V3Cross(&v1,&v2,N);
 if(N->x==0.0 && N->y==0.0 && N->z==0.0) return NULL;

 V3Normalize(N);

 p->off=V3Dot(N,p0);

 return p;
}
Ejemplo n.º 7
0
void SetupPolygon(PolygonData *ply)
{
	Vec3 V1, V2, N;
	float *pts;

	assert(ply != NULL);
	assert(ply->npts >= 3);

	pts = ply->pts;

	assert(pts != NULL);

	/* Compute plane normal. (based on first three vertices) */
	V1.x = pts[3] - pts[0];
	V2.x = pts[6] - pts[0];
	V1.y = pts[4] - pts[1];
	V2.y = pts[7] - pts[1];
	V1.z = pts[5] - pts[2];
	V2.z = pts[8] - pts[2];

	V3Cross(&N, &V1, &V2);
	V3Normalize(&N);
	ply->nx = (float)N.x;
	ply->ny = (float)N.y;
	ply->nz = (float)N.z;

	/* Determine axis of greatest projection. */
	if(fabs(N.x) > fabs(N.z))
	{
		if(fabs(N.x) > fabs(N.y))
			ply->axis = X_AXIS;
		else
			ply->axis = Y_AXIS;
	}
	else if(fabs(N.y) > fabs(N.z))
		ply->axis = Y_AXIS;
	else
		ply->axis = Z_AXIS;
}
Ejemplo n.º 8
0
void GetEntXForm(ADSResBuf *edata, Matrix4 mx)
{
    double xscl = 1.0, yscl = 1.0, zscl = 1.0, rotang = 0.0;
    Vector3 zaxis, *zaxis_p = NULL;
    Point3 inpt, *inpt_p = NULL;
	Point3 bpt, *bpt_p = NULL;
    ADSResBuf *bdata, *rb;
	int isinsert = 0;

    rb = RBGetPoint3(&zaxis, edata, 210);
	if(rb != NULL && V3Normalize(&zaxis) != 0.0) zaxis_p = &zaxis;

    if (strcmp(RBSearch(edata, 0)->resval.rstring, "INSERT") == 0) {
		isinsert = 1;
	    if(RBGetPoint3(&inpt, edata, 10) != NULL) inpt_p = &inpt;
		(void)RBGetDouble(&rotang, edata, 50);
		(void)RBGetDouble(&xscl, edata, 41);
		(void)RBGetDouble(&yscl, edata, 42);
		(void)RBGetDouble(&zscl, edata, 43);

		/* the block base point */
		bdata = ads_tblsearch("BLOCK", RBSearch(edata, 2)->resval.rstring, 1);
		if(bdata) {
			rb = RBGetPoint3(&bpt, bdata, 10);
			if (rb != NULL) bpt_p = &bpt;
		    ads_relrb(bdata);
		}
	}
	M4GetAcadXForm(mx, zaxis_p, isinsert, inpt_p, rotang, xscl, yscl, zscl, bpt_p);

#ifdef DEBUG
    fprintf(stderr, "GetEntXForm: bpt: %f %f %f\n", bpt.x,
            bpt.y, bpt.z);
    M4Print(stderr, mx);
    fprintf(stderr, "GetEntXForm: inpt: %f  %f  %f\n", inpt.x, inpt.y,
            inpt.z);
    fprintf(stderr, "GetEntXForm: pt: %f  %f  %f\n", pt.x, pt.y, pt.z);
#endif
}
Ejemplo n.º 9
0
Object *MakeExtrudeObject(PARAMS *par)
{
	Object *obj;
	MeshData *mesh;
	MeshTri *tris = NULL, *t;
	MeshVertex *v1, *v2, *pv1, *pv2, **newverts, **prevverts;
	Vec3 V;
	Xform *T = NULL, *Tlocal = NULL;   /* Transform matrix for segments. */
	int i, j, k, ntris, nverts, nsegs, reps, smooth;
	double u, v;

	if((mesh = Ray_NewMeshData()) == NULL)
		return NULL;

	/* First parameter is the number of vertices. */
	nverts = (int)par->V.x;
	
  /* Get the initial vertices... */
	par = par->next;
	for(i = 0; i < nverts; i++)
	{
		/* Get the point. */
		Eval_Params(par);
		if((v1 = Ray_NewMeshVertex(&par->V)) == NULL)
			goto fail_create;
		if(!Ray_AddMeshVertex(mesh, v1))
			goto fail_create;
		/* Get the optional stuff. */
		if(par->more)
		{
			/* Normal. */
			par = par->next;
			v1->nx = (float)par->V.x;
			v1->ny = (float)par->V.y;
			v1->nz = (float)par->V.z;
			v1->flags |= MESH_VERTEX_HAS_NORMAL;
			if(par->more)
			{
				/* Color. */
				par = par->next;
				v1->r = (float)par->V.x;
				v1->g = (float)par->V.y;
				v1->b = (float)par->V.z;
				v1->flags |= MESH_VERTEX_HAS_COLOR;
				if(par->more)
				{
					/* UV coordinates. */
					par = par->next;
					v1->u = (float)par->V.x;
					par = par->next;
					v1->v = (float)par->V.x;
					v1->flags |= MESH_VERTEX_HAS_UV;
			}
			}
		}
		par = par->next;
	}
			
	/*
	 * Get the segments.
	 * Create a new set of vertices as transformed copies of the
	 * previous set of vertices.
	 * Create the triangles that connect the two sets of vertices to
	 * form a segment.
	 */
	if((T = Ray_NewXform()) == NULL)
		goto fail_create;
	if((Tlocal = Ray_NewXform()) == NULL)
		goto fail_create;
  ntris = nsegs = 0;
	tris = t = NULL;
	smooth = 0;
	while(par != NULL)
	{
		switch(par->type)
		{
			case TK_SEGMENT:
				M4x4Identity(&Tlocal->M);
				M4x4Identity(&Tlocal->I);
				reps = 1; /* Repeat count. */
				break;
			case TK_SMOOTH:
				smooth = 1;
				break;
			case TK_RIGHTBRACE: /* End of segment. */
				while(reps--)
				{
					nsegs++;
					/*
					 * Create a new set of vertices as transformed copies of the
					 * original set.
					 */
					ConcatXforms(T, Tlocal);
					for(i = 0; i < nverts; i++)
					{
						if((v1 = Ray_NewMeshVertex(NULL)) == NULL)
							goto fail_create;
						*v1 = *mesh->vertices[i];
						V.x = v1->x; V.y = v1->y; V.z = v1->z;
						PointToWorld(&V, T);
						v1->x = (float)V.x; v1->y = (float)V.y; v1->z = (float)V.z;
						V.x = v1->nx; V.y = v1->ny; V.z = v1->nz;
						if(!(ISZERO(V.x) && ISZERO(V.y) && ISZERO(V.z)))
						{
							NormToWorld(&V, T);
							V3Normalize(&V);
							v1->nx = (float)V.x; v1->ny = (float)V.y; v1->nz = (float)V.z;
						}
						if(!Ray_AddMeshVertex(mesh, v1))
							goto fail_create;
					}
					/* Create connecting triangles. */
					prevverts = mesh->vertices + nverts * (nsegs - 1);
					newverts = mesh->vertices + nverts * nsegs;
					pv1 = *prevverts++;
					v1 = *newverts++;
					for(i = 1; i < nverts; i++)
					{
						pv2 = *prevverts++;
						v2 = *newverts++;
						if((t = Ray_NewMeshTri(pv1, pv2, v1)) != NULL)
						{
							t->next = tris;
							tris = t;
							ntris++;
						}
						if((t = Ray_NewMeshTri(v2, v1, pv2)) != NULL)
						{
							t->next = tris;
							tris = t;
							ntris++;
						}
						pv1 = pv2;
						v1 = v2;
					}
					/* If closed, connect the end vertices. */
				}
				break;
  		/*
			 * Since we know that there is always one vector parameter for all
			 * of the transform cases, the "TK_VECTOR" type param is
			 * actually the transform param, so we'll just just change
			 * the type to TK_VECTOR before passing it Eval_Params().
			 * This shortcut helps keep the parameter list short.
			 */
			case TK_ROTATE:
				par->type = TK_VECTOR;
        Eval_Params(par);
				XformXforms(Tlocal, &par->V, XFORM_ROTATE);
				break;
			case TK_SCALE:
				par->type = TK_VECTOR;
        Eval_Params(par);
				XformXforms(Tlocal, &par->V, XFORM_SCALE);
				break;
			case TK_SHEAR:
				par->type = TK_VECTOR;
        Eval_Params(par);
				XformXforms(Tlocal, &par->V, XFORM_SHEAR);
				break;
			case TK_TRANSLATE:
				par->type = TK_VECTOR;
        Eval_Params(par);
				XformXforms(Tlocal, &par->V, XFORM_TRANSLATE);
				break;
			case TK_REPEAT:
				par->type = TK_FLOAT;
        Eval_Params(par);
				reps = max((int)par->V.x, 0);
				break;
		}
		par = par->next;
	}

	Ray_DeleteXform(T);
	Ray_DeleteXform(Tlocal);
	
	/* If smooth, generate normals where none were explicitly defined. */

	/* Generate UV coordinates where none were explicitly defined. */
	k = 0;
	for(i = 0; i <= nsegs; i++)
	{
	  u = (double)i / (double)nsegs;
		for(j = 0; j < nverts; j++)
		{
			v = (double)j / (double)(nverts - 1);
			v1 = mesh->vertices[k++];
			v1->u = (float)u;
			v1->v = (float)v;
		}
	}

	if((obj = Ray_MakeMeshFromData(mesh, tris, ntris)) == NULL)
		goto fail_create;
	
	if(smooth)
		obj->flags |= OBJ_FLAG_SMOOTH;

	return obj;

	fail_create:

	while(tris != NULL)
	{
		t = tris;
		tris = t->next;
		Ray_DeleteMeshTri(t);
	}
	Ray_DeleteMeshData(mesh);
	Ray_DeleteXform(T);
	Ray_DeleteXform(Tlocal);

	return NULL;
}
Ejemplo n.º 10
0
extern int WriteCyl(FILE *fp, char *matName,
					int id, Cyl3 *cyls)
{
    int cylCnt = 0;
    Cyl3 *cyl;
    Vector3 dir;
	char *material = matName;

#ifdef DEBUG
    fprintf(stderr, "WriteCyl(%p, %p)\n", contblks, cyls);
#endif
    if (cyls == NULL)
        return 1;
    for (cyl = cyls; cyl; cyl = cyl->next) {
		if(matName == NULL) material = cyl->material;
		if(cyl->erad == 0.0) { /* it's a point/sphere */
			int sign;
			sign = (cyl->srad > 0 ? 1 : -1);
			if (sign > 0) {
				fprintf(fp, "\n%s sphere %s.%d.%d\n",
					material, material, id, cylCnt++);
			} else {
				fprintf(fp, "\n%s bubble %s.%d.%d\n",
					material, material, id, cylCnt++);
			}
			fprintf(fp, "0\n0\n4");
			fprintf(fp, "\t%.8g\t%.8g\t%.8g\t%.8g\n",
				cyl->svert.x, cyl->svert.y, cyl->svert.z,
				fabs(cyl->srad));
		} else if (cyl->length != 0.0) { /* it's a cylinder or tube */
			if(cyl->length >= 0.0) {
				fprintf(fp, "\n%s cylinder %s.%d.%d\n",
					material, material, id, cylCnt++);
			} else {
				fprintf(fp, "\n%s tube %s.%d.%d\n",
					material, material, id, cylCnt++);
			}
            fprintf(fp, "0\n0\n7");
            fprintf(fp, "\t%.8g %.8g %.8g\n", cyl->svert.x,
                    cyl->svert.y, cyl->svert.z);
            fprintf(fp, "\t%.8g %.8g %.8g\n", cyl->evert.x,
                    cyl->evert.y, cyl->evert.z);
            fprintf(fp, "\t%.8g\n", cyl->srad);
            /* bottom cap */
            fprintf(fp, "\n%s ring %s.%d.%d\n",
				material, material, id, cylCnt++);
            fprintf(fp, "0\n0\n8");
            fprintf(fp, "\t%.8g %.8g %.8g\n",
				cyl->svert.x, cyl->svert.y, cyl->svert.z);
			if(cyl->length >= 0.0) {
	            (void)V3Normalize(V3Sub(&cyl->svert, &cyl->evert, &dir));
			} else {
	            (void)V3Normalize(V3Sub(&cyl->evert, &cyl->svert, &dir));
			}
            fprintf(fp, "\t%.8g %.8g %.8g\n", dir.x, dir.y, dir.z);
            fprintf(fp, "\t0 %.8g\n", cyl->srad);
			/* top cap */
            fprintf(fp, "\n%s ring %s.%d.%d\n",
				material, material, id, cylCnt++);
            fprintf(fp, "0\n0\n8");
            fprintf(fp, "\t%.8g %.8g %.8g\n",
				cyl->evert.x, cyl->evert.y, cyl->evert.z);
			if(cyl->length >= 0.0) {
	            (void)V3Normalize(V3Sub(&cyl->evert, &cyl->svert, &dir));
			} else {
	            (void)V3Normalize(V3Sub(&cyl->svert, &cyl->evert, &dir));
			}
            fprintf(fp, "\t%.8g %.8g %.8g\n", dir.x, dir.y, dir.z);
            fprintf(fp, "\t0 %.8g\n", cyl->srad);
        } else {            /* it's a ring */
            fprintf(fp, "\n%s ring %s.%d.%d\n",
				material, material, id, cylCnt++);
            fprintf(fp, "0\n0\n8");
            fprintf(fp, "\t%.8g %.8g %.8g\n",
				cyl->svert.x, cyl->svert.y, cyl->svert.z);
            (void)V3Normalize(&cyl->normal);
            fprintf(fp, "\t%.8g %.8g %.8g\n",
					cyl->normal.x, cyl->normal.y, cyl->normal.z);

            fprintf(fp, "\t0 %.8g\n", cyl->srad);
        }
    }
	Cyl3FreeList(cyls);
    return 1;
}
Ejemplo n.º 11
0
static MeshPod CreateTrefoil()
{
    const int Slices = 256;
    const int Stacks = 32;
    const int VertexCount = Slices * Stacks;
    const int IndexCount = VertexCount * 6;

    MeshPod mesh;
    glGenVertexArrays(1, &mesh.Vao);
    glBindVertexArray(mesh.Vao);

    // Create a buffer with interleaved positions and normals
    if (true) {
        Vertex verts[VertexCount];
        Vertex* pVert = &verts[0];
        float ds = 1.0f / Slices;
        float dt = 1.0f / Stacks;

        // The upper bounds in these loops are tweaked to reduce the
        // chance of precision error causing an incorrect # of iterations.
        for (float s = 0; s < 1 - ds / 2; s += ds) {
            for (float t = 0; t < 1 - dt / 2; t += dt) {
                const float E = 0.01f;
                Vector3 p = EvaluateTrefoil(s, t);
                Vector3 u = V3Sub(EvaluateTrefoil(s + E, t), p);
                Vector3 v = V3Sub(EvaluateTrefoil(s, t + E), p);
                Vector3 n = V3Normalize(V3Cross(u, v));
                pVert->Position = p;
                pVert->Normal = n;
                ++pVert;
            }
        }

        pezCheck(pVert - &verts[0] == VertexCount, "Tessellation error.");

        GLuint vbo;
        GLsizeiptr size = sizeof(verts);
        const GLvoid* data = &verts[0].Position.x;
        GLenum usage = GL_STATIC_DRAW;
        glGenBuffers(1, &vbo);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, size, data, usage);
    }

    // Create a buffer of 16-bit indices
    if (true) {
        GLushort inds[IndexCount];
        GLushort* pIndex = &inds[0];
        GLushort n = 0;
        for (GLushort i = 0; i < Slices; i++) {
            for (GLushort j = 0; j < Stacks; j++) {
                *pIndex++ = (n + j + Stacks) % VertexCount;
                *pIndex++ = n + (j + 1) % Stacks;
                *pIndex++ = n + j;
                
                *pIndex++ = (n + (j + 1) % Stacks + Stacks) % VertexCount;
                *pIndex++ = (n + (j + 1) % Stacks) % VertexCount;
                *pIndex++ = (n + j + Stacks) % VertexCount;
            }
            n += Stacks;
        }

        pezCheck(n == VertexCount, "Tessellation error.");
        pezCheck(pIndex - &inds[0] == IndexCount, "Tessellation error.");

        GLuint handle;
        GLsizeiptr size = sizeof(inds);
        const GLvoid* data = &inds[0];
        GLenum usage = GL_STATIC_DRAW;
        glGenBuffers(1, &handle);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, usage);
    }

    mesh.VertexCount = VertexCount;
    mesh.IndexCount = IndexCount;

    glVertexAttribPointer(a("Position"), 3, GL_FLOAT, GL_FALSE, 24, 0);
    glVertexAttribPointer(a("Normal"), 3, GL_FLOAT, GL_FALSE, 24, offset(12));
    glEnableVertexAttribArray(a("Position"));
    glEnableVertexAttribArray(a("Normal"));

    pezCheck(OpenGLError);
    return mesh;
}
Ejemplo n.º 12
0
/*
 *---------------------------------------------------------
 * Compute a rotation matrix around an arbitrary axis
 * specified by 2 points p1 and p2; theta is the angle
 * between the two planes that share the same edge
 * defined by p1 and p2
 *
 * The matrix TM is the matrix that brings the plane of
 * face 'n' into face 'p'; Matrix iTM is the matrix
 * that brings the plane of face 'p' into 'n'
 * 'p' and 'n' are the names of faces according to the
 * winged edge data structure; 'p' is the previous face
 * and 'n' is the next face
 *---------------------------------------------------------
 */
int MxRotateAxis(Point3D p1, Point3D p2,
				 double theta, Matrix4 *TM, Matrix4 *iTM)
{
	Point3D p;
	double dist, cosX, sinX, cosY, sinY, det;
	Matrix4 m1, m2;
	
	p.x = p2.x - p1.x;
	p.y = p2.y - p1.y;
	p.z = p2.z - p1.z;
	
	if( V3Length( &p ) < 0.0 ) return(FALSE);
	
	V3Normalize( &p );
	
	dist = sqrt( p.y * p.y + p.z * p.z );
	
	/* maybe the 2 points are already aligned with the X-axis */
	if(dist < DAMN_SMALL || dist == 0.0){
		cosX = 1.0;
		sinX = 0.0;
	}
	else{
		cosX = p.z / dist;
		sinX = p.y / dist;
	}
	
	/* fprintf(stderr, "p: x = %3.2f y = %3.2f z = %3.2f dist = %3.2f\n",
	 p.x, p.y, p.z, dist); */
	
	cosY = dist;
	sinY = -p.x;
	
	loadIdentity( TM );
	loadIdentity( &m1 );
	
	/* inverse translation matrix */
	m1.element[0][3] = p1.x;
	m1.element[1][3] = p1.y;
	m1.element[2][3] = p1.z;
	/* fprintf(stderr,"Inverse Translation:\n");
	 printMatrix( m1 ); */
	
	/* Inverse Rotation around X */
	loadIdentity( &m2 );
	m2.element[1][1] = cosX;
	m2.element[2][1] = -sinX;
	m2.element[1][2] = sinX;
	m2.element[2][2] = cosX;
	/* fprintf(stderr,"Inverse Rotation around X:\n");
	 printMatrix( m2 ); */
	
	MatMul( &m1, &m2, TM );
	MatrixCopy( TM, &m1 );
	
	/* Inverse Rotation around Y */
	loadIdentity( &m2 );
	m2.element[0][0] = cosY;
	m2.element[2][0] = sinY;
	m2.element[0][2] = -sinY;
	m2.element[2][2] = cosY;
	/* fprintf(stderr,"Inverse Rotation around Y:\n");
	 printMatrix( m2 ); */
	
	MatMul( &m1, &m2, TM );
	MatrixCopy( TM, &m1 );
	
	/* Rotation around Z */
	loadIdentity( &m2 );
	m2.element[0][0]= cos( theta );
	m2.element[1][0]= -sin( theta );
	m2.element[0][1]= sin( theta );
	m2.element[1][1]= cos( theta );
	
	/* fprintf(stderr,"Rotation around Z:\n");
	 printMatrix( m2 ); */
	
	MatMul( &m1, &m2, TM );
	MatrixCopy( TM, &m1 );
	
	/* Rotation around Y */
	loadIdentity( &m2 );
	m2.element[0][0] = cosY;
	m2.element[2][0] = -sinY;
	m2.element[0][2] = sinY;
	m2.element[2][2] = cosY;
	/* fprintf(stderr,"Rotation around Y:\n");
	 printMatrix( m2 ); */
	
	MatMul( &m1, &m2, TM );
	MatrixCopy( TM, &m1 );
	
	/* Rotation around X */
	loadIdentity( &m2 );
	m2.element[1][1] = cosX;
	m2.element[2][1] = sinX;
	m2.element[1][2] = -sinX;
	m2.element[2][2] = cosX;
	/* fprintf(stderr,"Rotation around X:\n");
	 printMatrix( m2 ); */
	
	MatMul( &m1, &m2, TM );
	MatrixCopy( TM, &m1 );
	
	/* Translation matrix */
	loadIdentity( &m2 );
	m2.element[0][3] = -p1.x;
	m2.element[1][3] = -p1.y;
	m2.element[2][3] = -p1.z;
	/* fprintf(stderr,"Translation matrix:\n");
	 printMatrix( m2 ); */
	
	MatMul( &m1, &m2, TM );
	
	det = MxInvert(TM, iTM);
	if(det < L_EPSILON && det > -L_EPSILON)
		return( FALSE );
	/*return( MxInvert(TM, iTM) );*/
	else return ( TRUE );
}
Ejemplo n.º 13
0
Archivo: Blob.c Proyecto: oleavitt/gem
int Ray_BlobAddCylinder(Object *obj, Vec3 *pt1, Vec3 *pt2,
	double radius, double field)
{
	Bloblet *hemi1, *hemi2, *cyl;
	BlobData *blob = obj->data.blob;

	assert(obj != NULL);
	assert(blob != NULL);

	/*
	 * Cylindrical fields consist of three Bloblet elements.
	 * A cylinder and two hemispheres.
	 */						 

	/* Allocate the elements. */
	if ((cyl = (Bloblet *)Malloc(sizeof(Bloblet))) == NULL)
		return 0;
	if ((hemi1 = (Bloblet *)Malloc(sizeof(Bloblet))) == NULL)
	{
		Free(cyl, sizeof(Bloblet));
		return 0;
	}
	if ((hemi2 = (Bloblet *)Malloc(sizeof(Bloblet))) == NULL)
	{
		Free(hemi1, sizeof(Bloblet));
		Free(cyl, sizeof(Bloblet));
		return 0;
	}

	/* Link them together. */
	cyl->next = hemi1;
	hemi1->next = hemi2;
	hemi2->next = NULL;

	/* Store the origin point, radius and field strength for cylinder. */
	V3Copy(&cyl->loc, pt1);
	cyl->rad = radius;
	cyl->field = field;

	/*
	 * Pre-compute constants for the density eq. in standard form.
	 * Radii that are too small should be checked for during parse.
	 */
	cyl->rsq = cyl->rad * cyl->rad;
	cyl->r2 = -( 2.0 * cyl->field) / cyl->rsq;
	cyl->r4 = cyl->field / (cyl->rsq * cyl->rsq);

	/* Get offset vector of cylinder from the given end point. */
	V3Sub(&cyl->d, pt2, &cyl->loc);

	/*
	 * Get cylinder length squared & length, while we're at it...
	 * Zero length offset vectors should be checked for during parse.
	 */
	cyl->lsq = V3Dot(&cyl->d, &cyl->d);
	cyl->len = sqrt(cyl->lsq);
	V3Copy(&cyl->dir, &cyl->d);
	V3Normalize(&cyl->dir);

	/* Get "d" coeffs. for planes at cylinder ends. */
	cyl->d1 = -V3Dot(&cyl->dir, &cyl->loc);
	cyl->d2 = -V3Dot(&cyl->dir, pt2);

	/* Precompute location dot offset_vector constant. */
	cyl->l_dot_d = V3Dot(&cyl->loc, &cyl->d);

	cyl->type = BLOB_CYLINDER;

	/* Set up the hemispheres for the ends of the cylinder. */
	V3Copy(&hemi1->loc, &cyl->loc);
	V3Sub(&hemi1->dir, pt2, &hemi1->loc);
	V3Normalize(&hemi1->dir);
	hemi1->rad = cyl->rad;
	hemi1->rsq = cyl->rsq;
	hemi1->field = cyl->field;
	hemi1->r2 = cyl->r2;
	hemi1->r4 = cyl->r4;
	hemi1->type = BLOB_HEMISPHERE;

	V3Copy(&hemi2->loc, pt2);
	V3Sub(&hemi2->dir, &cyl->loc, &hemi2->loc);
	V3Normalize(&hemi2->dir);
	hemi2->rad = cyl->rad;
	hemi2->rsq = cyl->rsq;
	hemi2->field = cyl->field;
	hemi2->r2 = cyl->r2;
	hemi2->r4 = cyl->r4;
	hemi2->type = BLOB_HEMISPHERE;

	/*
	 * Finally, add the three new elements that make up the cylinder
	 * element to the blob.
	 */
	if (blob->elems != NULL)
	{
		Bloblet *lastbe;
		for (lastbe = blob->elems; lastbe->next != NULL; lastbe = lastbe->next)
			; /* Seek last element added to list. */
		/* Append our new one. */
		lastbe->next = cyl;
	}
	else
		blob->elems = cyl;

	return 1;
}
Ejemplo n.º 14
0
void SetupColorTriangle(ColorTriangleData *tri)
{
	Vec3 V1, V2, N;
	double len;
	int i;

	/* Compute plane normal. */
	V1.x = tri->pts[3] - tri->pts[0];
	V2.x = tri->pts[6] - tri->pts[0];
	V1.y = tri->pts[4] - tri->pts[1];
	V2.y = tri->pts[7] - tri->pts[1];
	V1.z = tri->pts[5] - tri->pts[2];
	V2.z = tri->pts[8] - tri->pts[2];

	V3Cross(&N, &V1, &V2);
	V3Normalize(&N);
	tri->pnorm[0] = (float)N.x;
	tri->pnorm[1] = (float)N.y;
	tri->pnorm[2] = (float)N.z;

	/* Normalize the vertex normals. */
	for(i = 0; i < 9; i += 3)
	{
		if((tri->norms[i] * N.x +
        tri->norms[i+1] * N.y +
        tri->norms[i+2] * N.z) < 0.0)
		{
			tri->norms[i] = - tri->norms[i];
			tri->norms[i+1] = - tri->norms[i+1];
			tri->norms[i+2] = - tri->norms[i+2];
		}

		len = sqrt(tri->norms[i] * tri->norms[i] +
      tri->norms[i+1] * tri->norms[i+1] +
      tri->norms[i+2] * tri->norms[i+2]);
		if(len > EPSILON)
		{
			tri->norms[i] /= (float)len;
			tri->norms[i+1] /= (float)len;
			tri->norms[i+2] /= (float)len;
		}
		else   /* Use the plane normal for bad vertex normals. */
		{
			tri->norms[i] = (float)N.x;
			tri->norms[i+1] = (float)N.y;
			tri->norms[i+2] = (float)N.z;
		}
	}

	/* Determine axis of greatest projection. */
	if(fabs(N.x) > fabs(N.z))
	{
		if(fabs(N.x) > fabs(N.y))
			tri->axis = X_AXIS;
		else if(fabs(N.y) > fabs(N.z))
			tri->axis = Y_AXIS;
		else
			tri->axis = Z_AXIS;
	}
	else if(fabs(N.y) > fabs(N.z))
		tri->axis = Y_AXIS;
	else
		tri->axis = Z_AXIS;
}
Ejemplo n.º 15
0
void CalcNormalColorTriangle(Object *obj, Vec3 *P, Vec3 *N)
{
	ColorTriangleData *tri = obj->data.colortri;
	double area, a1, a2, a3, u, v;
	float *P1, *P2, *P3;
	float *N1, *N2, *N3;
	int A, B;

	/*
	 * Project the triangle vertices to the 2D plane
	 * that is most perpendicular to the plane normal.
	 */
	switch(tri->axis)
	{
		case X_AXIS:
			A = 1;
			B = 2;
			u = P->y;
			v = P->z;
			break;
		case Y_AXIS:
			A = 0;
			B = 2;
			u = P->x;
			v = P->z;
			break;
		default:  /* Z_AXIS */
			A = 0;
			B = 1;
			u = P->x;
			v = P->y;
			break;
	}

	P1 = tri->pts;
	P2 = &tri->pts[3];
	P3 = &tri->pts[6];

	/* Determine barycentric coordinates of point... */
	area = ColorTriangleArea(P1[A], P1[B], P2[A], P2[B], P3[A], P3[B]);
	a1 =   ColorTriangleArea(u, v, P2[A], P2[B], P3[A], P3[B]) / area;
	a2 =   ColorTriangleArea(P1[A], P1[B], u, v, P3[A], P3[B]) / area;
	a3 =   1.0 - a1 - a2;

	/*
	 * ...and use them to interpolate between the vertex normals
	 * to get the real normal and likewise for the vertex colors.
	 */
	N1 = tri->norms;
	N2 = &tri->norms[3];
	N3 = &tri->norms[6];
	N->x = N1[0] * a1 + N2[0] * a2 + N3[0] * a3;
	N->y = N1[1] * a1 + N2[1] * a2 + N3[1] * a3;
	N->z = N1[2] * a1 + N2[2] * a2 + N3[2] * a3;
	V3Normalize(N);

	N1 = tri->colors;
	N2 = &tri->colors[3];
	N3 = &tri->colors[6];
	tri->r = (float)(N1[0] * a1 + N2[0] * a2 + N3[0] * a3);
	tri->g = (float)(N1[1] * a1 + N2[1] * a2 + N3[1] * a3);
	tri->b = (float)(N1[2] * a1 + N2[2] * a2 + N3[2] * a3);
}
Ejemplo n.º 16
0
void eval_vnorm(Expr *expr)
{
	expr->l->fn(expr->l);
	V3Copy(&expr->v, &expr->l->v);
	V3Normalize(&expr->v);
}
Ejemplo n.º 17
0
Archivo: Blob.c Proyecto: oleavitt/gem
Object *Ray_MakeBlob(PARAMS *par)
{
	Object *obj;
	int token, num_elems, i;
	PARAMS *p;
	BlobData *b;
	Bloblet *be, *new_be, *hemi1, *hemi2, *cyl;
	static Vec3 pt;


	if((obj = NewObject()) == NULL)
		return NULL;

	/* evaluate parameters */
	p = par;
	while(1)
	{
		Eval_Params(p);
		for(i = p->more; i >= 0; i--)
			p = p->next;
		if(p == NULL)
			break;
		p = p->next;   /* skip element type delimiter */
	}

	/* Allocate the main blob data structure... */
	b = (BlobData *)Malloc(sizeof(BlobData));
	b->nrefs = 1;

	/* Get threshold... */
	b->threshold = par->V.x;
	b->solver = 0;
	b->bound = NULL;

	/* Get blob elements... */
	be = NULL;
	num_elems = 0;
	while((par = par->next) != NULL)
	{
		token = par->type;
		/* Get blob element... */
		switch(token)
		{
			case BLOB_SPHERE:
			case BLOB_PLANE:
			case BLOB_CYLINDER:
				for(i = 0; i < 3; i++)
				{
					/* Allocate a "Bloblet" structure. */
					new_be = (Bloblet *)Malloc(sizeof(Bloblet));
					new_be->next = NULL;
					new_be->field = 1.0; /* Default field strength, if not given. */
					if(be == NULL)  /* First one, start the list. */
					{
						be = new_be;
						b->elems = be;
					}
					else   /* Add to the list. */
					{
						be->next = new_be;
						be = be->next;
					}
					num_elems++;

					if(token != BLOB_CYLINDER)
						break;

					/* Save references to the hemisphere sub-elements for cylinder. */
					if(i == 0) cyl = new_be;
					else if(i == 1) hemi1 = new_be;
					else hemi2 = new_be;
				}
				par = par->next;
				break;
			default:
				break;
		}

		/* Get parameters... */
		switch(token)
		{
			case BLOB_SPHERE:
				V3Copy(&be->loc, &par->V);
				par = par->next;
				be->rad = par->V.x;
				if(par->more) /* Optional field strength was specified, also. */
				{
					par = par->next;
					be->field = par->V.x;
				}

				/* Pre-compute constants for the density eq. in standard form. */
				/* Radii that are too small shoud be checked for during parse. */
				be->rsq = be->rad * be->rad;
				be->r2 = - (2.0 * be->field) / be->rsq;
				be->r4 = be->field / (be->rsq * be->rsq);
				be->type = BLOB_SPHERE;
				continue;

			case BLOB_PLANE:
				V3Copy(&be->loc, &par->V);
				par = par->next;
				V3Copy(&be->dir, &par->V);
				par = par->next;
				be->rad = par->V.x;
				if(par->more) /* Optional field strength was specified, also. */
				{
					par = par->next;
					be->field = par->V.x;
				}

				/* Normalize the normal vector. */
				/* Invalid normals should be checked for during parse. */
				V3Normalize(&be->dir);

				/* Get "d" coeff. for plane that bounds plane's interval. */
				pt.x = be->dir.x * be->rad;
				pt.y = be->dir.y * be->rad;
				pt.z = be->dir.z * be->rad;
				be->d1 = -V3Dot(&be->dir, &pt);

				/* Pre-compute constants for the density eq. in standard form. */
				/* Radii that are too small shoud be checked for during parse. */
				be->rsq = be->rad * be->rad;
				be->r2 = - (2.0 * be->field) / be->rsq;
				be->r4 = be->field / (be->rsq * be->rsq);
				be->type = BLOB_PLANE;
				continue;

			case BLOB_CYLINDER:
				V3Copy(&cyl->loc, &par->V);
				par = par->next;
				V3Copy(&pt, &par->V);   /* end point for cylinder */
				par = par->next;
				cyl->rad = par->V.x;
				if(par->more) /* Optional field strength was specified, also. */
				{
					par = par->next;
					cyl->field = par->V.x;
				}

				/* Pre-compute constants for the density eq. in standard form. */
				/* Radii that are too small shoud be checked for during parse. */
				cyl->rsq = cyl->rad * cyl->rad;
				cyl->r2 = -( 2.0 * cyl->field) / cyl->rsq;
				cyl->r4 = cyl->field / (cyl->rsq * cyl->rsq);

				/* Get offset vector of cylinder. */
				V3Sub(&cyl->d, &pt, &cyl->loc);
				/* Get cylinder length squared & length, while we're at it... */
				/* Zero length offset vectors shoud be checked for during parse. */
				cyl->lsq = V3Dot(&cyl->d, &cyl->d);
				cyl->len = sqrt(cyl->lsq);
				V3Copy(&cyl->dir, &cyl->d);
				V3Normalize(&cyl->dir);

				/* Get "d" coeffs. for planes at cylinder ends. */
				cyl->d1 = -V3Dot(&cyl->dir, &cyl->loc);
				cyl->d2 = -V3Dot(&cyl->dir, &pt);

				/* Precompute location dot offset_vector constant. */
				cyl->l_dot_d = V3Dot(&cyl->loc, &cyl->d);

				cyl->type = BLOB_CYLINDER;

				/* Set up the hemispheres for the ends of the cylinder. */
				V3Copy(&hemi1->loc, &cyl->loc);
				V3Sub(&hemi1->dir, &pt, &hemi1->loc);
				V3Normalize(&hemi1->dir);
				hemi1->rad = cyl->rad;
				hemi1->rsq = cyl->rsq;
				hemi1->field = cyl->field;
				hemi1->r2 = cyl->r2;
				hemi1->r4 = cyl->r4;
				hemi1->type = BLOB_HEMISPHERE;

				V3Copy(&hemi2->loc, &pt);
				V3Sub(&hemi2->dir, &cyl->loc, &hemi2->loc);
				V3Normalize(&hemi2->dir);
				hemi2->rad = cyl->rad;
				hemi2->rsq = cyl->rsq;
				hemi2->field = cyl->field;
				hemi2->r2 = cyl->r2;
				hemi2->r4 = cyl->r4;
				hemi2->type = BLOB_HEMISPHERE;
				continue;

			default:
				break;
		}
		break;
	}

	/*
	 * Blobs must have at least one element, this should be checked
	 * for during parse.
	 */
	/* Some assembly required... */
	b->hits = (BlobHit **)Malloc(sizeof(BlobHit *) * num_elems * 2);
	for (i = 0; i < num_elems * 2; i++)
		b->hits[i] = (BlobHit *)Malloc(sizeof(BlobHit));

	obj->data.blob = b;
	obj->procs = &blob_procs;

	return obj;
}
Ejemplo n.º 18
0
parg_mesh* parg_mesh_torus(int slices, int stacks, float major, float minor)
{
    parg_mesh* surf = malloc(sizeof(struct parg_mesh_s));
    float dphi = PARG_TWOPI / stacks;
    float dtheta = PARG_TWOPI / slices;
    int vertexCount = slices * stacks * 3;
    int vertexStride = sizeof(float) * 3;
    surf->coords =
        parg_buffer_alloc(vertexCount * vertexStride, PARG_GPU_ARRAY);
    surf->uvs = 0;
    Point3* position = (Point3*) parg_buffer_lock(surf->coords, PARG_WRITE);
    for (int slice = 0; slice < slices; slice++) {
        float theta = slice * dtheta;
        for (int stack = 0; stack < stacks; stack++) {
            float phi = stack * dphi;
            *position++ = torus_fn(major, minor, phi, theta);
        }
    }
    parg_buffer_unlock(surf->coords);

    surf->normals =
        parg_buffer_alloc(vertexCount * vertexStride, PARG_GPU_ARRAY);
    Vector3* normal = (Vector3*) parg_buffer_lock(surf->normals, PARG_WRITE);
    for (int slice = 0; slice < slices; slice++) {
        float theta = slice * dtheta;
        for (int stack = 0; stack < stacks; stack++) {
            float phi = stack * dphi;
            Point3 p = torus_fn(major, minor, phi, theta);
            Point3 p1 = torus_fn(major, minor, phi, theta + 0.01);
            Point3 p2 = torus_fn(major, minor, phi + 0.01, theta);
            Vector3 du = P3Sub(p2, p);
            Vector3 dv = P3Sub(p1, p);
            *normal = V3Normalize(V3Cross(du, dv));
            ++normal;
        }
    }
    parg_buffer_unlock(surf->normals);

    surf->ntriangles = slices * stacks * 2;
    int indexCount = surf->ntriangles * 3;
    surf->indices = parg_buffer_alloc(indexCount * 2, PARG_GPU_ELEMENTS);
    uint16_t* index = (uint16_t*) parg_buffer_lock(surf->indices, PARG_WRITE);
    int v = 0;
    for (int i = 0; i < slices - 1; i++) {
        for (int j = 0; j < stacks; j++) {
            int next = (j + 1) % stacks;
            *index++ = v + next + stacks;
            *index++ = v + next;
            *index++ = v + j;
            *index++ = v + j;
            *index++ = v + j + stacks;
            *index++ = v + next + stacks;
        }
        v += stacks;
    }
    for (int j = 0; j < stacks; j++) {
        int next = (j + 1) % stacks;
        *index++ = next;
        *index++ = v + next;
        *index++ = v + j;
        *index++ = v + j;
        *index++ = j;
        *index++ = next;
    }
    parg_buffer_unlock(surf->indices);
    return surf;
}
void PezRender()
{
    #define Instances 7

    Matrix4 Model[Instances];
    Model[0] = M4MakeRotationY(Globals.Theta);
    Model[1] = M4Mul(M4Mul(
                     M4MakeTranslation((Vector3){0, 0, 0.6}),
                     M4MakeScale(V3MakeFromScalar(0.25))),
                     M4MakeRotationX(Pi/2)
    );
    Model[2] = Model[3] = Model[4] = Model[1];
    Model[1] = M4Mul(M4MakeRotationY(Globals.Theta), Model[1]);
    Model[2] = M4Mul(M4MakeRotationY(Globals.Theta + Pi/2), Model[2]);
    Model[3] = M4Mul(M4MakeRotationY(Globals.Theta - Pi/2), Model[3]);
    Model[4] = M4Mul(M4MakeRotationY(Globals.Theta + Pi), Model[4]);
    Model[5] = M4Mul(M4Mul(
                     M4MakeScale(V3MakeFromScalar(0.5)),
                     M4MakeTranslation((Vector3){0, 1.25, 0})),
                     M4MakeRotationY(-Globals.Theta)
    );
    Model[6] = M4Mul(M4Mul(
                     M4MakeScale(V3MakeFromScalar(0.5)),
                     M4MakeTranslation((Vector3){0, -1.25, 0})),
                     M4MakeRotationY(-Globals.Theta)
    );

    Vector3 LightPosition = {0.5, 0.25, 1.0}; // world space
    Vector3 EyePosition = {0, 0, 1};          // world space

    Matrix4 MVP[Instances];
    Vector3 Lhat[Instances];
    Vector3 Hhat[Instances];
    for (int i = 0; i < Instances; i++) {
        Matrix4 mv = M4Mul(Globals.View, Model[i]);
        MVP[i] = M4Mul(Globals.Projection, mv);
        Matrix3 m = M3Transpose(M4GetUpper3x3(Model[i]));
        Lhat[i] = M3MulV3(m, V3Normalize(LightPosition));    // object space
        Vector3 Eye =  M3MulV3(m, V3Normalize(EyePosition)); // object space
        Hhat[i] = V3Normalize(V3Add(Lhat[i], Eye));
    }

    int instanceCount = Instances;
    MeshPod* mesh = &Globals.Cylinder;

    glBindFramebuffer(GL_FRAMEBUFFER, Globals.FboHandle);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
  
    glUseProgram(Globals.LitProgram);
    glUniform3f(u("SpecularMaterial"), 0.4, 0.4, 0.4);
    glUniform4f(u("FrontMaterial"), 0, 0, 1, 1);
    glUniform4f(u("BackMaterial"), 0.5, 0.5, 0, 1);
    glUniform3fv(u("Hhat"), Instances, &Hhat[0].x);
    glUniform3fv(u("Lhat"), Instances, &Lhat[0].x);
    glUniformMatrix4fv(u("ModelviewProjection"), Instances, 0, (float*) &MVP[0]);

    glBindVertexArray(mesh->FillVao);
    glDrawElementsInstanced(GL_TRIANGLES, mesh->FillIndexCount, GL_UNSIGNED_SHORT, 0, instanceCount);

    glUseProgram(Globals.SimpleProgram);
    glUniform4f(u("Color"), 0, 0, 0, 1);
    glUniformMatrix4fv(u("ModelviewProjection"), Instances, 0, (float*) &MVP[0]);

    glDepthMask(GL_FALSE);
    glBindVertexArray(mesh->LineVao);
    glDrawElementsInstanced(GL_LINES, mesh->LineIndexCount, GL_UNSIGNED_SHORT, 0, instanceCount);
    glDepthMask(GL_TRUE);

    glDisable(GL_DEPTH_TEST);

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glUseProgram(Globals.QuadProgram);
    glBindTexture(GL_TEXTURE_2D, Globals.FboTexture);
    glBindVertexArray(Globals.Grid.FillVao);
    glDrawElements(GL_TRIANGLES, Globals.Grid.FillIndexCount, GL_UNSIGNED_SHORT, 0);

    if (1) {
        glUseProgram(Globals.GridProgram);
        glBindVertexArray(Globals.Grid.LineVao);
        glDrawElements(GL_LINES, Globals.Grid.LineIndexCount, GL_UNSIGNED_SHORT, 0);
    }

    glBindTexture(GL_TEXTURE_2D, 0);
}
Ejemplo n.º 20
0
Archivo: Blob.c Proyecto: oleavitt/gem
void CalcNormalBlob(Object *obj, Vec3 *Q, Vec3 *N)
{
	BlobData *b;
	Bloblet *be;
	double dist, x, y, z, a;
	Vec3 p;

	b = obj->data.blob;

	V3Copy(&p, Q);
	if (obj->T != NULL)
		PointToObject(&p, obj->T);
	V3Zero(N);

	for (be = b->elems; be != NULL; be = be->next)
	{
		x = p.x - be->loc.x;
		y = p.y - be->loc.y;
		z = p.z - be->loc.z;
		if (be->type == BLOB_CYLINDER)
		{
			double t;

			/* get distance of point along cylinder axis from cylinder origin */
			t = x * be->dir.x + y * be->dir.y + z * be->dir.z;
			/* are we within cylinder length? */
			if (t >= 0.0 && t < be->len)  /* yes */
			{
				/* get radius-squared from correponding point along cylinder axis */
				x -= be->dir.x * t;
				y -= be->dir.y * t;
				z -= be->dir.z * t;
				/* If point is outside radius of influence, it doesn't count. */
				if ((dist = x*x + y*y + z*z) >= be->rsq)
					continue;
			}
			else
				continue; /* Outside of cylinder length. */
		}
		else if (be->type == BLOB_PLANE)
		{
			if ((dist = x * be->dir.x + y * be->dir.y + z * be->dir.z)
				>= be->rad)
				continue;
			x = be->dir.x;
			y = be->dir.y;
			z = be->dir.z;
		}
		else   /* Spheres or hemi-spheres. */
		{
			/* If point is outside sphere of influence, it doesn't count. */
			if ((dist = x*x + y*y + z*z) >= be->rsq)
				continue;

			/* See that point is also within the plane if this is a hemisphere. */
			if (be->type == BLOB_HEMISPHERE)
				if ((x * be->dir.x + y * be->dir.y + z * be->dir.z) > 0.0)
					continue;
		}
		/*
		 * Note: Since this is actually the gradient for the inward facing
		 * surface of the density equation(s), we need to flip the sign so
		 * that the normal is pointing out from the blob. The outer surface
		 * of the density equation is "mirrored" on the outside of the
		 * field of influence for the blob element (due to the "W" shape
		 * of the density function) and does not fall within the interval
		 * containing valid blob intersections. These are checked for
		 * and skipped in the intersection tests above.
		 */
		a = - 4.0 * be->r4 * dist - 2.0 * be->r2;
		N->x += x * a;
		N->y += y * a;
		N->z += z * a;
	}

	if (obj->T != NULL)
		NormToWorld(N, obj->T);
	V3Normalize(N);
}