Hey Sean!
Hope you're enjoying your trip!

A few days back I commented out some code to make a simplex example work.
Now I brought the changes back in. The same example now works on the full
version as well.

My next goal will be to set up a better test case with 4 points.
I also am moving over to my own source files and reset rtexample to the
original. For now I attach the rtexample version of todays work, but from
tomorrow onwards I will send the new clean files.

I'm not sure what the next best goal to work on would be. I'll try to code
some more snippets that might come in handy later. We will need to resume
our discussion on how to support more complex situations like the ones I
sent a few weeks back, and how to handle contributions based on how close
to the original vector we are (instead of just taking average). Might send
some more drawn examples to keep the discussion up.

Stay safe!
Mario.

2017-08-03 17:33 GMT+02:00 Mario Meissner <mr.rash....@gmail.com>:

> Hi!
> I also now added a curve to the blade by intersecting it with a stretched
> out sphere. I considered various options but this one ended up being my
> favorite.
> Am not sure why the resolution of the sphere is so low, I can see the
> polygons if I render it. Can I change that?
>
> I'm guessing you're on a trip again, so I will just try to continue
> working on the density() function, putting some of the stuff I commented
> out back in.
> Specifically, I want to store all the vectors we make into a list. How
> many of theses vectors we need to make and how, can be decided later on.
> For now I assume we just make vectors from all points to the first one.
> Will try to make a simple 4 point (origin and the three axis directions)
> example work.
>
>
> Mario.
>
> 2017-07-31 19:12 GMT+02:00 Mario Meissner <mr.rash....@gmail.com>:
>
>> Hello Sean!
>>
>> As you suggested, I reverted some of the changes I made (or rather, I
>> commented them out and used temporary variables instead). I'm proud to
>> announce that the situation I attach as pdf-sketch here, now works as
>> expected in code.
>> Giving no points and only one point works too. Also attached is a
>> screenshot of the output.
>>
>> Basically, if we provide two points I draw a vector and use the
>> orthogonal projection to take a coefficient (proportion) value that I use
>> to calculate the contribution of the vector.
>> If only one point is given it means homogeneous density and so we just
>> automatically return that points density value.
>> If no points are given we add one default point with a default density
>> value at 0,0,0 that works just like the case above.
>>
>> I understand that this is still not a finished goal but what other goals
>> would you suggest to do? I need one as fallback while waiting for feedback
>> on the main goals. Curving out the blade is one of them.
>> Mario.
>>
>>
>> 2017-07-31 1:10 GMT+02:00 Christopher Sean Morrison <brl...@mac.com>:
>>
>>>
>>> On Jul 30, 2017, at 12:25 PM, Mario Meissner <mr.rash....@gmail.com>
>>> wrote:
>>>
>>> Hi again!
>>>
>>> Attached goes current state of my new function. I've not even tried to
>>> run it yet as I still need to work on it before expecting anything to work.
>>>
>>>
>>> I encourage you to approach this from a somewhat different development
>>> approach, one feature at a time.
>>>
>>> Looking at your code you’ve obviously done well writing for the big
>>> picture, but you have conditionals with questions on both sides of the
>>> conditional because you’re already working on one of the more harder cases
>>> before getting two simpler cases working.  That lets issues accumulate and
>>> makes it really hard to talk about whether the direction is appropriate or
>>> not, to say nothing of how it complicates answering questions.
>>>
>>> In general terms, it’s the difference between breadth-first and
>>> depth-first coding.  Another word for it is coding “complete”, which
>>> relates to what was mentioned here: http://brlcad.org/wiki/S
>>> ummer_of_Code/Acceptance#Write_complete_code
>>>
>>> However, I would love to know if this is even remotely heading towards
>>> the right direction.
>>> Inside the code are some questions commented out that I may need an
>>> answer to.
>>>
>>>
>>> I’d request you revert the code back a bit to just implementing the very
>>> first step (i.e., no points), and demonstrate it compiling, running,
>>> working.  That will get you through so many pedantic issues.
>>>
>>> That would have weeded out your "fancier way" question (for which the
>>> answer is to see vmath.h, specifcially VSETALL and VINIT_ZERO) and you
>>> would have encountered a critical bug that is currently affecting all point
>>> cases (it will crash on writes to the origin pointer).  It will also make
>>> it a bit more apparent that an origin might not be needed if there are no
>>> points.
>>>
>>> For now I give the function a set of points and from that I build the
>>> vectors. However it makes no sense to recompute the vectors every time we
>>> call the function. How and where should we store the information so that
>>> when asking for density values the function knows where to look at to
>>> compute the result? Some shared structure maybe?
>>>
>>>
>>> That’s jumping ahead. :)
>>>
>>> Although we said we wouldn't yet deal with this, for the sake of
>>> structuring things up correctly I think it's useful to discuss it. If we
>>> have more than two points, would it be a good approach to draw vectors from
>>> the first point to every other point we got? Something like giving the
>>> first point the status of origin so that all other vectors start there?
>>> I've tried to do it this way for now, as you can see in the attached code.
>>>
>>>
>>> I can appreciate that this is conceptually very hard to accept — leaving
>>> these preconceptions to future-you.  “Structuring things up correctly” is
>>> almost certain to be *incorrect* if you jump to the more complex case
>>> without gaining any experience and insight with the simpler cases.  And
>>> reworking complex code on the simpler cases almost inevitably makes their
>>> code far more complex than they need to be as well.
>>>
>>> For example, you question assumes vectors will be needed or used when
>>> you have 3+ points and that’s not certain.  It’s not even 100% certain that
>>> it’s a good way for 2 points, but it seems reasonable.  That uncertainty
>>> will be reduced when 2-points is working and we can consider the structure
>>> implications.  Right now, you don’t even need a structure.
>>>
>>> Cheers!
>>> Sean
>>>
>>>
>>>
>>>
>>> ------------------------------------------------------------
>>> ------------------
>>> Check out the vibrant tech community on one of the world's most
>>> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
>>> _______________________________________________
>>> BRL-CAD Developer mailing list
>>> brlcad-devel@lists.sourceforge.net
>>> https://lists.sourceforge.net/lists/listinfo/brlcad-devel
>>>
>>>
>>
>
/*                     R T E X A M P L E . C
 * BRL-CAD
 *
 * Copyright (c) 2004-2016 United States Government as represented by
 * the U.S. Army Research Laboratory.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this file; see the file named COPYING for more
 * information.
 */
