Building from patterns convex / concave corners

   3490   9   2
User Avatar
Member
13 posts
Joined: Jan. 2014
Offline
Hello,

Is there any way to input convex / concave assets for corners in the built in "Building from patterns" generator ? It used to be the case in the previous building generator, but I don't see how to do that here.

Thanks a lot

Francis
User Avatar
Member
13 posts
Joined: Jan. 2014
Offline
I would add that I THINK that the corners option for the "building from patterns" presets is broken. When you fill in the box1 with a module name, it shows both right and left corners. Filling in the box 2 does not work.
User Avatar
Member
13 posts
Joined: Jan. 2014
Offline
About the corners, there is a mistake in the code that does not allow for left and right corners to be used.

To correct this, allow modifications on the building generator node, then go inside and look for the "place pieces" node. Go inside it and look for the "grammar_expansion1" node.

In this node, you'll see this
CC_L = _corners[0];
CC_R = _corners[0];

Replace by this
CC_L = _corners[0];
CC_R = _corners[1];

Left and right corners should work properly
Edited by Francis Bievre - Oct. 31, 2022 14:17:35
User Avatar
Member
13 posts
Joined: Jan. 2014
Offline
So I've been trying to modify the building tool to get it to work with convex / concave corners.

I think I'm pretty close, even though my solution is messy, but I started Houdini and Vex like a week ago so ...

I managed to isolate the convex corners, and I want to change their attribute to the right module, but I can't find the proper way to write this in Vex.

I want (in English):
If (@group_concave==1) then "getvalue from attribute A (which is the module name)" and "Use it to read a value from this module" then "give this value to this point in the "module_name" attribute"

I made an image to explain this clearly.

The code I have now is this and does not work. it copies the last value from the "bonjour" attribute, which is "K" in this case.

s[]@_bonjour = uniquevals(1, "prim", "module_conc");

foreach(string yo; s[]@_bonjour) {
   
    
     int _refprim = findattribval(1, "prim", "module_conc", yo, 0 );
     string _conc[] = prim(1, "module_conc", _refprim);
     
     if(@group_concave==1) {
     setpointattrib(0, "module_name", @ptnum, _conc, "set");
    
     }}

Any help would be appreciated. I can share the final set up with you when it works.

Thanks
Edited by Francis Bievre - Oct. 31, 2022 14:17:20

Attachments:
building_tool_help.jpg (483.8 KB)

User Avatar
Member
13 posts
Joined: Jan. 2014
Offline
Ok, I don't know how but I did it :p

The labs building system now works with convex and concave corners.

My code is not very good as I began Houdini and vex a week ago, but here it is anyways for anyone having the same issue in the future.

// get name of concave modules
s[]@_concavenames = uniquevals(1, "prim", "module_conc");

// get name of current floor
s[]@etage = pointattrib(0, "floorpattern", @ptnum, 0);


// LOOP THROUGH EACH CONCAVE MODULE NAME AND PRINT NAMES
foreach(string concavename; s[]@_concavenames) {
   
    
int _refprim = findattribval(1, "prim", "module_conc", concavename, 0 );
     

// GET BASE NODE NUMBER (PRIM)

     foreach(string etage; s[]@etage) {
     int _refprimconc = findattribval(1, "prim", "module_name", etage, 0 );

// PRINT VALUE RETURNED IN "HELLO" ATTRIBUTE TO TEST
i@hello = _refprimconc ;

// REPLACE CORNER MODULE BY CONCAVE
    if(@group_concave==1) {
     
// string value of the concave module for current floor ; last value / number is the primitive number (node where info is)(1=C)

string _concaveA[] = prim(1, "module_conc", _refprimconc); 
string _concaveB[] = prim(1, "module_concave", _refprimconc);


    // TEST NAME RETURNED AND PRINT IN "ConcaveA" Attribute
    setpointattrib(0, "concaveA", @ptnum, _concaveA[0], "set");
    
    // TEST IF CONCAVE MODULE IS PRESENT
    int concavemodulespresent = (_concaveA[0] != "" && _concaveB[1] != "") ? 1 : 0;   
    
    // REPLACE CONVEX BY CONCAVE IF VALUE OF CONCAVEMODULEPRESENT = 1
    if(concavemodulespresent==1) {
    // REPLACE ATTRIBUTE IN "MODULE_NAME" BY OUR CONCAVE MODULE ATTRIBUTE
    setpointattrib(0, "module_name", @ptnum, _concaveA[0], "set");
    setpointattrib(0, "module_name", @ptnum-1, _concaveB[1], "set");
    
    }}}}

