Search
  • Ziv

VSFX 755 Procedural 3D Shader Programming - Project 1



Using Python and C++ language to generate spheres around the geometry and also create the variables to have the control-ability of the coding.


Down bellow are two main scripts for the functionality.


PlaceSpheresProc.cpp

// PlaceSpheresProc.cpp #include <ri.h> #include <RixInterfaces.h> #include <RiTypesHelper.h> #include <stdio.h> #include <stdlib.h> #include <string.h> // A RiProcedural must implement these functions. This is a fixed requirement. extern "C" { PRMANEXPORT RtPointer ConvertParameters ( RtString paramStr ); PRMANEXPORT RtVoid Subdivide ( RtPointer data, RtFloat detail ); PRMANEXPORT RtVoid Free ( RtPointer data ); } // A custom data structure for defining an arbitrary number of spheres // positioned at locations defined by the "coords" array. typedef struct { RtFloat radius; RtFloat *coords; // an array of x,y,z coordinates RtInt num_coords; } SpheresData; RtFloat randBetween(RtFloat min, RtFloat max); // ---------------------------------------------------- // A RiProcedural required function // ---------------------------------------------------- // RtPointer ConvertParameters(RtString paramStr) { // The strtok() function cannot be used on the paramStr directly because // it modifies the string. long len = strlen(paramStr); // We could directly create a copy of the input paramStr as an array and // use the strcpy(), string copy, function. //char copyStr[len]; //strcpy(copyStr, paramStr); // However, because the paramStr can be very large we allocate memory // from the main memory pool (the "heap") and then perform a block // copy of the contents of paramStr. char *copyStr = (char*)calloc(len + 1, sizeof(char)); memcpy(copyStr, paramStr, len + 1); // Allocate a block of memory to store one instance of SpheresData. SpheresData *dataPtr = (SpheresData*)calloc(1, sizeof(SpheresData)); // Irrespective of how many values are specified by the paramStr we // know the first two values will specify the radius of the spheres // and the number of coordinates that define their 3D locations. sscanf(copyStr, "%f %d", &dataPtr->radius, &dataPtr->num_coords); // Allocate memory to store an array of coordinates RtInt num_floats = dataPtr->num_coords; dataPtr->coords = (RtFloat*)calloc(num_floats, sizeof(RtFloat)); char *strPtr = strtok(copyStr, " "); strPtr = strtok(NULL, " "); // eat the radius value strPtr = strtok(NULL, " "); // eat the num coordinates value long count = 0; while(strPtr) { // Convert each string to a double precision floating point number dataPtr->coords[count] = strtod(strPtr, NULL); count++; strPtr = strtok(NULL, " "); // grab the next part of copyStr. } // Don't forget to free the memory that was allocated for the copied text. free(copyStr); return (RtPointer)dataPtr; } // ---------------------------------------------------- // A RiProcedural required function // ---------------------------------------------------- RtVoid Subdivide(RtPointer data, RtFloat detail) { RtFloat radius = ((SpheresData*)data)->radius; RtInt num_coords = ((SpheresData*)data)->num_coords; RtFloat *coords = ((SpheresData*)data)->coords; for(int n = 0; n < num_coords; n = n + 3) { RtFloat x = coords[n]; RtFloat y = coords[n + 1]; RtFloat z = coords[n + 2]; RiTransformBegin(); RiTranslate(x,y,z); // To assign a color to each sphere un-comment the next two lines // and comment line 92 //RtColor cs[1] = { {randBetween(0,1),randBetween(0,1),randBetween(0,1) } } ; //RiSphere(radius, -radius, radius, 360, "constant color Cs", (RtPointer)cs, RI_NULL); RiSphere(radius, -radius, radius, 360, RI_NULL); RiTransformEnd(); } } // ---------------------------------------------------- // A RiProcedural required function // ---------------------------------------------------- RtVoid Free(RtPointer data) { free(((SpheresData*)data)->coords); free(data); } // ---------------------------------------------------- // Our utility functions begin here // ---------------------------------------------------- RtFloat randBetween(RtFloat min, RtFloat max) { return ((RtFloat)rand()/RAND_MAX) * (max - min) + min; }


pp_place_spheres.py

import maya.cmds as cmds from random import uniform # In the "RenderManProceduralShape->Scripts->Pre Shape Python Script" copy the following text: # import rfm2.api.strings as apistr;import pp_place_spheres_ziv;pp_place_spheres_ziv.setDataStr(apistr.expand_string("<shape>")) def setDataStr(shapeName): tnode = cmds.getAttr(shapeName + '.target') # If the name of the transform node of the target shape has # not been specified we assume the RenderManProgram has been # parented to the polymesh that will "receive" the spheres. if len(tnode) == 0: tnode = cmds.listRelatives(shapeName, parent=True)[0] tnode = cmds.listRelatives(tnode, parent=True)[0] rad = str(cmds.getAttr(shapeName + '.radius')) use_local_space = cmds.getAttr(shapeName + '.use_local_space') # NEW CODE BEGIN___________________________________________ probability = cmds.getAttr(shapeName + '.probability') jitter = cmds.getAttr(shapeName + '.jitter') spread = cmds.getAttr(shapeName + '.particle_spread') num_particles = cmds.getAttr(shapeName + '.num_particles') coords = get_coordinates(tnode, use_local_space) jittered_coords = [] for n in range(0,len(coords), 3 ): possibility = uniform (0,1) if possibility<=probability: original_x = coords[n+0] + uniform(-jitter, jitter) original_y = coords[n+1] + uniform(-jitter, jitter) original_z = coords[n+2] + uniform(-jitter, jitter) x = original_x + uniform(-spread, spread) y = original_y + uniform(-spread, spread) z = original_z + uniform(-spread, spread) jittered_coords.extend( [x,y,z] ) rounded = [] # Reduce precision to 3 decimal places - less text to pass. # NEW CODE END___(note the use of jittered_coords in this loop) for coord in jittered_coords: rounded.append(round(coord,3)) coords_str = " ".join(map(str, rounded)) text = rad + ' ' + str(len(coords)) + ' ' + coords_str cmds.setAttr(shapeName + '.data', text, type='string') # Rreturns a flat list of coords ie. [x0,y0,z0,x1,y1,z1....] def get_coordinates(tnode, useLocalSpace=True): verts = [] shape = cmds.listRelatives(tnode, shapes=True)[0] num_verts = cmds.polyEvaluate(tnode, vertex=True) for n in range(num_verts): vert_str = shape + '.vtx[%d]' % n; vert_pos = cmds.pointPosition(vert_str) verts.extend(vert_pos) return verts

9 views

(912) 572-3743

  • artstation

©2020 by Ziv. Proudly created with Wix.com