/** @file rt/rtexample.c
 *
 * This is a heavily commented example of a program that uses librt to
 * shoot a single ray at some geometry in a .g database.
 *
 * The primary BRL-CAD ray-tracing API consists of calls to the
 * function rt_shootray().  This function takes a single argument, the
 * address of a data structure called the "application" structure.
 * This data structure contains crucial information, such as the
 * origin and direction of the ray to be traced, what to do if the ray
 * hits geometry, or what to do if it misses everything.  While the
 * application struct is a large and somewhat complex looking, (it is
 * defined in the raytrace.h header) there are really very few items
 * in it which the application programmer must know about. These are:
 *
 *   a_rt_i	The "raytrace instance" obtained via rt_dirbuild()
 *   a_ray	The ray origin and direction to be shot
 *   a_hit	A callback function for when the ray encounters geometry
 *   a_miss	A callback function for when the ray misses everything
 *
 * Most of the work an application performs will be done in the "hit"
 * routine.  This user-supplied routine gets called deep inside the
 * raytracing library via the rt_shootray() function.  It is provided
 * with 3 parameters:
 *
 *   ap		Pointer to the application structure passed to rt_shootray()
 *   PartHeadp	List of ray "partitions" which represent geometry hit
 *   segp	List of ray "segments" that comprised partitions
 *
 * Most applications can ignore the last parameter.  The PartHeadp
 * parameter is a linked-list of "partition" structures (defined in
 * the raytrace.h header).  It is the job of the "hit" routine to
 * process these ray/object intersections to do the work of the
 * application.
 *
 * This file is part of the default compile in source distributions of
 * BRL-CAD and is usually installed or provided via binary and source
 * distributions.  To compile this example from a binary install:
 *
 * cc -I/usr/brlcad/include/brlcad -L/usr/brlcad/lib -o rtexample rtexample.c -lbu -lrt -lm
 *
 * Jump to the START HERE section below for main().
 */

