HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cvexsample.C
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018
3  * Side Effects Software Inc. All rights reserved.
4  *
5  * Redistribution and use of Houdini Development Kit samples in source and
6  * binary forms, with or without modification, are permitted provided that the
7  * following conditions are met:
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * 2. The name of Side Effects Software may not be used to endorse or
11  * promote products derived from this software without specific prior
12  * written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17  * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
20  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
23  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  *----------------------------------------------------------------------------
26  * Sample of the CVEX interface to call VEX.
27  *
28  * CVEX is most efficient when operating on arrays of data. The interface
29  * allows you to create a VEX function to perform some computation. Instead of
30  * hard-coding the algorithm in your C++ code, you can alter the algorithm by
31  * running different VEX code. It allows flexibility in design of your code.
32  */
33 
34 #include <CVEX/CVEX_Context.h>
35 #include <UT/UT_Vector3.h>
36 
37 namespace HDK_Sample {
38 
39 // This is the array length for the sample program.
40 #define CV_SIZE 8
41 
42 // Static methods to fill input variables to the VEX function
43 static void
44 fillP(UT_Vector3 *P)
45 {
46  int i;
47  fpreal t;
48  for (i = 0; i < CV_SIZE; i++)
49  {
50  t = (fpreal)i / (CV_SIZE-1);
51  P[i].assign(t, SYSsin(t*M_PI), 0);
52  }
53 }
54 
55 static void
56 fillN(UT_Vector3 *N)
57 {
58  int i;
59  for (i = 0; i < CV_SIZE; i++)
60  N[i].assign(0, 1, 0);
61 }
62 
63 static void
64 fillST(fpreal32 *s, fpreal32 *t)
65 {
66  int i;
67  for (i = 0; i < CV_SIZE; i++)
68  {
69  s[i] = (fpreal)i / (CV_SIZE-1);
70  t[i] = 1-s[i];
71  }
72 }
73 
74 //
75 // Convenience methods to print output from the function
76 //
77 static void
78 dumpFloat(const fpreal32 *v, int n)
79 {
80  int i;
81 
82  printf("%g", v[0]);
83  for (i = 1; i < n; i++)
84  printf(", %g", v[i]);
85 }
86 
87 static void
88 dumpVector(const UT_Vector3 *v, int n)
89 {
90  int i;
91  printf("{%g,%g,%g}", v[0].x(), v[0].y(), v[0].z());
92  for (i = 1; i < n; i++)
93  printf(", {%g,%g,%g}", v[i].x(), v[i].y(), v[i].z());
94 }
95 
96 static void
97 dumpValue(CVEX_Value *value)
98 {
99  if (!value || !value->isExport())
100  return;
101  printf("%s = [", (const char *) value->getName());
102  switch (value->getType())
103  {
104  case CVEX_TYPE_FLOAT:
105  dumpFloat((fpreal32 *)value->getRawData(), value->getArraySize());
106  break;
107  case CVEX_TYPE_VECTOR3:
108  dumpVector((UT_Vector3 *)value->getRawData(), value->getArraySize());
109  break;
110  default:
111  printf("No output supported currently\n");
112  }
113  printf("]\n");
114 }
115 
116 static void
117 dumpValueList(const char *label, CVEX_ValueList &list)
118 {
119  int i;
120  CVEX_Value *value;
121  printf("%s:\n", label);
122  for (i = 0; i < list.entries(); i++)
123  {
124  value = list.getValue(i);
125  printf("\t%2d.", i+1);
126  if (value->isExport())
127  printf("export ");
128  switch (value->getType())
129  {
130  case CVEX_TYPE_INTEGER: printf("int"); break;
131  case CVEX_TYPE_FLOAT: printf("float"); break;
132  case CVEX_TYPE_VECTOR3: printf("vector"); break;
133  case CVEX_TYPE_VECTOR4: printf("vector4"); break;
134  case CVEX_TYPE_MATRIX3: printf("matrix3"); break;
135  case CVEX_TYPE_MATRIX4: printf("matrix"); break;
136  case CVEX_TYPE_STRING: printf("string"); break;
137  default: printf("unknown"); break;
138  }
139  printf(" %s[%d]\n", (const char *) value->getName(), value->getArraySize());
140  }
141 }
142 }
143 
144 using namespace HDK_Sample;
145 
146 int
147 main(int argc, char *argv[])
148 {
149  CVEX_Context cvex;
150 
151  // Define storage for the input parameters to the CVEX function. If the
152  // CVEX function accesses these variables by name, we need to make sure
153  // they are initialized. Any parameters which aren't "bound" by inputs,
154  // will be handled by the parameters the user specifies.
155  UT_Vector3 P[CV_SIZE];
156  UT_Vector3 N[CV_SIZE];
157  fpreal32 s[CV_SIZE], t[CV_SIZE];
158  fpreal32 zero[CV_SIZE];
159  int32 seed = 1;
160  CVEX_StringArray map;
161 
162  // When parameters are declared as exports, we can grab the data as
163  // computed by VEX. These buffers are used to store the output of the Cf
164  // and Of export parameters.
165  UT_Vector3 Cf[CV_SIZE];
166  UT_Vector3 Of[CV_SIZE];
167 
168  // Before we load the VEX function, we need to declare which variables are
169  // defined as input parameters. We can do "lazy" assignment, or
170  // pre-computed assignment. Lazy assignment just declares the variable
171  // without specifying its value.
172  //
173  // Declare P, N, s, and t without computing their values.
174  cvex.addInput("P", CVEX_TYPE_VECTOR3, true);
175  cvex.addInput("N", CVEX_TYPE_VECTOR3, true);
176  cvex.addInput("s", CVEX_TYPE_FLOAT, true);
177  cvex.addInput("t", CVEX_TYPE_FLOAT, true);
178 
179  //
180  // Declare parameters which have values automatically assigned. This is
181  // more of a convenience for simple parameters.
182  map.append("Mandril.pic");
183  memset(zero, 0, sizeof(zero));
184  // seed is a "uniform" variable -- it has a single value
185  // zero is a "varying" variable -- it has a different value for each
186  // element of the array. Well, not actually, but it could.
187  // map is a "uniform" variable since there is only one string in the array
188  cvex.addInput("seed", CVEX_TYPE_INTEGER, &seed, 1);
189  cvex.addInput("zero", CVEX_TYPE_FLOAT, zero, CV_SIZE);
190  cvex.addInput("map", map);
191 
192  // Load the VEX function
193  if (!cvex.load(argc-1, argv+1))
194  {
195  fprintf(stderr, "Unable to load cvex function: %s\n", argv[1]);
196  return 1;
197  }
198 
199  // Now that the function is loaded, we can find out all sorts of
200  // information about the function.
201  dumpValueList("Input Parameters", cvex.getInputList());
202  dumpValueList("Output Parameters", cvex.getOutputList());
203 
204  // Now, we need to initialize the variables we declared. But we only have
205  // to do this if the variable was specified in the VEX function.
206  CVEX_Value *Pval, *Nval, *sval, *tval;
207  Pval = cvex.findInput("P", CVEX_TYPE_VECTOR3);
208  Nval = cvex.findInput("N", CVEX_TYPE_VECTOR3);
209  sval = cvex.findInput("s", CVEX_TYPE_FLOAT);
210  tval = cvex.findInput("t", CVEX_TYPE_FLOAT);
211 
212  if (Pval)
213  {
214  fillP(P); // Initialize P
215  Pval->setTypedData(P, CV_SIZE); // Set the parameter value
216  }
217  if (Nval)
218  {
219  fillN(N);
220  Nval->setTypedData(N, CV_SIZE);
221  }
222  if (sval || tval)
223  {
224  fillST(s, t);
225  if (sval) sval->setTypedData(s, CV_SIZE);
226  if (tval) tval->setTypedData(t, CV_SIZE);
227  }
228 
229  // We can also find exported parameters.
230  CVEX_Value *CfVal, *OfVal, *sout, *tout;
231 
232  CfVal = cvex.findOutput("Cf", CVEX_TYPE_VECTOR3);
233  OfVal = cvex.findOutput("Of", CVEX_TYPE_VECTOR3);
234 
235  // When an input parameter (like P, N, s or t) is specified as an export
236  // parameter, CVEX will _not_ modify the data buffer assigned to the input
237  // value.
238  sout = cvex.findOutput("s", CVEX_TYPE_FLOAT);
239  tout = cvex.findOutput("t", CVEX_TYPE_FLOAT);
240 
241  if (!CfVal && !OfVal)
242  fprintf(stderr, "%s doesn't seem to write to Cf or Of\n", argv[1]);
243 
244  if (CfVal)
245  CfVal->setTypedData(Cf, CV_SIZE);
246  if (OfVal)
247  OfVal->setTypedData(Of, CV_SIZE);
248 
249  // To get the output value, you need to grab the output variable and set
250  // its data. You can think of input variables as being "const" for the VEX
251  // function. You can obviously have VEX write to a different buffer, or it
252  // can overwrite the input buffer (like below)
253  if (sout)
254  sout->setTypedData(s, CV_SIZE);
255  if (tout)
256  tout->setTypedData(t, CV_SIZE);
257 
258  // Now, call VEX
259  printf("Calling VEX ----------------------------\n\n");
260  cvex.run(CV_SIZE, false);
261  printf("\n\nFinished VEX ----------------------------\n");
262 
263  // And print out the output values
264  dumpValue(CfVal);
265  dumpValue(OfVal);
266  dumpValue(sout);
267  dumpValue(tout);
268 
269  return 0;
270 }
const CVEX_ValueList & getOutputList() const
Definition: CVEX_Context.h:273
bool isExport() const
Query whether the VEX value is an export (or read-only)
Definition: CVEX_Value.h:61
bool setTypedData(int *data, int array_size)
GLuint GLsizei const GLchar * label
Definition: glcorearb.h:2544
const GLdouble * v
Definition: glcorearb.h:836
CVEX_Type getType() const
Query type of VEX value.
Definition: CVEX_Value.h:58
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:847
List of input or output values for a CVEX_Context.
#define CV_SIZE
Definition: cvexsample.C:40
GLint y
Definition: glcorearb.h:102
void * getRawData()
Definition: CVEX_Value.h:81
const CVEX_Value * getValue(int i) const
Get a value by index.
bool addInput(const UT_StringHolder &name, CVEX_Type type, bool varying)
png_uint_32 i
Definition: png.h:2877
#define M_PI
Definition: ImathPlatform.h:51
Call VEX from C++.
Definition: CVEX_Context.h:147
bool run(int array_size, bool interruptable, CVEX_RunData *rundata=nullptr)
GLdouble n
Definition: glcorearb.h:2007
int main(int argc, char *argv[])
Definition: cvexsample.C:147
const CVEX_Value * findOutput(const UT_StringRef &name, CVEX_Type type) const
Find an output by name/type.
Definition: CVEX_Context.h:277
const UT_StringHolder & getName() const
Query name of VEX value.
Definition: CVEX_Value.h:56
int int32
Definition: SYS_Types.h:34
A class representing a VEX value.
Definition: CVEX_Value.h:50
void assign(T xx=0.0f, T yy=0.0f, T zz=0.0f)
Set the values of the vector components.
Definition: UT_Vector3.h:612
int entries() const
Returns the number of values in the list.
GLsizei const GLfloat * value
Definition: glcorearb.h:823
double fpreal
Definition: SYS_Types.h:269
const CVEX_Value * findInput(const UT_StringRef &name, CVEX_Type type) const
Find an input by name/type.
Definition: CVEX_Context.h:255
CVEX_ValueList & getInputList()
Definition: CVEX_Context.h:251
int getArraySize() const
Definition: CVEX_Value.h:67
GLint GLenum GLint x
Definition: glcorearb.h:408
GA_API const UT_StringHolder N
exint append(void)
Definition: UT_Array.h:95
float fpreal32
Definition: SYS_Types.h:190
bool load(int argc, const char *const argv[])