This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/blenlib/intern/rand.c
Ton Roosendaal 8d940dfafe Random() issues with rendering...
- AO and soft shadow AreaLight tables were generated without fixed seed,
  causing animations to give unwanted amounts of noise.
- Made sure these tables now are calculated before render, with fixed seed
- Then found out the BLI_rand() has very bad seeding... it showed up as
  patterns. After some experimenting, found a nice method using noise.c
  hash tables. For compatibility with old code, named it BLI_srandom() to
  use this next to the BLI_srand(). This follows libc rand() and random()
  naming convention.
- Then of course threading should work... so made a BLI_thread_rand version
  of the calls. Now supports up to 16 threads, comments added in .h and .c

Result is stable animation render with AO and soft shadow. But, please
test and feedback!
2005-08-25 13:11:04 +00:00

183 lines
4.1 KiB
C

/**
* $Id$
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#include <stdlib.h>
#include <string.h>
#include "MEM_guardedalloc.h"
#include "PIL_time.h"
#include "BLI_rand.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#if defined(WIN32) && !defined(FREE_WINDOWS)
typedef unsigned __int64 r_uint64;
#else
typedef unsigned long long r_uint64;
#endif
#define MULTIPLIER 0x5DEECE66DLL
#define ADDEND 0xB
#define LOWSEED 0x330E
/***/
struct RNG {
r_uint64 X;
};
RNG *rng_new(unsigned int seed)
{
RNG *rng = MEM_mallocN(sizeof(*rng), "rng");
rng_seed(rng, seed);
return rng;
}
void rng_free(RNG* rng)
{
MEM_freeN(rng);
}
void rng_seed(RNG *rng, unsigned int seed) {
rng->X= (((r_uint64) seed)<<16) | LOWSEED;
}
int rng_getInt(RNG *rng) {
rng->X= (MULTIPLIER*rng->X + ADDEND)&0x0000FFFFFFFFFFFFLL;
return (int) (rng->X>>17);
}
double rng_getDouble(RNG *rng) {
return (double) rng_getInt(rng)/0x80000000;
}
float rng_getFloat(RNG *rng) {
return (float) rng_getInt(rng)/0x80000000;
}
void rng_shuffleArray(RNG *rng, void *data, int elemSize, int numElems)
{
int i = numElems;
void *temp = malloc(elemSize);
while (--i) {
int j = rng_getInt(rng)%i;
void *iElem = (unsigned char*)data + i*elemSize;
void *jElem = (unsigned char*)data + j*elemSize;
memcpy(temp, iElem, elemSize);
memcpy(iElem, jElem, elemSize);
memcpy(jElem, temp, elemSize);
}
free(temp);
}
/***/
static RNG theBLI_rng = {0};
/* note, this one creates periodical patterns */
void BLI_srand(unsigned int seed) {
rng_seed(&theBLI_rng, seed);
}
/* using hash table to create better seed */
void BLI_srandom(unsigned int seed) {
extern unsigned char hash[]; // noise.c
rng_seed(&theBLI_rng, seed + hash[seed & 255]);
seed= rng_getInt(&theBLI_rng);
rng_seed(&theBLI_rng, seed + hash[seed & 255]);
seed= rng_getInt(&theBLI_rng);
rng_seed(&theBLI_rng, seed + hash[seed & 255]);
}
int BLI_rand(void) {
return rng_getInt(&theBLI_rng);
}
double BLI_drand(void) {
return rng_getDouble(&theBLI_rng);
}
float BLI_frand(void) {
return rng_getFloat(&theBLI_rng);
}
void BLI_fillrand(void *addr, int len) {
RNG rng;
unsigned char *p= addr;
rng_seed(&rng, (unsigned int) (PIL_check_seconds_timer()*0x7FFFFFFF));
while (len--) *p++= rng_getInt(&rng)&0xFF;
}
void BLI_array_randomize(void *data, int elemSize, int numElems, unsigned int seed)
{
RNG rng;
rng_seed(&rng, seed);
rng_shuffleArray(&rng, data, elemSize, numElems);
}
/* ********* for threaded random ************** */
#define MAX_RNG_THREADS 16
static RNG rng_tab[MAX_RNG_THREADS];
void BLI_thread_srandom(int thread, unsigned int seed)
{
extern unsigned char hash[]; // noise.c
rng_seed(&rng_tab[thread], seed + hash[seed & 255]);
seed= rng_getInt(&rng_tab[thread]);
rng_seed(&rng_tab[thread], seed + hash[seed & 255]);
seed= rng_getInt(&rng_tab[thread]);
rng_seed(&rng_tab[thread], seed + hash[seed & 255]);
}
int BLI_thread_rand(int thread) {
return rng_getInt(&rng_tab[thread]);
}
float BLI_thread_frand(int thread) {
return rng_getFloat(&rng_tab[thread]);
}