#include "common.h"

#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <string.h>

#include "vmath.h"		/* vector math macros */
#include "raytrace.h"		/* librt interface definitions */

struct density_point {
	struct bu_list l;
	point_t point;
	fastf_t density;

};
fastf_t density(point_t);

struct density_vector {
	struct bu_list l;
	vect_t vector;
	//point_t origin; We may not need if we assume all vectors originate from the first point provided
	fastf_t factor;
};

struct contribution {
	struct bu_list l;
	fastf_t contrib;
	struct density_vector * dvp;
};

int
main(int argc, char **argv)
{
	/* old rtexample code has ben moved to separate function to clean up main */
    //return rtexample();

	/* TEST MAIN FOR DENSITY() */

	point_t origin = { 0, 0, 0 };
	point_t point_a = { 0, 1000, 500 };
	point_t point_b = { 1000, 1000, 500 };
	point_t point_c = { 500, 1000, 1000 };
	point_t point_d = { 500, 1000, 0 };
	point_t point_e = { 666.6666, 333.3333, 1000 };

	bu_log("Density at origin  is %lf Expected 5.0 \n", density(origin));
	bu_log("Density at point a is %lf Expected 5.0 \n", density(point_a));
	bu_log("Density at point b is %lf Expected 10.0 \n", density(point_b));
	bu_log("Density at point c is %lf Expected 7.5 \n", density(point_c));
	bu_log("Density at point d is %lf Expected 7.5 \n", density(point_d));
	bu_log("Density at point e is %lf Expected 8.33 \n", density(point_e));
	
	/* TEST MAIN FOR MODIFIED RTEXAMPLE */
	/*
	struct density_point *dplist = NULL;

	// allocate and initialize your list head
	BU_GET(dplist, struct density_point);
	BU_LIST_INIT(&(dplist->l));

	readDensityPoints(dplist);

	struct density_point *entry;
	bu_log("We loaded the following points:\n");
	for (BU_LIST_FOR(entry, density_point, &(dplist->l))) {
		bu_log("Point [%lf, %lf, %lf] has density: %lf\n", entry->point[0], entry->point[1], entry->point[2], entry->density);
	}
	*/


}

