Exemplo n.º 1
0
size_t LightTree::recursive_build(std::vector<LightTree::BuildNode>::iterator start, std::vector<LightTree::BuildNode>::iterator end) {
	// Allocate the node
	const size_t me = nodes.size();
	nodes.push_back(Node());

	if ((start + 1) == end) {
		// Leaf node
		const Instance& instance = assembly->instances[start->instance_index];

		nodes[me].is_leaf = true;
		nodes[me].instance_index = start->instance_index;

		// Get bounds
		if (instance.type == Instance::OBJECT) {
			nodes[me].bounds = assembly->instance_bounds(start->instance_index);
		} else if (instance.type == Instance::ASSEMBLY) {
			const Assembly* assmb = assembly->assemblies[instance.data_index].get();
			if (instance.transform_count > 0) {
				auto xstart = assembly->xforms.cbegin() + instance.transform_index;
				auto xend = xstart + instance.transform_count;
				nodes[me].bounds = transform_from(assmb->light_accel.bounds(), xstart, xend);
			} else {
				nodes[me].bounds = assmb->light_accel.bounds();
			}
		}

		// Copy energy
		nodes[me].energy = start->energy;
	} else {
		// Not a leaf node
		nodes[me].is_leaf = false;

		// Create child nodes
		auto split_itr = split_lights(start, end);
		const size_t c1 = recursive_build(start, split_itr);
		const size_t c2 = recursive_build(split_itr, end);
		nodes[me].index1 = c1;
		nodes[me].index2 = c2;

		// Calculate bounds
		nodes[me].bounds = merge(nodes[c1].bounds, nodes[c2].bounds);

		// Calculate energy
		nodes[me].energy = nodes[c1].energy + nodes[c2].energy;
	}

	return me;
}
Exemplo n.º 2
0
Arquivo: atlas.c Projeto: cpence/arcus
arcus_atlas *atlas_from_xml(scew_element *element)
{
    arcus_atlas *atlas;
    scew_list *list, *i;
    int expected_transforms, ii, jj, kk;

    if (!element)
    {
        set_error_string("atlas_from_xml: NULL element");
        return NULL;
    }
    if (strcmp(scew_element_name(element), "atlas") != 0)
    {
        set_error_string("atlas_from_xml: element name != 'atlas'");
        return NULL;
    }
    
    atlas = atlas_create();
    if (!atlas)
        return NULL;
    
    list = scew_element_list_by_name(element, "system");
    if (!list)
    {
        set_error_string("atlas_from_xml: no systems in atlas");
        
        atlas_destroy(atlas);
        return NULL;
    }
    
    for (i = list ; i ; i = scew_list_next(i))
    {
        scew_element *e;
        arcus_system *s;
        
        e = (scew_element *)scew_list_data(i);
        s = system_from_xml(e);
        
        if (!s)
        {
            atlas_destroy(atlas);
            return NULL;
        }
        
        atlas->systems = (arcus_system **)realloc(atlas->systems, (atlas->num_systems + 1) * sizeof(arcus_system *));
        atlas->systems[atlas->num_systems] = s;
        atlas->num_systems++;
    }
    
    // If there's only one system, ignore the transforms
    if (atlas->num_systems == 1)
        return atlas;
    
    // Figure out how many transforms we should have (n choose k, both directions)
    expected_transforms = binomial(atlas->num_systems, 2) * 2;

    // Load transforms
    list = scew_element_list_by_name(element, "transform");
    if (!list)
    {
        set_error_string("atlas_from_xml: no transforms in atlas when expected");
        
        atlas_destroy(atlas);
        return NULL;
    }
    
    if (scew_list_size(list) != expected_transforms)
    {
        set_error_string("atlas_from_xml: wrong number of transforms in atlas");
        
        atlas_destroy(atlas);
        return NULL;
    }
    
    for (i = list ; i ; i = scew_list_next(i))
    {
        scew_element *e;
        arcus_transform *t;
        
        e = (scew_element *)scew_list_data(i);
        t = transform_from_xml(e);
        
        if (!t)
        {
            atlas_destroy(atlas);
            return NULL;
        }
        
        atlas->transforms = (arcus_transform **)realloc(atlas->transforms, (atlas->num_transforms + 1) * sizeof(arcus_transform *));
        atlas->transforms[atlas->num_transforms] = t;
        atlas->num_transforms++;
    }
    
    // Load differential transforms
    list = scew_element_list_by_name(element, "transform_diff");
    if (!list)
    {
        set_error_string("atlas_from_xml: no differential transforms in atlas when expected");
        
        atlas_destroy(atlas);
        return NULL;
    }
    
    if (scew_list_size(list) != expected_transforms)
    {
        set_error_string("atlas_from_xml: wrong number of differential transforms in atlas");
        
        atlas_destroy(atlas);
        return NULL;
    }
    
    for (i = list ; i ; i = scew_list_next(i))
    {
        scew_element *e;
        arcus_transform *t;
        
        e = (scew_element *)scew_list_data(i);
        t = transform_from_xml(e);
        
        if (!t)
        {
            atlas_destroy(atlas);
            return NULL;
        }
        
        atlas->diff_transforms = (arcus_transform **)realloc(atlas->diff_transforms, (atlas->num_diff_transforms + 1) * sizeof(arcus_transform *));
        atlas->diff_transforms[atlas->num_diff_transforms] = t;
        atlas->num_diff_transforms++;
    }
    
    // Check the accuracy and completeness of the transform lists
    for (ii = 0 ; ii < expected_transforms ; ii++)
    {
        arcus_transform *t, *dt;
        int found_t_from = 0, found_t_to = 0;
        int found_dt_from = 0, found_dt_to = 0;
        
        t = atlas->transforms[ii];
        dt = atlas->diff_transforms[ii];
        
        for (jj = 0 ; jj < atlas->num_systems ; jj++)
        {
            if (strcmp(system_id(atlas->systems[jj]), transform_from(t)) == 0)
                found_t_from = 1;
            if (strcmp(system_id(atlas->systems[jj]), transform_from(dt)) == 0)
                found_dt_from = 1;
            if (strcmp(system_id(atlas->systems[jj]), transform_to(t)) == 0)
                found_t_to = 1;
            if (strcmp(system_id(atlas->systems[jj]), transform_to(dt)) == 0)
                found_dt_to = 1;
        }
        
        if (!found_t_from || !found_t_to)
        {
            set_error_string("atlas_from_xml: transform has invalid from/to");
            
            atlas_destroy(atlas);
            return NULL;
        }
        
        if (!found_dt_from || !found_dt_to)
        {
            set_error_string("atlas_from_xml: transform_diff has invalid from/to");
            
            atlas_destroy(atlas);
            return NULL;
        }
    }
    
    for (ii = 0 ; ii < atlas->num_systems ; ii++)
    {
        for (jj = 0 ; jj < atlas->num_systems ; jj++)
        {
            int found_ij = 0, found_ji = 0, found_ij_d = 0, found_ji_d = 0;
            
            if (ii == jj)
                continue;
            
            arcus_system *si, *sj;
            si = atlas->systems[ii];
            sj = atlas->systems[jj];
            
            for (kk = 0 ; kk < expected_transforms ; kk++)
            {
                arcus_transform *t = atlas->transforms[kk];
                
                if (strcmp(system_id(si), transform_from(t)) == 0 &&
                    strcmp(system_id(sj), transform_to(t)) == 0)
                    found_ij = 1;
                else if (strcmp(system_id(sj), transform_from(t)) == 0 &&
                         strcmp(system_id(si), transform_to(t)) == 0)
                    found_ji = 1;
                
                t = atlas->diff_transforms[kk];
                
                if (strcmp(system_id(si), transform_from(t)) == 0 &&
                    strcmp(system_id(sj), transform_to(t)) == 0)
                    found_ij_d = 1;
                else if (strcmp(system_id(sj), transform_from(t)) == 0 &&
                         strcmp(system_id(si), transform_to(t)) == 0)
                    found_ji_d = 1;
            }
            
            if (!found_ij || !found_ji)
            {
                set_error_string("atlas_from_xml: no transforms found for one pair of systems");
                
                atlas_destroy(atlas);
                return NULL;
            }
            
            if (!found_ij_d || !found_ji_d)
            {
                set_error_string("atlas_from_xml: no differential transforms found for one pair of systems");
                
                atlas_destroy(atlas);
                return NULL;
            }
        }
    }
    
    return atlas;
}