byyyyye
Edited by Francis Bievre - Nov. 1, 2022 11:57:43

Attachments:
Capture d’écran 2022-11-01 à 16.52.25.png (3.4 MB)

User Avatar
Member
1 posts
Joined: April 2017
Offline
Hi Francis,

I have been digging into building generator then I encountered convex, concave corner problem.
That was when I found your approach to solve this.
Thank you so much for dealing with this issue, it is mind blowing that you did it in a matter of a week of learning houdini!

I tried the method you mentioned here.

However I am unable to replicate the same result.
Do you possibly have some bandwidth to explain more or share the hip file by any chance?

Thank you so much for your dedication, and I am looking forward to hearing from you.
Edited by Kosuke - Jan. 20, 2023 19:27:26
User Avatar
Member
18 posts
Joined: Feb. 2013
Offline
@Kosuke @Francis

Hi gents, I'm also looking at the corners feature , Francis where does your code fix get placed? inside the attributewrangle2?

Thanks!
User Avatar
Member
13 posts
Joined: Jan. 2014
Offline
Hey, I don't remember exactly what I did sorry, but the solution above was not right. It replaced corners alright but didn't take into account the relative sizes of corners. Found a new one, much simpler since then.

If you want to trace my steps, what you need to do is :
- create a concave input (besides the corners input) on the building utility node
- into that node, there is a wrangle node defining variables, add concave variables, same way as corners variables are currently added
- into the building generator > place pieces node, add a tree finding out if a corner is concave or convex, write the answer into a point attribute, then convert it to a primitive attribute
- into the grammar expansion node, which is the node defining which point is what, edit the code to replace corners by concave corners if a segment (i.e prim) has a concave attribute. The segments are read from 1 to XXX so if segment 1 is concave and not segment 0, you know which corners are concave, and which are not. In this case, a few if statements should do the trick.

Here is my current code for that node. Please note that it won't work for you, as it uses variables I created as specified above. You should replace my variables by yours.

+ what I've done so far with the tool : https://www.youtube.com/watch?v=Z6ImSSJe9nQ [www.youtube.com]

float seed = chf("seed");

f@__length = primintrinsic(0, "measuredperimeter", @primnum);

string pattern = chs("pattern");
string CC_L = chs("cc_l");
string CC_R = chs("cc_r");
string CONC_L = chs("cc_l");
string CONC_R = chs("cc_r");

string GetRandomModule(string input; float seed) {
    // Gathering data per module
    int __refpt= findattribval(1, "point", "name", input, 0);
    string _variations[] = point(1, "variations", __refpt);
    float _variationsweights[] = point(1, "weights", __refpt);
    return _variations[sample_discrete(_variationsweights, rand(seed))];

}



if (chi("orientation") == 0) {
        
        s@name = GetRandomModule(s@name, seed * 482824);
        s@conc = GetRandomModule(s@concaveA, seed * 482824);
        int lookup = findattribval(1, "point", "name", s@name, 0);
        i@lookupname = lookup ;
        pattern = point(1, "expanded_form", lookup);
        
        string _corners[] = point(1, "corners", lookup);
        string _concaves[] = point(1, "concave", lookup);
    
        CC_L = _corners[0];
        CC_R = _corners[1];
        

        
        s@CC_R = CC_R ;
        
        
        // ajouter une condition d'appartenance au groupe concave
        CONC_L = _concaves[0];
        CONC_R = _concaves[1];
        
        s@CONC_R = CONC_R ;
        s@CONC_L = CONC_L ;
        
        //Test if previous segement is concave
i@prev_seg = inprimgroup(0, "concavePRIM", @primnum-1);
i@curr_seg = inprimgroup(0, "concavePRIM", @primnum);
i@next_seg = inprimgroup(0, "concavePRIM", @primnum+1);

f@concave_test = @prev_seg + @next_seg + @curr_seg ;

i@replace_L = @concave_test-@next_seg ;
i@replace_R = @concave_test-@prev_seg ;
//f@replace_L = @concave_test ;
         
        
       


    
        
}