/* Returns the density value associated to the indicated point in space, 
for the material in question. 
For now the function receives an initial set of points but we will need
to talk about how this function gets its initial information to work with. 
*/
fastf_t density(point_t query_point) {
	
	/* Situation:
	- 1x1x1m box
	- Left side has 5g/cm3
	- Right side has 10g/cm3
	*/

	struct density_point * V;
	BU_GET(V, struct density_point);
	V->density = 5.0;
	VSET(V->point, 0.0, 0.0, 0.0);

	struct density_point * A;
	BU_GET(A, struct density_point);
	A->density = 10.0;
	VSET(A->point, 1000.0, 0.0, 0.0);

	struct density_point * B;
	BU_GET(A, struct density_point);
	A->density = 10.0;

	VSET(A->point, 1000.0, 0.0, 0.0);
	struct density_point * dplist;

	BU_GET(dplist, struct density_point);
	BU_LIST_INIT(&(dplist->l));

	/* Comment this out to test results with one point or no points */
	BU_LIST_PUSH(&(dplist->l), A); 
	BU_LIST_PUSH(&(dplist->l), V);
	
	/* When no points provided we use this as fallback value */
	fastf_t DEFAULT_DENSITY = 8.0;
	
	/* Set up density_vector list */
	struct density_vector * dvlist;
	BU_GET(dvlist, struct density_vector);
	BU_LIST_INIT(&(dvlist->l));

	/* This point is the origin for all density_vectors, 
	and holds origin density value of material */
	struct density_point * origin;
	BU_GET(origin, struct density_point);

	/* If point list is empty, no points, we assume homogeneous default density.
	   I set the origin point to default in this case. */
	if (BU_LIST_IS_EMPTY(&(dplist->l))) {
		origin->density = DEFAULT_DENSITY;
		VSETALL(origin->point, 0.0);
		/* dvlist will remain empty */
	}
	else {
		/* If there is at least one point, take first point and make it origin. */
		BU_LIST_POP(density_point, &(dplist->l), origin);

		/* While there are still points, draw a vector from origin to point 
		and store it in list. */
		struct density_vector * new_vect;
		struct density_point * point_iter;
		while (BU_LIST_WHILE(point_iter, density_point, &(dplist->l))) {
			BU_GET(new_vect, struct density_vector);
			VSUB2(new_vect->vector, point_iter->point, origin->point);
			new_vect->factor = point_iter->density / origin->density;
			BU_LIST_PUSH(&(dvlist->l), new_vect);
			BU_LIST_DEQUEUE(&(point_iter->l));
		}
		
	}
	

	/* We draw the vector corresponding to the queried point */
	vect_t query_vector;
	VSUB2(query_vector, query_point, origin->point);

	/* After this, we will always have at least one point, origin.
	If no more points are present, we use this point's value for
	homogeneous density. */
	if (BU_LIST_IS_EMPTY(&(dvlist->l))) {
		return origin->density;
	}
	else {
		
		/* We now dequeue our vector list and fill in the array of projection values */

		vect_t paral_projection; //I need this so VPROJECT doesn't complain?
		vect_t orth_projection; //Orthogonally projected query_vector onto density_vectors
		/* Set up contribution lists */
		struct contribution * contrib_list; 
		BU_GET(contrib_list, struct contribution);
		BU_LIST_INIT(&(contrib_list->l));
		/* Variables for the loop */
		struct density_vector * vect_iter;
		struct contribution * new_contrib;
		fastf_t contrib, scalar_proj, proportion;

		/* Loop through vectors and build contribution list */
		while (BU_LIST_WHILE(vect_iter, density_vector, &(dvlist->l))) {
			VPROJECT(query_vector, vect_iter->vector, orth_projection, paral_projection);
			scalar_proj = MAGNITUDE(orth_projection);
			proportion = scalar_proj / MAGNITUDE(vect_iter->vector);
			BU_GET(new_contrib, struct contribution);
			/* In 'scalar_proj' proportion, our contribution value will be the density of dv,
			which is original * factor. The 'rest' is original density */
			contrib = origin->density * vect_iter->factor * proportion +
				origin->density * (1 - proportion);
			new_contrib->contrib = contrib;
			new_contrib->dvp = vect_iter;
			BU_LIST_PUSH(&(contrib_list->l), new_contrib);
			BU_LIST_DEQUEUE(&(vect_iter->l));
		}
		
		
		/* Now go through contributions and do work on it 
		   For now take average */
		struct contribution * contrib_iter;
		fastf_t acc_contrib = 0.0; //Accumulated contributions (total)
		int numContribs = bu_list_len(&(contrib_list->l)); //Amount of entries
		while (BU_LIST_WHILE(contrib_iter, contribution, &(contrib_list->l))) {
			acc_contrib += contrib_iter->contrib;
			BU_LIST_DEQUEUE(&(contrib_iter->l));
		};
		
		/*DEBUG
		VPRINT("query_vector", query_vector);
		VPRINT("orth_proj", vector_orth_proj);
		bu_log("scalar_proj is %lf \n", scalar_proj);
		bu_log("proportion is %lf \n", proportion);
		*/

		return acc_contrib / numContribs;

	}
	
}


