josjoha
Resident-
Posts
3 -
Joined
-
Last visited
Content Type
Forums
Blogs
Knowledge Base
Everything posted by josjoha
-
How to: make your animations Petite Mesh Avatar Compatible
josjoha replied to Judith Flow's topic in Animation Forum
Hello, I have just automated this process. Not sure how to give the program but perhaps I can just paste it here ? Note that this is C code, it is not LSL code (it does not work in second life itself). It is written on and tested with GNU/Debian/Linux, using gcc. Compile on a GNU/Linux machine: gcc bvh2resize.c -o bvh2resize ; Then to run and get usage message: bvh2resize --help. This code will likely work on other implementations of C, for example for a windos compiler. (I do not use windos and can hence not help with it, sorry.) /* Name: bvh2resize * * Usage: > cat FILE.bvh | bvh2resize -f FRACTION > NEWFILE.bvh * > bvh2resize -h|--help * * Description: A program that will adapt numbers in a *.bvh file, so that * the root (hip) movement is resized according to a supplied * argument (a fraction). A *.bvh file is a file relating * to 3D simulated worlds, encoding an "animation" on an * "avatar". Note that 'resize' does not refer to file size, * but to the size of the avatar on which the animation plays. * It affects numerical values in the BVH file, which are * adjusted according to a user supplied fraction. * * Method of computation provided by 'Judith Flow', link: * https://community.secondlife.com/t5/Animation-Forum/How-to-make-your-animations-Petite-Mesh-Avatar-Compatible/td-p/1651619 * * Author: by Jos Boersema (Josjoha / joshb). * aug 25 07:32:39 UTC 2016, on Debian 8/GNU/Linux, using gcc. * 2016 © Jos Boersema * * License: This program is free software. It is provided 'as is,' without * any warranty or assumed fitness for a particular purpose. See * for complete License: http://www.gnu.org GNU General Public * License, version 3 (GPLv3). * * (Indent tab size = 4) This is version: 0.91 */#include <stdio.h>#include <string.h>#define LINE_BUFFER_LEN 1000 // The length of the buffer that records each // line in the file. An example of some BVHs showed its maximum line // length was 611 characters.#define FIND_START "Frame Time:" // This is what we look for as a marker in the // BVH file, to find the start of the data (based on face value look at // a BVH file).#define FIND_START_LEN 11 // This is the length of the just above string // FIND_START.void print_help ( ){ printf ( "bvh2resize: change root movement in a BVH animation file.\n" ) ; printf ( " Reads standard input, writes changed file to standard output.\n" ) ; printf ( "Usage: bvh2resize -h|--help|-f FRACTION\n" ) ; printf ( " FRACTION: < 1.0 is smaller ~, " "> 1.0 bigger avatar\n" ) ; printf ( "Example: cat dance.bvh | bvh2resize -f 0.30 > " "dance_petite.bvh\n") ; printf ( "Returns: success 0, usage error 1, FRACTION input error 2, " "input file error 3 \n" ) ; printf ( "© Jos Boersema 2016, This program is Free Software (GPLv3).\n" ) ;}// This function gets one line of input, does the error handling, and // returns non-zero when a program abort error occured, zero on success.// It writes the variable 'line' as existing in main ( ).// Note: this function error-aborts when fgets() hits End Of File, meaning// it cannot be used to detect the End Of File when it is expected. Use of// feof() after fgets_plus is necessary when EOF is expected.int fgets_plus ( char * getline ){ if ( NULL == fgets ( getline , LINE_BUFFER_LEN , stdin ) ) return 3 ; // read failed // Detect line buffer filled to capacity, assuming it was likely // even longer, thus aborting with error. if ( ( LINE_BUFFER_LEN - 1 ) <= strlen ( getline ) ) { fprintf ( stderr , "Error: too long line for line buffer size %i; " "recompile program with a larger LINE_BUFFER_LEN, " "aborting.\n" , LINE_BUFFER_LEN ) ; return 3 ; // File Input error (abort program) } return 0 ; // success}// This function returns a pointer to the desired number in a string,// the numbers are separated by spaces. Ex: bvh_number ( line , 3 ) // returns the 3rd number on a BVH data line (latter data block in BVH).// Starts count from 0. Returns NULL pointer on error.char * bvh_number ( char * data , int list_n ){ int count ; // count off the numbers. char * chr_n = data ; // Shifts through 'line' until found list_n number. if ( 0 == list_n ) return data ; // special case: no searching for ( count = 0 ; count < list_n ; count ++ ) { chr_n = strchr ( chr_n + 1 , ' ' ) ; if ( NULL == chr_n ) // Error: Could not find next occurance of ' ' { fprintf ( stderr , "Error: Could not find needed number in BVH, aborting.\n" ) ; return NULL ; // Program abort with file format error 3. } } return chr_n + 1 ; // + 1 because it returns the leading space location.}// Wraps the scanf() call with some error handling, "scanf-f(loat)-plus"()// Also takes in the call to bvh_number(...).int scanf_fplus ( char * data , int list_n , float * store ){ char * source ; // get the start of the number using bvh_number(...) // Find where this number is if ( NULL == ( source = bvh_number ( data , list_n ) ) ) return 3 ; // bvh_number() already prints an error to stderr // bvh_number() encountered an error: program abort // Scan it in if ( 1 != sscanf ( source , "%f" , store ) ) { // failed (probably not a BVH file or corrupted.) fprintf ( stderr , "Error: unable to scan a number in input," ", aborting. Problem occured at the first element of this " "data (which is not necessarily the start of a BVH line):\n" ) ; fprintf ( stderr , "%s\n" , source ) ; return 3 ; // file format error } return 0 ; // success: value stored}int main ( int argc , char * argv [ ] ) { float resize_fraction ; // Program argument: the animation is resized // to this number. char line [ LINE_BUFFER_LEN ] ; // Each line in the input file we will // read first, then process it if needed: thus need storing it. float original_rootz ; // This is the 2nd number of the 1st line of the data // block in a BVH file, which is the 'root' joint. Once read then kept. float root_x ; // The x-coordinate of the root, 1st number on a data line. float root_z ; // The z-coordinate of the root, 2nd number on a data line. float root_y ; // The y-coordinate of the root, 3rd number on a data line. // -----------------------------v--------------------------------------- // Program user arguments if ( argc > 1 ) // There is at least 1 argument { // detect a request for usage help: if ( ( ( 0 == strcmp ( "-h" , argv [ 1 ] ) ) || ( 0 == strcmp ( "--help" , argv [ 1 ] ) ) ) ) { print_help ( ) ; return 0 ; } // GNU recommends license/author arguments as well ... TODO // GNU recommends long arguments: --fraction=N ... TODO // process the user input of a fraction to resize animation to: else if ( 0 == strcmp ( "-f" , argv [ 1 ] ) ) { if ( argc > 2 ) // There is at least 2 arguments { int error ; // record return value from sscanf() error = sscanf ( argv [ 2 ] , " %f" , & resize_fraction ) ; // Some error detection. Zero input is also not allowed (math // error) Not using scanf_fplus because of other error message. if ( 0.0 == resize_fraction || 1 != error ) { fprintf ( stderr , "Error: unable to read resize " "fraction, or 0.00 input: '%s', aborting\n" , argv [ 2 ] ) ; return 2 ; // fraction user input error } } else // Expects the fraction argument as well { fprintf ( stderr , "Error: no fraction given with '-f', aborting.\n" ) ; print_help ( ) ; // Keeping it simple: no user-interaction. return 1 ; // usage error } } else // An unrecognized argument: usage error { fprintf ( stderr , "Error: unrecognized argument '%s', aborting.\n" , argv [ 1 ] ) ; print_help ( ) ; // Keeping it simple, no user-interaction. return 1 ; // usage error } } else // absence of all arguments { fprintf ( stderr , "Error: no arguments received, aborting.\n" ) ; print_help ( ) ; // Keeping it simple, no user-interaction. return 1 ; // usage error } // End processing arguments. // -------------------------------^------------------------------------ // -------------------------------v------------------------------------ // Flush the header to output // // Start processing the input: first look for the marker FIND_START in // the input. What precedes it is not needing changes, and echoed unto // stdout unchanged. do { // Getting an input file line in the line buffer, followed by error // handling: if ( 0 != fgets_plus ( line ) ) // fills 'line' { if ( 0 != feof ( stdin ) ) // End Of File reached { // Since we have not even reached data to process, this is a // file format error. Probably the input is not a BVH file, or // erroneously truncated. fprintf ( stderr , "Error: unexpected End Of File, aborting.\n" ) ; return 3 ; // File Input error (abort program) } else { // If not that, then abort with a generic message. fprintf ( stderr , "Error: problem reading file, " "aborting.\n" ) ; return 3 ; // error (abort program) } } // All input is handled by fgets(), all output by printf(). printf ( "%s" , line ) ; // Echo this header info line back on // stdout, to form the header of the new resized file as well. // With line read in hand, we'll scan for the marker: } while ( 0 != strncmp ( FIND_START , line , FIND_START_LEN ) ) ; // Found the marker: we have reached the data block in the input. // ----------------------------^--------------------------------------- // ----------------------------v--------------------------------------- // Handle the special first data line // The next line seems to be an initialization line of sorts. This will // be handled as a special case, outside the reading loops. At this point // the buffer 'line' holds the line containing the marker. // Getting a line in the line buffer, followed by error handling. if ( 0 != fgets_plus ( line ) ) return 3 ; // error abort printf ( "%s" , line ) ; // This line is also to be output back as is. // Scan in the special root height initialization number: if ( 0 != scanf_fplus ( line , 1 , & original_rootz ) ) return 3 ; // I have not added code to change the root original offset, because // a user can edit the BVH file at that point by hand, nor is there // information on whether this would ever be useful. // ----------------------------v--------------------------------------- // Main data processing // Start processing the first 3 numbers of each line. // The formula is; 1st and 3rd number are multiplied with the fraction. // The difference with the original_rootz and the 2nd number is also // multiplied with the fraction, and then added to original_rootz do { // INPUT: Getting an input file line, followed by condition handling: char * start_number_p ; // Holding space for bvh_number() return value if ( 0 != fgets_plus ( line ) ) // fills 'line' { // Expected End Of File: assumes succes, program end. if ( 0 != feof ( stdin ) ) return 0 ; // ok PROGRAM END. fprintf ( stderr , "Error: problem reading file, " "aborting.\n" ) ; return 3 ; // error abort } // CONVERT: Get the 3 numbers read in as floats: if ( 0 != scanf_fplus ( line , 0 , & root_x ) ) return 3 ; if ( 0 != scanf_fplus ( line , 1 , & root_z ) ) return 3 ;// Z, not Y if ( 0 != scanf_fplus ( line , 2 , & root_y ) ) return 3 ; // COMPUTE: root_x = root_x * resize_fraction ; root_z = ( root_z - original_rootz ) * resize_fraction + original_rootz ; root_y = root_y * resize_fraction ; // PRINT: Get the start of the remainder of the line, print all. if ( NULL == ( start_number_p = bvh_number ( line , 3 ) ) ) return 3 ; printf ( "%f %f %f %s" , root_x , root_z , root_y , start_number_p ) ; } while ( 1 ) ; // See fputs_plus() if-then for program end.} We resized a dance with FRACTION 0.30 for petite avis and it worked perfectly. Thank you Judith for providing the BVH resize methodoly. I hope the code is fairly bug free. In the likely case you want to convert many animations at once, you can do so on GNU/Linux with the following Zshell script: #!/usr/bin/zsh --# Writes a group of new BVH files, sourced from the same directory as # the program is running in. Writes the new files in /tmp/ directory.# (This is a Zshell script.) # (Author: Jos Boersema. Licensed: GNU G.P.L. version 3.)MARK="petite-" # Your markerFRACTION="0.30" # Your fraction OUTPUT_DIR="/tmp/bvh2resize_${MARK}${FRACTION}" # Your output directorymkdir ${OUTPUT_DIR}for i in $( ls ./*.bvh ) { NEWFILE="${i:r}_${MARK}${FRACTION}.${i:e}" echo "Converting file '${i}' into '${OUTPUT_DIR}/${NEWFILE}'" cat $i | bvh2resize -f "${FRACTION}" > ${OUTPUT_DIR}/${NEWFILE}} P.S. Isn't this weird: Judith post was on 08-28-2012 12:28 PM, my last (hopefully final) addition/revision on the programcode was on 08-28-2016 12:41 PM. That seems to be exactly 4 years (and 13 minutes) later. (aug 28 12:34 group-bvhresized.zsh) -
Hello, In Singularity viewer there is an option under Advanced>Debug, by which you can change WASD to ZQSD. Type "wasd" in the search box, the option comes up: true/false on using ZQSD for movement. I then have ZQSD remapped to "AOE," using the keys.ini file, or rather the keysZQSD.ini file. I don't know anymore if that was necessary, to remap ZQSD to "AOE," rather then remap WASD to "AOE," but in any case it works. It seems that Singularity has an easy option to use ZQSD, although I have not specifically attempted that without remapping to "AOE,". I don't know if other viewers have this option. Using Singularity Viewer (64 bit) 1.8.6 (6157) Sep 2 2014 15:52:42 on Linux, Debian 7 & 8, Dvorak keyboard layout and a keyboard without arrows (HH keyboard).
-
When taking 'coalesqued' objects (that is objects that consist of multiple groups of linked prims), the 'root prim' is supposed to be the first one clicked (the opposite of linking objects, when the last one becomes the root prim, right ?). However when then rezzing this coalosqued object using a rezzer script and the function llRezAtRoot, the object often (perhaps half the time) fails to rezz with the correct root prim at the specified rezz coordinates. Sometimes another prim seems to be taken as the root, and sometimes nothing seems to be taken as the root. The rotation is also always changed, for example it comes out at 90 degrees, or another rotation. It typically keeps failing once it fails once until perhaps a day or days later when it suddenly works again for unknown reason. Sometimes it does work properly (perhaps in total half the time.) For good order: I am building large objects that then have to come out of a 'rezzer,' then I take them with a 'special' prim as the root so that they always get rezzed correctly (if this function works that is). Sadly this fuction does not seem to work often, despite no different procedure being taken. Sometimes relogging helps, often it does not. I am wondering why this is happening, if I am doing something wrong, or if this function has bugs, or something else ? If this is a bug in SL is there a known work-around for this ? Thank you for your help. P.S. Hello Rolig Loon, thanks for answering my question. I will probably be able to make it work with "CasperTech Rez-Free BOX v1.57" even better then i had. The way I concluded it was the first one clicked of a coalesqued object was by trial and error. I have attempted to use the last clicked now as you suggested but this also did not seem to work. If it is the last one clicked that does make me wonder why it often worked with the first one clicked. Also the naming of the coalesqued object was sometimes not what was apparently being used as the root prim, even if it did work properly. Since I will try to use Casper's system (which seems to work correctly) this will hopefully not bother me though hopefully; Casper's system doesn't use coalsqued objects hence this will hopefully not be a problem then however it is caused. (I couldn't find a 'reply' function hence i put it here). P.P.S. This isn't relevant anymore for a potential problem with llRezAtRoot, but ... I switched to the builder-buddy system which seems to be more powerful in various ways. I'm glad llRezzAtRoot failed. One downside of these rezzers is that they seem to rezz either everything or nothing but that can be solved (I'll probably try having these rezzboxes in another rezzer and have each rezzbox rezz a part.) Thanks for your pointers. P.P.P.S I think the conclusion here is then that llRezAtRoot is unstable, because the suggestion is to not use it but use a builder packager. Perhaps this is something to be added to the llRezAtRoot manual (that it is unstable for coalesced objects).