Hi again.

I fixed the issues I mentioned and the snippet now works as intended. Just
compile and run rtexample to check it out.
I'll continue with the next snipped I proposed unless you think I should do
something else instead :P

Mario.



2017-07-27 22:42 GMT+02:00 Mario Meissner <[email protected]>:

> This is great, please keep sharing.  This looks potentially like the
>> beginnings for what a proper material object (see TODO) might end up
>> requiring/using for the typein interface.
>>
>
> Which TODO do you mean?
>
>
>> Some feedback, you should use bu_fgets for portability.  You're also also
>> not using the right format specifier, even though it seems to work (man
>> printf).  Fastf_t is a floating point type so it should be something like
>> %.2lf instead of lld which is for long long integers.
>>
>
> Noted, thank you!
>
>
>> What are your next steps with that code?
>>
>
> First of all make the thing work as is. Then probably print the list to
> check it's storing all the points correctly.
> From there on I'm not really sure. I'll probably leave it as is until we
> know exactly how we're gonna work with these values.
> I'd like to make a little function that, having only axis vectors (since
> it's what we agreed to start off with), returns density values at any given
> point. We can then call this function from rtweight and see if simple
> examples like the box actually return the expected results.
> Would love to get some more goal suggestions from you if you have.
>
> Yep, looks like the right direction.
>>
>
> Glad to hear that.
>
> Cheers!
> Mario.
>
>
/*                     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;

};

int
main(int argc, char **argv)
{
	/* old rtexample code has ben moved to separate function to clean up main */
    //return 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);
	}


}

/* 
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 */
	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) {

			/* If user typed exit we need to exit both loops */
			gets(input); /* get the input. This gets rid of trailing \n and allows to check exit, otherwise load data with sscanf */
			if (!strcmp(input, "exit")) {
				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
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-devel

Reply via email to