/* 
Reads density points from stdin and stores them into density_point structs
Receives the head of a bu_list of density_point structs
and appends all points generated during the reading session to the list
Returns the number of successfully read points 
*/
int readDensityPoints(struct density_point * dplist_head) {

	/* If we are given no bu_list... */
	if (!BU_LIST_IS_INITIALIZED(&(dplist_head->l))) {
		bu_log("No valid head of bu_list has been provided.\n");
		/* Maybe also check if bu_list is of type density_points? */
	}

	/* Local variables */

	/* I count the number of times I */
	int count = 0;
	struct density_point *entry;
	int correct, reading = 1;
	char input[30];

	/* Outer loop. We come back here whenever user inputs wrong format and until he types exit */
	while (reading) {
		bu_log("Please insert density points in the format: X Y Z density_value (in g/cm3). \n");
		bu_log("Type 'exit' to finish. \n");
		correct = 1;

		/* Inner loop. While user inputs points in correct format we loop here */
		while (correct) {

			bu_fgets(input, 30, stdin);
			//gets(input); 

			/* If user typed exit we need to exit both loops */
			if (!strcmp(input, "exit\n")) {
				bu_log("Exiting...");
				correct = 0; 
				reading = 0;
			}

			/* User didn't type exit */
			else {

				/* Set up new entry */
				BU_GET(entry, struct density_point);
				
				/* If the input is in correct format we load it and continue */
				if (sscanf(input, "%lf %lf %lf %lf", &entry->point[0], &entry->point[1], &entry->point[2], &entry->density) == 4) {
					BU_LIST_PUSH(&(dplist_head->l), &(entry->l));
					count++;
				}

				/* Otherwise we dont load it and jump back to outer loop to print usage again */
				else {
					correct = 0;
				}
			}
		} /* Close inner loop */
	} /* Close outer loop */
	return count;
} /* Close function */




  /**
  * rt_shootray() was told to call this on a hit.
  *
  * This callback routine utilizes the application structure which
  * describes the current state of the raytrace.
  *
  * This callback routine is provided a circular linked list of
  * partitions, each one describing one in and out segment of one
  * region for each region encountered.
  *
  * The 'segs' segment list is unused in this example.
  */
