How to use Clutter.ShaderEffect.set_uniform_value() properly? - clutter

I am trying set a uniform float of a Clutter.ShaderEffect. This works well if floating point Numbers are passed to set_uniform_value(). However, when you pass an integer Number, an OpenGL error (1282, Invalid operation) is thrown. It seems that the implementation assumes in this case that the uniform is actually of type int. Here is a minimal example:
const {Clutter, GObject} = imports.gi;
Clutter.init(null);
let stage = new Clutter.Stage({width: 200, height: 200});
let shader = new Clutter.ShaderEffect({shader_type: Clutter.ShaderType.FRAGMENT_SHADER});
shader.set_shader_source(`
uniform float value;
void main(void) {
cogl_color_out = vec4(value, 0, 0, 1);
}
`);
// This creates the OpenGL Error.
// shader.set_uniform_value('value', 1);
// This works however:
shader.set_uniform_value('value', 0.999);
stage.add_effect(shader);
stage.connect('destroy', () => Clutter.main_quit());
stage.show();
Clutter.main();
So how do I force set_uniform_value() to interpret the value as floating point number? Reading the documentation (https://gjs-docs.gnome.org/clutter6~6_api/clutter.shadereffect#method-set_uniform_value), I would assume that I could pass a GObject.Value - maybe like this:
let value = new GObject.Value();
value.init(GObject.TYPE_FLOAT);
value.set_float(1.0);
shader.set_uniform_value('value', value);
But this yields the error Invalid uniform of type 'GValue' for name 'value'. Maybe I now have a GObject.Value containing a GObject.Value containing a GObject.TYPE_FLOAT?

As of GJS 1.68.0 (GNOME 40), passing a GObject.Value works:
let value = new GObject.Value();
value.init(GObject.TYPE_FLOAT);
value.set_float(1);
shader.set_uniform_value('value', value);

if someone looks for this question, I have the answer:
https://gjs-docs.gnome.org/clutter7~7_api/clutter.shadereffect#method-set_uniform_value value - a GObject.Value GObject.TYPE_FLOAT for float
and in gjs GTK Javascript they have https://gjs-docs.gnome.org/clutter7~7_api/clutter.value_set_shader_float
value_set_shader_float(value,[float]) method - Value must have been initialized using %CLUTTER_TYPE_SHADER_FLOAT.
and in Javascript version of GTK they dont have any way to initialize that CLUTTER_TYPE_SHADER_FLOAT or GObject.TYPE_FLOAT
The solution is:
function make_float(val) {
return Math.floor(val)==val?val+0.000001:val;
}

Related

'withUnsafeBytes' is deprecated warning when passing void* argument to c function in swift 5

I have a library parsing FIT file in swift using an externally provided c library. The parsing function takes as argument a void * data.
To call the function, I was converting the data using data.withUnsafeBytes( { (ptr: UnsafePointer<UInt8>) in ...} to build the argument to the c function and it was working fine.
After the upgrade of Xcode to swift 5, I now get a deprecated warning
'withUnsafeBytes' is deprecated: use withUnsafeBytes<R>(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R instead
I couldn't work out how to fix the code to remove the deprecated warning. The code has been working fine and without warning in swift 4
I tried to change the argument in the closure to take UnsafeRawBufferPointer instead of the UnsafePointer but this resulted in an error in calling the function: Cannot convert 'UnsafeRawBufferPointer' to expected argument type 'UnsafeRawPointer?'
This is a small swift file to show the problem:
import Foundation
// Create sample data (Typically would be read from a file
let data = Data(repeating: 1, count: 10)
data.withUnsafeBytes( { (ptr : UnsafePointer<UInt8>) in
// call the c function with the void* argument
let value = readFITfile(ptr)
print( value )
})
And an example c function
unsigned readFITfile(const void * data){
//Silly example to show it works, just returning the value of pointer as int
//Typically would parse the data and return a structure
return (unsigned)data;
}
I saved a small repo with the above code here https://github.com/roznet/swift2c and the full scale project with the parsing of the file is here https://github.com/roznet/fit-sdk-swift
You have to change the closure argument to UnsafeRawBufferPointer and then take its baseAdress (which is a UnsafeRawPointer?, the Swift equivalent of void * in C):
data.withUnsafeBytes( { (ptr : UnsafeRawBufferPointer) in
let value = readFITfile(ptr.baseAddress)
// ...
})
The Swift compiler can also infer the closure argument type automatically:
data.withUnsafeBytes( { ptr in
let value = readFITfile(ptr.baseAddress)
// ...
})
For more information about this problem, see withUnsafeBytes Data API confusion in the Swift forum.
To get UnsafePointer now you should do something like that
data.withUnsafeBytes { (ptr: UnsafeRawBufferPointer) in
if let ptrAddress = ptr.baseAddress, ptr.count > 0 {
let pointer = ptrAddress.assumingMemoryBound(to: UInt8.self) // here you got UnsafePointer<UInt8>
let value = readFITfile(ptr)
print( value )
} else {
// Here you should provide some error handling if you want ofc
}
}

How to get the class of a VALUE in Ruby C API

I created some classes with Ruby's C API. I want to create a function whose behavior will change depending on the class of the Ruby object.
I tried to use is_a? from Ruby, however, I don't think it's the good way to do this. I checked "Creating Extension Libraries for Ruby" without success. The only direct way to check classes is with the default types.
I have my class "Klass" already created:
VALUE rb_cKlass = rb_define_class("Klass", rb_cObject);
And how I wanted to check if the class is the good one:
VALUE my_function(VALUE self, VALUE my_argument) {
if(rb_check_class(my_argument), rb_cKlass)) {
// do something if my_argument is an instance of Klass
} else {
return Qnil;
}
}
Is there a way to do this?
I came across this recently, and used the RBASIC_CLASS macro, but was getting segfaults in certain scenarios for some unexplained reason.
After scanning through ruby.h, I found the CLASS_OF macro, which returns the class as VALUE of a given object.
VALUE obj = INT2NUM(10);
VALUE klass = CLASS_OF(obj); // rb_cInteger
Using Ruby 2.5
Every ruby object is internally represented by RObject struct (I will copy the source here for the sake of future readers):
struct RObject {
struct RBasic basic;
union {
struct {
uint32_t numiv;
VALUE *ivptr;
void *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */
} heap;
VALUE ary[ROBJECT_EMBED_LEN_MAX];
} as;
};
The very first member, RBasic, defines the class:
struct RBasic {
VALUE flags;
const VALUE klass;
}
To get an access to RBasic metadata of anything, one might use RBASIC macro:
RBASIC(my_argument)
To get the class directly, one might use RBASIC_CLASS macro:
RBASIC_CLASS(my_argument)
If you want to stay close to the is_a? Ruby fashion (i.e. check if any of the ancestors is the expected class), you could directly use the C implementation of is_a?, rb_obj_is_kind_of:
rb_obj_is_kind_of(my_argument, rb_cKlass) // Qtrue OR Qfalse
And since Qfalse == 0, you can just use that method as a condition:
VALUE my_function(VALUE self, VALUE my_argument) {
if(rb_obj_is_kind_of(my_argument, rb_cKlass)) {
// do something if my_argument is an instance of Klass
} else {
return Qnil;
}
}
To find this method, just check Object#is_a? documentation and click to toggle source, you'll see the C implementation if it is a C function (hence this will work for most of the standard lib).

R, Integrate at each point of array

I'm stuck with computing the integral at each point of an array. The idea is first to create a function ("Integrand"). Then, create a second function ("MyConvolve") that computes the necessary integral.
Here's what I did up to now:
Integrand = function(s,x)
{ 1/4*(abs(x-s)<=1)*(abs(s)<=1) }
MyConvolve = function(func,data)
{ return( integrate(func, lower=-Inf, upper=Inf, data) ) }
Now, running the code with some array, I get an error message:
SomeMatrix = replicate(10, rnorm(10))
MyConvolve(Integrand, SomeMatrix)
Which ends up with the following error message:
Error in integrate(func, lower = -Inf, upper = Inf, data) :
evaluation of function gave a result of wrong length
I already tried vectorizing the function, but still ended up with error messages.
Thank you very much for your help!
I am not sure I understand what you are trying to compute,
but if you want to evaluate MyConvolve(Integrand,s),
where s takes all the values in SomeMatrix,
then apply is sufficient.
sapply( SomeMatrix, function(s) MyConvolve( Integrand, s )$value )
However, the dimensions of the matrix are lost.
You can recover them as follows:
result <- SomeMatrix
result[] <- sapply( SomeMatrix, function(s) MyConvolve( Integrand, s )$value )

Scope Issue: double array not accessible in if statement

I have a class method that is supposed to take an object and populate a few values in place. This is at the stage of functional demonstration, so the implementation will be better later. right now I just would like this to work.
In the code below, the districtID integer is successfully passed to the if statements. The rgb double array does not make it into the if statement scope. The values set at initialization make it all the way to the districtPoint.color without getting set inside the if statement.
the code below will not compile as is. I would like to know how to get the rgb variable to be visible within the if statement scope.
(note: I tried the naive solution of initializing the variables within the if statement. This clears the error, but doesn't let the new rgb variables out of the if scope)
// This method populates properties
+(void)setContantPropertiesForID:(DistrictPoint *)districtPoint
{
int districtID = [districtPoint.districtID intValue];
double rgb[3] = {0,0,0};
if (districtID == 1) {
districtPoint.title = #"District 1";
rgb = {1.0,0.0,0.0}; // error is expected expression
} else if (districtID == 2) {
districtPoint.title = #"District 1";
rgb = {0.0,1.0,0.0};
} else if (districtID == 3) {
districtPoint.title = #"District 1";
rgb = {0.0,0.0,1.0};
} else {
districtPoint.title = nil;
rgb = {1.0,1.0,1.0}; // error condition
}
districtPoint.color = [UIColor colorWithRed:rgb[0] green:rgb[1] blue:rgb[2] alpha:0.5];
}
This has nothing to do with the if statement. You can use the curly-braces notation to set an array's elements only when initializing (as you do, in fact, earlier in the code).

How do I generate an array in D?

I have this c++11 code:
auto gen = []() -> double { /* do stuff */ };
std::generate(myArray.begin(), myArray.end(), gen);
How would I do the same with D's array? std.algorithm.fill doesn't take a function object, and I don't know how to pass a function to recurrence.
Here's a version that seems to work:
import std.algorithm, std.array, std.range, std.stdio;
void main() {
writefln("%s", __VERSION__);
int i;
auto dg = delegate float(int) { return i++; };
float[] res = array(map!dg(iota(0, 10)));
float[] res2 = new float[10];
fill(res2, map!dg(iota(0, res2.length)));
writefln("meep");
writefln("%s", res);
writefln("%s", res2);
}
[edit] Added fill-based version (res2).
I tested it in Ideone (http://www.ideone.com/DFK5A) but it crashes .. a friend with a current version of DMD says it works though, so I assume Ideone's DMD is just outdated by about ten to twenty versions.
You could do something like
auto arr = {/* generate an array and return that array */}();
If it's assigned to a global it should be evaluated at compile-time.
You can also use string mixins to generate code for an array literal.

Resources