s[]@__segments[0] = CC_L;
 // replace module by LEFT CONCAVE
             
               if ( @replace_L == 2) { s[]@__segments[0] = CONC_L ; }

//Test if previous segement is concave
i@prev_seg = inprimgroup(0, "concavePRIM", @primnum-1);
i@curr_seg = inprimgroup(0, "concavePRIM", @primnum);






i[]@__repeatable[0] = 0;
i[]@__corner;

int cornermodulespresent = (CC_L != "" && CC_R != "") ? 1 : 0;
int segmentindex = (cornermodulespresent) ? 1 : 0;
int repeat = 0;
string prevmodule = "";


for (int i = 0; i<len(pattern); i++) {
    string _token = pattern[i];

    if (_token == "<") {
        if (prevmodule != "" && prevmodule != ">")
            segmentindex++;

        repeat = 1;

    } else if (_token == ">") {
        segmentindex++;
        repeat = 0;
        
    } else {
        s@__segments[segmentindex] += _token;
        i@__repeatable[segmentindex] = repeat;
        
    }
    prevmodule = _token;
}

// Expand any expressions
foreach (int _index; string segment; s[]@__segments){
    
    string _segmentstack = "";
    string _segmentsubstack = "";
    prevmodule = "";

    for (int i = 0; i<len(segment); i++) {
        string _token = segment[i];

        if (_token == "[") {
            _segmentstack += _segmentsubstack;
            _segmentsubstack = "";

        } else if (_token == "]") {
            string _nexttoken = segment[clamp(i+1, 0, len(segment))];
            
            
            if (isdigit(_nexttoken) == 1) {
                string _out = "";

                for (int j=0; j < atoi(_nexttoken); j++) 
                    _out += "-"+_segmentsubstack;

                _segmentstack += _out;
                _segmentsubstack = "";

            }

        } else {
            if (prevmodule == "]" && isdigit(_token) == 1 ) {
                
            } else {
                _segmentsubstack += _token;
            }

        }

        prevmodule = _token;
        
    }

    _segmentstack += _segmentsubstack;

    s[]@__segments[_index] = _segmentstack;
}

resize(i[]@__corner, len(s[]@__segments));

if (cornermodulespresent == 1) {
    

// replace module by right corner ir corner module present
    //if (@group_concavePRIM==1) { push(s[]@__segments, CONC_R); }
    
    //if (@group_concavePRIM==0){push(s[]@__segments, CC_R);}
    
    if ( @replace_R != 2) { push(s[]@__segments, CC_R); }
    
    if ( @replace_R == 2) {push(s[]@__segments, CONC_R); }
    
    resize(i[]@__corner, len(s[]@__segments));
    push(i[]@__repeatable, 0);
    i[]@__corner[0] = 1;
    i[]@__corner[-1] = 1;
}
Edited by Francis Bievre - May 15, 2023 10:01:37
User Avatar
Member
1 posts
Joined: Aug. 2021
Offline
May I ask, what did you do with the third point? I don't quite understand what you said

- into the building generator > place pieces node, add a tree finding out if a corner is concave or convex, write the answer into a point attribute, then convert it to a primitive attribute
User Avatar
Member
13 posts
Joined: Jan. 2014
Offline
By memory.

Into the place pieces node, you add a specific section designed to determine if a corner is concave or convex. Sides of the buildings are segments, and segments are divided into points. First and last points of a segment are the corners.

You must determine if these points are convex or concave. That will be a point attribute.

The grammar expansion node uses prims to determine where to put corners (in the code already in place). So you convert your point attribute (convex / concave) into a prim attribute and feed that info into the wrangle node (grammar expansion). You then use it to determine what module goes where.
  • Quick Links