int
hit(struct application *ap, struct partition *PartHeadp, struct seg *UNUSED(segs))
{
	/* iterating over partitions, this will keep track of the current
	* partition we're working on.
	*/
	struct partition *pp;

	/* will serve as a pointer for the entry and exit hitpoints */
	struct hit *hitp;

	/* will serve as a pointer to the solid primitive we hit */
	struct soltab *stp;

	/* will contain surface curvature information at the entry */
	struct curvature cur = RT_CURVATURE_INIT_ZERO;

	/* will contain our hit point coordinate */
	point_t pt;

	/* will contain normal vector where ray enters geometry */
	vect_t inormal;

	/* will contain normal vector where ray exits geometry */
	vect_t onormal;

	/* Since we dont have the structure to query densities yet,
	I define some constants that contain the values */
	const fastf_t INHIT_FACTOR = 0.2;
	const fastf_t OUTHIT_FACTOR = 1;
	const fastf_t MAT_DENSITY = 5;

	/* Area that the ray covers, in mm^2 */
	const int RAY_AREA = 4; //2mm height, 2mm width

							/* iterate over each partition until we get back to the head.
							* each partition corresponds to a specific homogeneous region of
							* material.
							*/
	for (pp = PartHeadp->pt_forw; pp != PartHeadp; pp = pp->pt_forw) {

		/* print the name of the region we hit as well as the name of
		* the primitives encountered on entry and exit.
		*/
		bu_log("\n--- Hit region %s (in %s, out %s)\n",
			pp->pt_regionp->reg_name,
			pp->pt_inseg->seg_stp->st_name,
			pp->pt_outseg->seg_stp->st_name);

		/* entry hit point, so we type less */
		//TODO What exactly does this hitp contain? 
		//Distance from origin of ray where we hit into something?
		hitp = pp->pt_inhit;

		/* construct the actual (entry) hit-point from the ray and the
		* distance to the intersection point (i.e., the 't' value).
		*/
		VJOIN1(pt, ap->a_ray.r_pt, hitp->hit_dist, ap->a_ray.r_dir);

		/* primitive we encountered on entry */
		stp = pp->pt_inseg->seg_stp;

		/* compute the normal vector at the entry point, flipping the
		* normal if necessary.
		*/
		RT_HIT_NORMAL(inormal, hitp, stp, &(ap->a_ray), pp->pt_inflip);

		/* print the entry hit point info */
		rt_pr_hit("  In", hitp);
		VPRINT("  Ipoint", pt);
		VPRINT("  Inormal", inormal);


		/* exit point, so we type less */
		hitp = pp->pt_outhit;

		/* construct the actual (exit) hit-point from the ray and the
		* distance to the intersection point (i.e., the 't' value).
		*/
		VJOIN1(pt, ap->a_ray.r_pt, hitp->hit_dist, ap->a_ray.r_dir);

		/* primitive we exited from */
		stp = pp->pt_outseg->seg_stp;

		/* compute the normal vector at the exit point, flipping the
		* normal if necessary.
		*/
		RT_HIT_NORMAL(onormal, hitp, stp, &(ap->a_ray), pp->pt_outflip);

		/* print the exit hit point info */
		rt_pr_hit("  Out", hitp);
		VPRINT("  Opoint", pt);
		VPRINT("  Onormal", onormal);

		/* Now we compute the total mass this element saw while crossing the region */
		fastf_t mass, volume, length, avg_density;

		/* Here we would query the density, but we use mock constants */
		avg_density = (INHIT_FACTOR + OUTHIT_FACTOR) * MAT_DENSITY / 2;
		length = pp->pt_outhit->hit_dist - pp->pt_inhit->hit_dist;

		//Was in mm, we need cm
		length = length / 10;

		volume = length * RAY_AREA;
		mass = volume * avg_density;
		bu_log("  Segment length: %lld, volume crossed: %lld \n", length, volume);
		bu_log("  Mass the ray saw through this region: %lld g \n", mass);

	}




	return 1;
}


/**
* This is a callback routine that is invoked for every ray that
* entirely misses hitting any geometry.  This function is invoked by
* rt_shootray() if the ray encounters nothing.
*/
int
miss(struct application *UNUSED(ap))
{
	bu_log("missed\n");
	return 0;
}

int rtexample(int argc, char **argv) {
	/* Every application needs one of these.  The "application"
	* structure carries information about how the ray-casting should
	* be performed.  Defined in the raytrace.h header.
	*/
	struct application	ap;

	/* The "raytrace instance" structure contains definitions for
	* librt which are specific to the particular model being
	* processed.  One copy exists for each model.  Defined in
	* the raytrace.h header and is returned by rt_dirbuild().
	*/
	static struct rt_i *rtip;

	/* optional parameter to rt_dirbuild() that can be used to capture
	* a title if the geometry database has one set.
	*/
	char title[1024] = { 0 };

	/* Check for command-line arguments.  Make sure we have at least a
	* geometry file and one geometry object on the command line.
	*/
	if (argc < 3) {
		bu_exit(1, "Usage: %s model.g objects...\n", argv[0]);
	}

	/* Load the specified geometry database (i.e., a ".g" file).
	* rt_dirbuild() returns an "instance" pointer which describes the
	* database to be raytraced.  It also gives you back the title
	* string if you provide a buffer.  This builds a directory of the
	* geometry (i.e., a table of contents) in the file.
	*/
	rtip = rt_dirbuild(argv[1], title, sizeof(title));
	if (rtip == RTI_NULL) {
		bu_exit(2, "Building the database directory for [%s] FAILED\n", argv[1]);
	}

	/* Display the geometry database title obtained during
	* rt_dirbuild if a title is set.
	*/
	if (title[0]) {
		bu_log("Title:\n%s\n", title);
	}

	/* Walk the geometry trees.  Here you identify any objects in the
	* database that you want included in the ray trace by iterating
	* of the object names that were specified on the command-line.
	*/
	while (argc > 2) {
		if (rt_gettree(rtip, argv[2]) < 0)
			bu_log("Loading the geometry for [%s] FAILED\n", argv[2]);
		argc--;
		argv++;
	}

	/* This next call gets the database ready for ray tracing.  This
	* causes some values to be precomputed, sets up space
	* partitioning, computes bounding volumes, etc.
	*/
	rt_prep_parallel(rtip, 1);

	/* initialize all values in application structure to zero */
	RT_APPLICATION_INIT(&ap);

	/* your application uses the raytrace instance containing the
	* geometry we loaded.  this describes what we're shooting at.
	*/
	ap.a_rt_i = rtip;

	/* stop at the first point of intersection or shoot all the way
	* through (defaults to 0 to shoot all the way through).
	*/
	ap.a_onehit = 0;

	/* Set the ray start point and direction rt_shootray() uses these
	* two to determine what ray to fire.  In this case we simply
	* shoot down the z axis toward the origin from 10 meters away.
	*
	* It's worth nothing that librt assumes units of millimeters.
	* All geometry is stored as millimeters regardless of the units
	* set during editing.  There are libbu routines for performing
	* unit conversions if desired.
	*/
	VSET(ap.a_ray.r_pt, 0.0, 0.0, 10000.0);
	VSET(ap.a_ray.r_dir, 0.0, 0.0, -1.0);

	/* Simple debug printing */
	VPRINT("Pnt", ap.a_ray.r_pt);
	VPRINT("Dir", ap.a_ray.r_dir);

	/* This is what callback to perform on a hit. */
	ap.a_hit = hit;

	/* This is what callback to perform on a miss. */
	ap.a_miss = miss;

	/* Shoot the ray. */
	(void)rt_shootray(&ap);

	/* A real application would probably set up another ray and fire
	* again or do something a lot more complex in the callbacks.
	*/

	return 0;
}

//BULIST EXAMPLE
/*
// make bu_list the first element in your structure
struct my_structure {
	struct bu_list l;
	int my_data;
};


// your actual list
struct my_structure *my_list = NULL;

// allocate and initialize your list head
BU_GET(my_list, struct my_structure);
BU_LIST_INIT(&(my_list->l));
my_list->my_data = -1;

// add a new element to your list
struct my_structure *new_entry;
BU_GET(new_entry, struct my_structure);
new_entry->my_data = rand();
BU_LIST_PUSH(&(my_list->l), &(new_entry->l));

// iterate over your list, remove all items
struct my_structure *entry;
while (BU_LIST_WHILE(entry, my_structure, &(my_list->l))) {
	bu_log("Entry value is %d\n", entry->my_data);
	BU_LIST_DEQUEUE(&(entry->l));
	BU_PUT(entry, struct my_structure);
}
BU_PUT(my_list, struct my_structure);

*/

/*
 * Local Variables:
 * mode: C
 * tab-width: 8
 * indent-tabs-mode: t
 * c-file-style: "stroustrup"
 * End:
 * ex: shiftwidth=4 tabstop=8
 */
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
BRL-CAD Developer mailing list
brlcad-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/brlcad-devel

Reply via email to