LINUX.ORG.RU

Сообщения Gyros

 

Распознавание типа нарисованной двумерной фигуры (Figure Recognition)

Форум — Development

Всех приветствую!

Раскопал у себя на старом компьютере давно скачанный exe-шник:

рисуешь примерно фигуру и она определяет ее тип

(окружность, эллипс, ромб, треугольник (в тч равнобедренный и прямоугольный) и тп).

[Окружность]

[Прямоугольник]

[Прямоуг. треугольник]

[Ромб]

[Трапеция]

Программа 2006 года.

Исходников нет. Текстового файла с описанием тоже нет.

Только один EXE-шник.

[About]

Вопрос: как узнать какие библиотеки использовались (opencv?). Или с пом. какого алгоритма это было сделано?

PS поиском не нашел с какого это сайта когда-то взял

 , ,

Gyros
()

Отправка ip адреса посетителя сайта себе на почту

Форум — Web-development

Всех приветствую!

Вопрос: Как отправить ip адрес посетителя сайта себе на почту.

Знаю, что можно сделать через node.js.

А что если хостинг предлагает только статические страницы и тогда это (node) нельзя применить.

Кто знает как такое сделать? Какие есть еще способы?

PS Понимаю, что все есть где-ниб. в интернете, но а вдруг тут кто-нибудь уже решал такую или похожую задачу.

Заранее благодарю за осмысленные ответы и замечания.

 , , ,

Gyros
()

Загадка: почему mouseX выводится как целое, а mouseY - число с плавающей запятой

Форум — Web-development

Всех приветствую!

Собственно вопрос в заголовке темы.

Скриншот: здесь

Вывожу коорд. курсора мыши и в элементы, созданные js, так и в элемент , который уже присутствует в разметке.

Код для воспроизведения эффекта:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>P5j  Test</title>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
	
		<script>
			let inputX;
			let inputY;
			let elemP;
						
			function setup() {
  				let canvas = createCanvas(500, 500);
				background(64);
				canvas.parent('sketch-container');

				inputX = createInput('EmptyX');
				inputX.position(100, 100);

				inputY = createInput('EmptyY');
				inputY.position(100, 130);

				elemP = document.getElementById("Coords");
			}

			function draw() {
  				background(128);
				elemP.textContent=`x: ${mouseX} y: ${mouseY}`;
				//text(`x: ${mouseX} y: ${mouseY}`, 100, 70);

				if ( (mouseX>0 && mouseX < 500) && (mouseY>0 && mouseY < 500) )
				{	
					inputX.value(mouseX);
					inputY.value(mouseY);
				}
				else
				{	
					inputX.value('---');
					inputY.value('---');
				}

				if ( (mouseX>0 && mouseX < 500) && (mouseY>0 && mouseY < 500) )
				{
					ellipse(mouseX, mouseY, 15, 15);
				}
								
			}
		</script>


		<style type="text/css">
			body {
					font-family:"Arial";
					color:#493628;
					background:#C0C0C0}
		</style>
</head>
<body>
	<center>
		<h1>Приветствую Вас в P5j!</h1>
		<p="status">* * *</p>
		<p id="Coords"> </p>
		<div id="sketch-container">
 			
		</div>

		<p>* * *</p>
		<p>20 Марта 2025 by Gyros</p>
	</center>
</body>
</html>

Заранее благодарю за осмысленные ответы и замечания.

 ,

Gyros
()

Стоит ли делать always_inline для простеньких функций?

Форум — Development

Всех приветствую!

Мне не нравиться библиотека glm из-за своей многословности, сложности и большого кол-ва файлов.

Поэтому я, как программирующий на C естественно, пишу свою библиотеку.

Вопрос 1: Стоит ли делать always_inline для простеньких функций в своей библиотеке, например

...
static inline __attribute__((always_inline)) void   vec3_add     (VEC3 *v, const VEC3 *u,const VEC3 *w)    { v->X = u->X + w->X; 
                                                                                                             v->Y = u->Y + w->Y; 
                                                                                                             v->Z = u->Z + w->Z; }

static inline __attribute__((always_inline)) void   vec3_sub     (VEC3 *v, const VEC3 *u,const VEC3 *w)    { v->X = u->X - w->X; 
                                                                                                             v->Y = u->Y - w->Y; 
                                                                                                             v->Z = u->Z - w->Z; }
...

или компилятор лучше знает когда и что ему оптимизировать. И сделать их обычными static vec3_add(…)

Если такие ф-ции присутствуют внутри какого-то цикла, который не известно на уровне исполнения когда закончится, то компилятор не даст сделать такие ф-ции встроенными (_inline). Верно?

Вопрос 2: Имеет ли смысл держать еще аналогичные макросы

#define vec3_ADD(v,u,w)       { \
                                 (v).X = (u).X + (w).X; \
                                 (v).Y = (u).Y + (w).Y; \
                                 (v).Z = (u).Z + (w).Z; \
                              }
#define vec3_SUB(v,u,w)       { \
                                 (v).X = (u).X - (w).X; \
                                 (v).Y = (u).Y - (w).Y; \
                                 (v).Z = (u).Z - (w).Z; \
                              }

Они кажутся естественными. Даже иногда не знаешь, что лучше ф-ция или такой аналогичный макрос. Как быть, что выбрать? Или оставить и то, то это (на всякий случай).

Вопрос 3: Или все таки использовать glm, потому что..1).. 2)..3)?

Интересуют мысли по существу и про по такие вещи вообще.

Спасибо!

 , ,

Gyros
()

Слетает выравнивание для строк с русскими символами. Unicode в Си.

Форум — Development

Всех приветствую!

Все таки решил создать новую тему.

Хотя обсуждение началось в этой теме, но там оно больше уклонилось в лингвистическую строну, да и у меня немного другой вопрос.

Проблема вот в чем: если в printf-е мы ставим «%30s», то у нас выводится сначало 30-length(str) пробелов, потом наша строка str длиной length(str).

Но это не работает, если в строке есть не англ. символы.

Чтобы проверить какое будет поведение под Windows и Linux, а также с char* и wchar_t*, набросал программку:



#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <locale.h>
#include <wchar.h>
#include <uchar.h> // for char16_t


char *str_dup(char const *in)
{
    size_t len = strlen(in);
    char *out = malloc(len+1);
    strncpy(out, in, len+1);
    return out;
}

wchar_t *wstr_dup(wchar_t const *in)
{
    size_t len = wcslen(in);
    wchar_t *out = malloc((len+1)* sizeof(wchar_t));
    wcsncpy(out, in, (len+1) );
    return out;
}

wchar_t* convert_to_wstr(const char* cstr)
{
    mbstate_t state;
    memset(&state, 0, sizeof(state) );
    size_t out_sz = 1 + mbsrtowcs(NULL, &cstr, 0, &state);
    
    wchar_t* ws = malloc(out_sz*sizeof(wchar_t) );
    mbstowcs(ws, cstr, out_sz);
    return ws;
}

char* convert_to_cstr(const wchar_t* wstr)
{
    mbstate_t state;
    memset(&state, 0, sizeof(state) );
    size_t out_sz = 1 + wcsrtombs(NULL, &wstr, 0, &state);
    
    char* cs = malloc(out_sz*sizeof(char) );
    wcstombs(cs, wstr, out_sz);
    return cs;
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
typedef struct CSTRUCT
{
	char* data_only_engl; // только англ. буквы
        char* data_from_file; // строка из файла
        char* data_from_prog; // строка в программе
} CSTRUCT;

CSTRUCT* cs_create(const char* cstr)
{
	CSTRUCT* cs = malloc(sizeof(CSTRUCT));

	cs->data_only_engl = str_dup("Hello Friend");
	cs->data_from_prog = str_dup(cstr);

	FILE *input = fopen("text.txt", "r");
    char buff[128];
    memset(buff, '\0', 128);
    fgets(buff, 128, input);
    	cs->data_from_file = str_dup(buff);
	return cs;
}

void cs_print(CSTRUCT* cs)
{
	fprintf(stdout,"------------------------------|\n");
	const char FMT[] = "%30s| %2ld\n";
	fprintf(stdout, FMT, cs->data_only_engl, strlen(cs->data_only_engl) );
	fprintf(stdout, FMT, cs->data_from_prog, strlen(cs->data_from_prog) );
	fprintf(stdout, FMT, cs->data_from_file, strlen(cs->data_from_file) );
	fprintf(stdout,"123456789012345678901234567890|\n"); // ровно 30 символов
}

void cs_free(CSTRUCT** cs)
{
	free( (*cs)->data_from_prog);
	free( (*cs)->data_from_file);
	free( (*cs)->data_only_engl);
	free(*cs);
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/



typedef struct WSTRUCT
{
	wchar_t* data_only_engl;
        wchar_t* data_from_file;
        wchar_t* data_from_prog;
} WSTRUCT;


WSTRUCT* ws_create(const char* str)
{
	WSTRUCT* ws = malloc(sizeof(WSTRUCT));
	ws->data_only_engl = wstr_dup(L"Hello Friend");
	ws->data_from_prog = convert_to_wstr(str);

	FILE *input = fopen("text.txt", "r");
    char buff[128];
    memset(buff, '\0', 128);
    fgets(buff, 128, input);
    
	ws->data_from_file = convert_to_wstr(buff);
	return ws;
}

void ws_print(WSTRUCT* ws)
{
	fprintf(stdout,"------------------------------|\n");
	const char FMT[] = "%30ls| %2ld\n";
	fprintf(stdout, FMT, ws->data_only_engl, wcslen(ws->data_only_engl) );
	fprintf(stdout, FMT, ws->data_from_prog, wcslen(ws->data_from_prog) );
	fprintf(stdout, FMT, ws->data_from_file, wcslen(ws->data_from_file) );
	fprintf(stdout,"123456789012345678901234567890|\n");
}

void ws_free(WSTRUCT** ws)
{
	free( (*ws)->data_from_prog);
	free( (*ws)->data_from_file);
	free( (*ws)->data_only_engl);
	free(*ws);
}



int main(int argc, char const *argv[])
{
	
#if defined (_WIN32)
	setlocale(LC_ALL, "ru_RU");
#else
	setlocale(LC_ALL, "ru_RU.utf8");
#endif

	printf("sizeof(char)    = %ld\n", sizeof(char) );
	printf("sizeof(char16_t)= %ld\n", sizeof(char16_t) );
	printf("sizeof(wchar_t) = %ld\n", sizeof(wchar_t) );
	printf("\n");


	CSTRUCT* cs = cs_create("Hello! Друг");
	cs_print(cs);
	cs_free(&cs);

	WSTRUCT* ws = ws_create("Hello! Друг");
	ws_print(ws);
	ws_free(&ws);


	return EXIT_SUCCESS;
}

Кратко: есть две структуры одна хранит строки в char*, другая - wchar_t*.

Обе хранят три строки: с чисто англ. символами, со строкой инициализируемой в программе и строкой считываемой из файла:

text.txt

Привет friend из файла!

В итоге под Linux получаю

sizeof(char)    = 1
sizeof(char16_t)= 2
sizeof(wchar_t) = 4

------------------------------|
                  Hello Friend| 12
               Hello! Друг| 15
Привет friend из файла!
| 37
123456789012345678901234567890|
------------------------------|
                  Hello Friend| 12
               Hello! Друг| 11
Привет friend из файла!
| 24
123456789012345678901234567890|

Видно, что выравнивание сработало для строки только с англ. символами.

А хотелось бы:

------------------------------|
                  Hello Friend| 12
                   Hello! Друг| 11
       Привет friend из файла!| 23
123456789012345678901234567890|

Соответственно под Windows имею:

sizeof(char)    = 1
sizeof(char16_t)= 2
sizeof(wchar_t) = 2

------------------------------|
                  Hello Friend| 12
               Hello! Друг| 15
Привет friend из файла!
| 37
123456789012345678901234567890|
------------------------------|
                  Hello Friend| 12
               Hello! Друг| 15
Привет friend из файла!
| 37
123456789012345678901234567890|

Как сделать кроссплатф. вывод на экран с правильным выравниваем?

 , , , ,

Gyros
()

Проблема при сборке библиотеки: ключ -fPIC

Форум — Development

Всех приветствую!

Знает ли кто-нибудь решение такой проблемы:

собираю библиотеку (lib)xlsxio,но для нее нужна minizip-ng:

действую

cmake -S . -B build -D MZ_BUILD_TESTS=ON

~/minizip-ng$ cmake -S . -B build -D MZ_BUILD_TESTS=ON
-- Using CMake version 3.16.3
-- Using ZLIB 1.3.1
-- BZip2 library not found
-- Checking for module 'liblzma'
--   No package 'liblzma' found
-- Using LZMA 5.2.4
-- Checking for module 'libzstd'
--   No package 'libzstd' found
-- ZSTD library not found
-- Using OpenSSL 3.2.2
-- Using Iconv
-- The following features have been enabled:

 * MZ_COMPAT, Enables compatibility layer
 * MZ_ZLIB, Enables ZLIB compression
 * MZ_LZMA, Enables LZMA & XZ compression
 * MZ_PKCRYPT, Enables PKWARE traditional encryption
 * MZ_WZAES, Enables WinZIP AES encryption
 * MZ_OPENSSL, Enables OpenSSL for encryption
 * MZ_LIBBSD, Builds with libbsd crypto random
 * MZ_ICONV, Enables iconv string encoding conversion library
 * MZ_BUILD_TESTS, Builds minizip test executable

-- The following features have been disabled:

 * MZ_BZIP2, Enables BZIP2 compression
 * MZ_ZSTD, Enables ZSTD compression
 * MZ_LIBCOMP, Enables Apple compression
 * MZ_FETCH_LIBS, Enables fetching third-party libraries if not found
 * MZ_FORCE_FETCH_LIBS, Enables fetching third-party libraries always
 * MZ_COMPRESS_ONLY, Only support compression
 * MZ_DECOMPRESS_ONLY, Only support decompression
 * MZ_FILE32_API, Builds using posix 32-bit file api
 * MZ_BUILD_UNIT_TESTS, Builds minizip unit test project
 * MZ_BUILD_FUZZ_TESTS, Builds minizip fuzzer executables
 * MZ_CODE_COVERAGE, Builds with code coverage flags

-- Configuring done
-- Generating done
-- Build files have been written to: /home/bark/minizip-ng/build

Потом

cmake –build build

~/minizip-ng$ cmake --build build
make[1]: Entering directory '/home/bark/minizip-ng/build'
make[2]: Entering directory '/home/bark/minizip-ng/build'
make[2]: Leaving directory '/home/bark/minizip-ng/build'
make[2]: Entering directory '/home/bark/minizip-ng/build'
[  4%] Building C object CMakeFiles/minizip.dir/mz_crypt.c.o
[  8%] Building C object CMakeFiles/minizip.dir/mz_os.c.o
[ 13%] Building C object CMakeFiles/minizip.dir/mz_strm.c.o
[ 17%] Building C object CMakeFiles/minizip.dir/mz_strm_buf.c.o
[ 21%] Building C object CMakeFiles/minizip.dir/mz_strm_mem.c.o
[ 26%] Building C object CMakeFiles/minizip.dir/mz_strm_split.c.o
[ 30%] Building C object CMakeFiles/minizip.dir/mz_zip.c.o
[ 34%] Building C object CMakeFiles/minizip.dir/mz_zip_rw.c.o
[ 39%] Building C object CMakeFiles/minizip.dir/mz_strm_zlib.c.o
[ 43%] Building C object CMakeFiles/minizip.dir/mz_strm_lzma.c.o
[ 47%] Building C object CMakeFiles/minizip.dir/mz_crypt_openssl.c.o
[ 52%] Building C object CMakeFiles/minizip.dir/mz_os_posix.c.o
[ 56%] Building C object CMakeFiles/minizip.dir/mz_strm_os_posix.c.o
[ 60%] Building C object CMakeFiles/minizip.dir/mz_strm_pkcrypt.c.o
[ 65%] Building C object CMakeFiles/minizip.dir/mz_strm_wzaes.c.o
[ 69%] Building C object CMakeFiles/minizip.dir/compat/ioapi.c.o
[ 73%] Building C object CMakeFiles/minizip.dir/compat/unzip.c.o
[ 78%] Building C object CMakeFiles/minizip.dir/compat/zip.c.o
[ 82%] Linking C static library libminizip.a
make[2]: Leaving directory '/home/bark/minizip-ng/build'
[ 82%] Built target minizip
make[2]: Entering directory '/home/bark/minizip-ng/build'
make[2]: Leaving directory '/home/bark/minizip-ng/build'
make[2]: Entering directory '/home/bark/minizip-ng/build'
[ 86%] Building C object CMakeFiles/minizip_cli.dir/minizip.c.o
[ 91%] Linking C executable minizip
make[2]: Leaving directory '/home/bark/minizip-ng/build'
[ 91%] Built target minizip_cli
make[2]: Entering directory '/home/bark/minizip-ng/build'
make[2]: Leaving directory '/home/bark/minizip-ng/build'
make[2]: Entering directory '/home/bark/minizip-ng/build'
[ 95%] Building C object CMakeFiles/minigzip_cli.dir/minigzip.c.o
[100%] Linking C executable minigzip
make[2]: Leaving directory '/home/bark/minizip-ng/build'
[100%] Built target minigzip_cli
make[1]: Leaving directory '/home/bark/minizip-ng/build'

Потом устанавливаю в usr/local sudo make install

Теперь собираю xlsxio:


~/xlsxio$ cmake -G"Unix Makefiles"
CMake Warning:
  No source or binary directory provided.  Both will be assumed to be the
  same as the current working directory, but note that this warning will
  become a fatal error in future CMake releases.


-- XLSX I/O library version: 0.2.35
-- Configuring done
-- Generating done
-- Build files have been written to: /home/bark/xlsxio
bark@zuzu:~/xlsxio$ make
make[1]: Entering directory '/home/bark/xlsxio'
make[2]: Entering directory '/home/bark/xlsxio'
make[2]: Leaving directory '/home/bark/xlsxio'
make[2]: Entering directory '/home/bark/xlsxio'
[  4%] Building C object CMakeFiles/xlsxio_read_SHARED.dir/lib/xlsxio_read.c.o
[  8%] Building C object CMakeFiles/xlsxio_read_SHARED.dir/lib/xlsxio_read_sharedstrings.c.o
[ 13%] Linking C shared library libxlsxio_read.so
/usr/bin/ld: /usr/local/lib/libminizip.a(mz_strm.c.o): relocation R_X86_64_PC32 against symbol `mz_stream_write' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/xlsxio_read_SHARED.dir/build.make:102: libxlsxio_read.so] Error 1
make[2]: Leaving directory '/home/bark/xlsxio'
make[1]: *** [CMakeFiles/Makefile2:150: CMakeFiles/xlsxio_read_SHARED.dir/all] Error 2
make[1]: Leaving directory '/home/bark/xlsxio'
make: *** [Makefile:130: all] Error 2

Проблема тут

relocation R_X86_64_PC32 against symbol `mz_stream_write’ can not be used when making a shared object; recompile with -fPIC

Тогда ставлю в minizip-ng/CMakeLists.txt

на СЛЕДУЮЩЕЙ строке после комментария

# Set compiler options

строчку SET(CMAKE_SHARED_LIBRARY_C_FLAGS «-fpic»)

Потом, пересобираю, устанавливаю minixip-ng

Возвращаюсь к xlsxio:

результат такой же, тот же выхлоп в консоль, опять не может прилинковать

[ 13%] Linking C shared library libxlsxio_read.so

Linking C shared library libxlsxio_read.so
/usr/bin/ld: /usr/local/lib/libminizip.a(mz_strm.c.o): relocation R_X86_64_PC32 against symbol `mz_stream_write' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: bad value

Пока не ясно в чем проблема.

Странно, что разработчики в соих инструкциях по сборке никак момент с -fPIC не упомянули.

Видимо это считается тривиальным моментом..

 , ,

Gyros
()

Сборка Freetype-GL в Windows для mingw и символические ссылки на файлы

Форум — Development

Всех приветствую!

Хочу описать процесс сборки указанной выше библиотеки и задать вопрос. Сразу вопрос может показаться непонятным.

Итак, сборка:

  1. Имеем установленный MSYS (C:\msys64\ucrt64) плюс минимально необх. библиотеки
pacman -S mingw-w64-ucrt-x86_64-gcc
pacman -S mingw-w64-ucrt-x86_64-cmake
pacman -S mingw-w64-ucrt-x86_64-make
pacman -S mingw-w64-ucrt-x86_64-glew
pacman -S mingw-w64-ucrt-x86_64-glfw
pacman -S mingw-w64-ucrt-x86_64-fontconfig
pacman -S mingw-w64-ucrt-x86_64-freetype
pacman -S mingw-w64-ucrt-x86_64-harfbuzz
pacman -S mingw-w64-ucrt-x86_64-pkg-config
pacman -S mingw-w64-ucrt-x86_64-doxygen

установленные через шелл msys2.exe

  1. скачиваем Freetype GL https://github.com/rougier/freetype-gl/tree/master в C:\freetype-gl

  2. Читаем в INSTALL.md

 **Note**: Harfbuzz examples only work with symbolic links enabled. See <https://github.com/git-for-windows/git/wiki/Symbolic-links>

Поэтому делаем для всех файлов (кроме texture-font.h, texture-font.с, freetype-gl-err.h, freetype-gl-err.c ) в папке C:\freetype-gl\harfbuzz символические ссылки на файлы с теми же именами, но на уровень каталога выше.

(

По умолчанию создание символич. ссылок в Windows не разрешено.

Для этого включаем разрешение на создание символич. ссылок в Windows (в моем случае Windows 11).

Чтобы включить разрешение нужно запустить оснастку Group Policy Editor: Win+R gpedit.msc Конфигурация компьютера->Конфигурация Windows->Параметры безопасности->Локальные политики->Назначение прав пользователя добавляем своего user-а в пункте «Создание символических ссылок».

PS. Если такой оснастки нет, то устанавливаем ее: запускаем терминал с правами администратор и вводим: сначала

FOR %F IN ("%SystemRoot%\servicing\Packages\Microsoft-Windows-GroupPolicy-ClientTools-Package~*.mum") DO ( DISM /Online /NoRestart /Add-Package:"%F" ) 

потом

FOR %F IN ("%SystemRoot%\servicing\Packages\Microsoft-Windows-GroupPolicy-ClientExtensions-Package~*.mum") DO ( DISM /Online /NoRestart /Add-Package:"%F" )

)

Создание ссылок происходит так:

Запоминаем имя файла находящегося в C:\freetype-gl\harfbuzz, удаляем его из папки. Потом в этом каталоге выполняем

mklink <имя файла>  C:\freetype-gl\<имя файла>

Например,

mklink  freetype-gl-errdef.h C:\freetype-gl\freetype-gl-errdef.h

будет выдано

symbolic link created for freetype-gl-errdef.h <<===>> C:\freetype-gl\freetype-gl-errdef.h

Вот здесь вопрос(!?): а то делать с файлами freetype-gl-err.h, freetype-gl-err.c у которых нет в папке C:\freetype-gl аналогов с такими же именами?

Например, файл freetype-gl-err.h содержит одну строку «../freetype-gl-err.h», но уровнем выше нет файла с таким именем.

Т.е. нам нужно переделать файл в ссылку, но как будто не существует файла на который он должен ссылатся.

Это относится к этим двум файлам.

Естественно из-за этого сборка будет неудачной.

В репозитории Freetype GL в описании комита на эти файлы указано «Add harfbuzz support for errno stuff».

mkdir C:\freetype-gl\build

далее запускаем шелл C:\msys64\urct64.exe и в нем выполняем

  cd C:\freetype-gl\build

Далее возможны два варианта (все команды вып. в шелле C:\msys64\urct64.exe):

3а)

cmake -G "MinGW Makefiles"  -Dfreetype-gl_BUILD_HARFBUZZ=ON ..

потом mingw32-make

Отваливается в самом начале на:

[ 26%] Building C object harfbuzz/CMakeFiles/freetype-gl-hb.dir/platform.c.obj
[ 27%] Building C object harfbuzz/CMakeFiles/freetype-gl-hb.dir/texture-atlas.c.obj
[ 28%] Building C object harfbuzz/CMakeFiles/freetype-gl-hb.dir/texture-font.c.obj
In file included from C:\freetype-gl\harfbuzz\texture-font.c:15:
C:\freetype-gl\harfbuzz\freetype-gl-err.h:1:1: error: expected identifier or '(' before '.' token
    1 | ../freetype-gl-err.h
      | ^
C:\freetype-gl\harfbuzz\texture-font.c:26:3: warning: data definition has no type or storage class
   26 | } FT_Errors[] =
      |   ^~~~~~~~~
C:\freetype-gl\harfbuzz\texture-font.c:26:3: error: type defaults to 'int' in declaration of 'FT_Errors' [-Wimplicit-int]
In file included from C:/msys64/ucrt64/include/freetype2/freetype/fterrors.h:200,
                 from C:\freetype-gl\harfbuzz\texture-font.c:27:
C:/msys64/ucrt64/include/freetype2/freetype/fterrdef.h:58:3: warning: braces around scalar initializer
   58 |   FT_NOERRORDEF_( Ok,                                        0x00,
...

3б)

cmake -G "MinGW Makefiles"  -Dfreetype-gl_BUILD_HARFBUZZ=OFF ..

потом mingw32-make

Тут компилирует почти все примеры библиотеки, отваливается на

[ 94%] Building C object demos/CMakeFiles/markup.dir/markup.c.obj
[ 96%] Linking C executable markup.exe
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/14.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\markup.dir/objects.a(markup.c.obj):markup.c:(.text+0x15): undefined reference to `FcInit'
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/14.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\markup.dir/objects.a(markup.c.obj):markup.c:(.text+0x21): undefined reference to `FcNameParse'
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/14.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\markup.dir/objects.a(markup.c.obj):markup.c:(.text+0x3c): undefined reference to `FcConfigSubstitute'
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/14.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\markup.dir/objects.a(markup.c.obj):markup.c:(.text+0x48): undefined reference to `FcDefaultSubstitute'
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/14.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\markup.dir/objects.a(markup.c.obj):markup.c:(.text+0x60): undefined reference to `FcFontMatch'
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/14.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\markup.dir/objects.a(markup.c.obj):markup.c:(.text+0x70): undefined reference to `FcPatternDestroy'
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/14.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\markup.dir/objects.a(markup.c.obj):markup.c:(.text+0xc5): undefined reference to `FcPatternGet'
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/14.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles\markup.dir/objects.a(markup.c.obj):markup.c:(.text+0x113): undefined reference to `FcPatternDestroy'
collect2.exe: error: ld returned 1 exit status
mingw32-make[2]: *** [demos\CMakeFiles\markup.dir\build.make:112: demos/markup.exe] Error 1
mingw32-make[1]: *** [CMakeFiles\Makefile2:902: demos/CMakeFiles/markup.dir/all] Error 2
mingw32-make: *** [Makefile:145: all] Error 2

Но можно сказать уже успех.

Делитесь своими мыслями по поводу описанного.

Кто как собирает с меньшими издержками?

Что делать со ссылками непонятно куда?

Заранее благодарен за содержательные комментарии.

 , , , ,

Gyros
()

Как гарантированно заNULLить указатель на уже освобожденный объект

Форум — Development

Всех приветствую!

Может кому-нибудь мой вопрос покажется надуманным, но все равно напишу.

Есть (в данном примере игрушечный) код

KIT*   kit=NULL;

// создаем kit
kit = kit_create("Abracadabra", 5);

// пользуемся kit
// ...
kit_print(stdout, kit);
// ...

// освобождаем kit
kit_free(kit);
	
// ...	

// забыли, что уже освободили kit и делаем распечатку
kit_print(stdout, kit);
//Segmentation fault

Segmentation fault

Т.к. после

#define SAFE_FREE(object) if(object!=NULL) {free(object); (object)=NULL;}
void  kit_free(KIT *kit)
{   
	SAFE_FREE(kit->name);
	SAFE_FREE(kit->data);
	SAFE_FREE(kit);
}

указатель на kit не будет NULL на вызывающей стороне. И даже если сделать проверку в kit_print

if (kit != NULL && kit->data != NULL)
{  
  // печатаем kit
}
else
  printf("Извините, но kit=NULL");

все равно в kit_print придет ненулевой указатель.

Варианты решения:

   kit_free(kit);
   kit=NULL;

Недостаток: лишняя строка которую можно забыть написать, и вообще хотелось бы чтобы все делалось в kit_free

Сделать

KIT*  kit_free(KIT *kit)
{   
	SAFE_FREE(kit->name);
	SAFE_FREE(kit->data);
	SAFE_FREE(kit);
	return kit; // уже ставший NULL
}

и вызывать

kit = kit_free(kit);

Выглядит неплохо.

А теперь вопрос:

Имеются ли у кого-нибудь более изящные решения или возможен иной принципиально подход к освобождению памяти в pure C ?

 , , ,

Gyros
()

Глюк с инициализацией глобальных переменных (C/mingw)

Форум — Development

Всех приветствую!

Обнаружилось непонятное явление: после компиляции mingw32 и запуска под wine в программе не инициализируются глобальные переменные.

Более подробно:

Глобальные переменные:

bool line_mode = false;
enum {ORTHOGRAPHIC=0, PERSPECTIVE};
int projection_type=ORTHOGRAPHIC;

Некоторые ф-ции:

void reshape_cb (int w, int h)
{
    glViewport ( 0, 0, (GLint) w, (GLint) h ) ;
    WIDTH = w;
    HEIGHT = h;

       
    printf("projection_type = %d\n", projection_type);
    printf("line_mode = %d\n", line_mode);
    switch ( projection_type )
    {
      case PERSPECTIVE:
        printf("PERSPECTIVE\n");
        ...        
        break;

      case ORTHOGRAPHIC:
        printf("ORTHOGRAPHIC\n");
        ...
        break;
    };

    ...
    CHECK_GL_ERROR(); 
    printf("reshape()\n");
}
void keyboard_cb ( unsigned char key, int x, int y )
{
    switch ( key )
    {
      case 'l' :
      case 'L' :
      {
          line_mode = !line_mode;
          break;
      }

      case '1' :
      {
          projection_type = ORTHOGRAPHIC;
          reshape_cb(WIDTH, HEIGHT);
          break;
      }

      case '2' :
      {
          projection_type = PERSPECTIVE;
          reshape_cb(WIDTH, HEIGHT);
          break;
      }

      ...

    };

    glutPostRedisplay();
}

После запуска wine program.exe на экран выдается

projection_type = -1122261533
line_mode = 100
reshape()

При компиляции gcc все нормально:

projection_type = 0
line_mode = 0
ORTHOGRAPHIC
reshape()

Лечится это явление добавлением static:

static bool line_mode = false;
enum {ORTHOGRAPHIC=0, PERSPECTIVE};
static int projection_type=ORTHOGRAPHIC;

(или, возможно, инициализацией в ф-ции main) Тогда правильно работает и после mingw.

Кто-нибудь сталкивался с таким явлением? Почему это происходит?

Добавление.

Если после запуска wine program.exe нажать клавишу [2], то

projection_type = -1122261533
line_mode = 100
reshape()
НАЖАТИЕ КЛАВИШИ [2]
projection_type = 1
line_mode = 100
PERSPECTIVE
reshape()

видно значение projection_type инициализировалось как и задумано.

Тоже самое после gcc: ./program

projection_type = 0
line_mode = 0
ORTHOGRAPHIC
reshape()
НАЖАТИЕ КЛАВИШИ [2]
projection_type = 1
line_mode = 0
PERSPECTIVE
reshape()

PS Заранее благодарю за осмысленные ответы.

PS2 К сожалению, сделать маленький пример на выдачу этой ошибки пока не удалось. А вываливать кучу файлов сюда неуместно. Могу exe-шник дать для анализа явления.

 , , , ,

Gyros
()

Как обойти/исправить ошибку при сборке библиотек mxe?

Форум — Linux-install

Всех приветствую! Пытаюсь собрать некоторые библиотеки для mxe. На каком-то этапе происходит ошибка:


[download]    libsndfile-1.1.0.tar.xz
[build]       libsndfile              x86_64-w64-mingw32.static

Failed to build package libsndfile for target x86_64-w64-mingw32.static!
------------------------------------------------------------
configure.ac:345: the top level
autom4te: error: /usr/bin/m4 failed with exit status: 1
aclocal: error: /usr/local/bin/autom4te failed with exit status: 1
autoreconf: error: aclocal failed with exit status: 1
make[1]: *** [Makefile:903: build-only-libsndfile_x86_64-w64-mingw32.static] Error 1
make[1]: Leaving directory '/home/bark/mxe'
real	0m5,646s
user	0m4,455s
sys	0m0,188s
------------------------------------------------------------
[log]      /home/bark/mxe/log/libsndfile_x86_64-w64-mingw32.static

make: *** [Makefile:891: /home/bark/mxe/usr/x86_64-w64-mingw32.static/installed/libsndfile] Error 1

Далее смотрю лог, в нем:

cd '/home/bark/mxe/tmp-libsndfile-x86_64-w64-mingw32.static/libsndfile-1.1.0' && autoreconf -fi
configure.ac:345: error: macro PKG_INSTALLDIR is not defined; is a m4 file missing?
m4/ax_require_defined.m4:35: AX_REQUIRE_DEFINED is expanded from...
configure.ac:345: the top level
autom4te: error: /usr/bin/m4 failed with exit status: 1
aclocal: error: /usr/local/bin/autom4te failed with exit status: 1
autoreconf: error: aclocal failed with exit status: 1
make[1]: *** [Makefile:903: build-only-libsndfile_x86_64-w64-mingw32.static] Error 1
make[1]: Leaving directory '/home/bark/mxe'

Моя версия pkg:

pkg-config --version
0.29.1

Читаю про макрос PKG_INSTALLDIR:

PKG_INSTALLDIR(КАТАЛОГ)
Определяет переменную $pkgconfigdir как место, куда пакет должен установить pkg-config.
файлы .pc.

В mxe/tmp-libsndfile-x86_64-w64-mingw32.static/libsndfile-1.1.0/configure.ac указано:

dnl Require autoconf version >= 2.69
AC_PREREQ([2.69])

У меня

autoconf --version
autoconf (GNU Autoconf) 2.71

В этом файле configure.ac макрос PKG_INSTALLDIR упоминается два раза:

dnl Check for pkg-config outside the if statement.
PKG_PROG_PKG_CONFIG
AX_REQUIRE_DEFINED([PKG_INSTALLDIR])
PKG_INSTALLDIR

Версия Убунты 20.04 LTS.

Никто случайно не знает как это решить. Мысли вслух: может вручную создать директорию m4?

Заранее благодарен за ответы со существу.

 , , , ,

Gyros
()

Имитация фиксированного конвейера на современном OpenGL

Форум — Development

Приветстсвую всех!

Пытаюсь воспроизвести древний пример 1996 года на opengl4

(чтобы рендерилась в точности картинка с использованием фиксированных функций - но до этого пока далеко).

Простенькая сцена. Для простоты вывожу только три плоскости: пол, левую и правую стенки.

Последовательные запуски дают разные варианты затенения:

первый вариант

второй

третий

Сталкивался ли кто-нибудь с таким эффектом? Чем он вызван?

В расчете модели освещения нет элементов случайности, так что в этом виноват не шейдер (вершинный/фрагментный).

Тут что-то с vbo?

Инициализация пола

void initFloor()
{

    // 1) Текстура
    GLfloat *textureData = make_texture(TEXDIM, TEXDIM);
    glGenTextures(1, &tex_id);

    glBindTexture(GL_TEXTURE_2D, tex_id);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, TEXDIM, TEXDIM);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TEXDIM, TEXDIM, GL_RED, GL_FLOAT, textureData);
    free(textureData);
    CHECK_GL_ERROR();
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);


    glActiveTexture(GL_TEXTURE0);
    CHECK_GL_ERROR();
    prog_set_uniform_int(&floorsh, "tex1", 0);

    // 2) Геометрия
    float vertexData[4*3]=
    {
         -100.f,  -100.f, -320.f,  
          100.f,  -100.f, -320.f,  
          100.f,  -100.f, -640.f,  
         -100.f,  -100.f, -640.f   
    };

    GLubyte colorData[4*3] =
    {
        200, 200, 200,
        200, 200, 200,
        200, 200, 200,
        200, 200, 200 
       
    };

    GLubyte texCoords[4*2] =
    {
        0, 0, 
        1, 0, 
        1, 1, 
        0, 1
    };

    GLuint indexList[2][3] =
    {
        {0, 1, 2},   // first triangle
        {0, 2, 3}    // second triangle
    };



    glGenBuffers(1, &vbo_floor_pos);
    glBindBuffer(GL_ARRAY_BUFFER, vbo_floor_pos);
    glBufferData(GL_ARRAY_BUFFER, 4*3 * sizeof(float), vertexData, GL_STATIC_DRAW);

    glGenBuffers(1, &vbo_floor_color);
    glBindBuffer(GL_ARRAY_BUFFER, vbo_floor_color);
    glBufferData(GL_ARRAY_BUFFER, 4*3 * sizeof(GLubyte), colorData, GL_STATIC_DRAW);

    glGenBuffers(1, &vbo_floor_tex);
    glBindBuffer(GL_ARRAY_BUFFER, vbo_floor_tex);
    glBufferData(GL_ARRAY_BUFFER, 4*2 * sizeof(float), texCoords, GL_STATIC_DRAW);

    glGenBuffers(1, &ebo_floor);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_floor);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 2*3 * sizeof(GLuint), indexList, GL_STATIC_DRAW);

    

    glGenVertexArrays( 1, &vao_floor );
    glBindVertexArray(vao_floor);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_floor);

    

    glEnableVertexAttribArray(0);  // position
    glEnableVertexAttribArray(1);  // color
    glEnableVertexAttribArray(2);  // texture coords

    glBindBuffer(GL_ARRAY_BUFFER, vbo_floor_pos);
    glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, NULL );

    glBindBuffer(GL_ARRAY_BUFFER, vbo_floor_color);
    glVertexAttribPointer( 1, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL );

    glBindBuffer(GL_ARRAY_BUFFER, vbo_floor_tex);
    glVertexAttribPointer( 2, 2, GL_UNSIGNED_BYTE, GL_FALSE, 0, NULL );

    glBindVertexArray(0);
}

Отрисовка пола

void drawFloor()
{
    prog_use(&floorsh);

    glEnable(GL_TEXTURE_2D);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, tex_id);
    
    glBindVertexArray(vao_floor);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_floor);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

    glBindVertexArray(0);
    glDisable(GL_TEXTURE_2D);
}

Инициализация левой и правой стены

/* left wall */
static float left_wall[12] = {-100.f, -100.f, -320.f,
                              -100.f, -100.f, -640.f,
                              -100.f,  100.f, -640.f,
                              -100.f,  100.f, -320.f };
static float left_normal[3] = {1.f, 0.f, 0.f};
static float left_color[3] = {165, 165, 165};
static struct PLANE left;

/* right wall */
static float right_wall[12] = {  100.f, -100.f, -320.f,
                                 100.f,  100.f, -320.f,
                                 100.f,  100.f, -640.f,
                                 100.f, -100.f, -640.f };
static float right_normal[3] = {-1.f, 0.f, 0.f};
static float right_color[3] = {165, 165, 165};
static struct PLANE right;

void plane_init(PLANE *plane, const float *points, float *normal, float *color)
{
    
    float vertexData[4*3]=
    {
          points[0],  points[ 1], points[ 2],  
          points[3],  points[ 4], points[ 5], 
          points[6],  points[ 7], points[ 8], 
          points[9],  points[10], points[11]
    };

    GLubyte colorData[4*3] =
    {
        color[0], color[1], color[2],
        color[0], color[1], color[2],
        color[0], color[1], color[2],
        color[0], color[1], color[2]
    };

    GLubyte texCoords[4*2] =
    {
        0, 0, 
        1, 0, 
        1, 1, 
        0, 1
    };

    GLubyte normalData[4*3] =
    {
        normal[0], normal[1], normal[2],
        normal[0], normal[1], normal[2],
        normal[0], normal[1], normal[2],
        normal[0], normal[1], normal[2] 
    };

    GLuint indexList[2][3] =
    {
        {0, 1, 2},   // first triangle
        {0, 2, 3}    // second triangle
    };



    glGenBuffers(1, &plane->vbo_pos);
    glBindBuffer(GL_ARRAY_BUFFER, plane->vbo_pos);
    glBufferData(GL_ARRAY_BUFFER, 4*3 * sizeof(float), vertexData, GL_STATIC_DRAW);

    glGenBuffers(1, &plane->vbo_color);
    glBindBuffer(GL_ARRAY_BUFFER, plane->vbo_color);
    glBufferData(GL_ARRAY_BUFFER, 4*3 * sizeof(GLubyte), colorData, GL_STATIC_DRAW);

    glGenBuffers(1, &plane->vbo_tex);
    glBindBuffer(GL_ARRAY_BUFFER, plane->vbo_tex);
    glBufferData(GL_ARRAY_BUFFER, 4*2 * sizeof(float), texCoords, GL_STATIC_DRAW);

    glGenBuffers(1, &plane->vbo_normal);
    glBindBuffer(GL_ARRAY_BUFFER, plane->vbo_normal);
    glBufferData(GL_ARRAY_BUFFER, 4*3 * sizeof(float), normalData, GL_STATIC_DRAW);

    glGenBuffers(1, &plane->ebo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, plane->ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 2*3 * sizeof(GLuint), indexList, GL_STATIC_DRAW);

    

    glGenVertexArrays( 1, &plane->vao );
    glBindVertexArray(plane->vao);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, plane->ebo);

    

    glEnableVertexAttribArray(0);  // position
    glEnableVertexAttribArray(1);  // color
    glEnableVertexAttribArray(2);  // texture coords
    glEnableVertexAttribArray(3);  // normal

    glBindBuffer(GL_ARRAY_BUFFER, plane->vbo_pos);
    glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, NULL );

    glBindBuffer(GL_ARRAY_BUFFER, plane->vbo_color);
    glVertexAttribPointer( 1, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL );

    glBindBuffer(GL_ARRAY_BUFFER, plane->vbo_tex);
    glVertexAttribPointer( 2, 2, GL_UNSIGNED_BYTE, GL_FALSE, 0, NULL );

    glBindBuffer(GL_ARRAY_BUFFER, plane->vbo_normal);
    glVertexAttribPointer( 3, 3, GL_FLOAT, GL_FALSE, 0, NULL );

    glBindVertexArray(0);

}

void plane_draw(PLANE *plane)
{
    glBindVertexArray(plane->vao);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, plane->ebo);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

    glBindVertexArray(0);
}

Инициализация шейдеров:

void init_scene()
{
    glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ;
   
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f );  

    prog_create(&floorsh);
    prog_attach_shader_from_file(&floorsh, FLOOR_VERTEX_SHADER_NAME);
    prog_attach_shader_from_file(&floorsh, FLOOR_FRAGMENT_SHADER_NAME);
    prog_link(&floorsh);
    prog_use(&floorsh);
    initFloor();
    
    
    
    prog_create(&wallsh);
    prog_attach_shader_from_file(&wallsh, WALL_VERTEX_SHADER_NAME);
    prog_attach_shader_from_file(&wallsh, WALL_FRAGMENT_SHADER_NAME);
    prog_link(&wallsh);
    prog_use(&wallsh);
    initWalls();
      
 
    prog_set_uniform_3f(&wallsh, "lightSource.ambient",  1.0f, 1.0f, 1.0f);  
    prog_set_uniform_3f(&wallsh, "lightSource.diffuse",  1.0f, 1.0f, 1.0f); 
    prog_set_uniform_3f(&wallsh, "lightSource.specular", 1.0f, 1.0f, 1.0f);  
    prog_set_uniform_3f(&wallsh, "lightSource.position", 50.f, 50.f, -320.f);

    prog_set_uniform_3f(&wallsh, "lightModel.ambient",  1.0f, 1.0f, 1.0f);  
    prog_set_uniform_3f(&wallsh, "material.emission",   1.0f, 1.0f, 1.0f); 
    prog_set_uniform_3f(&wallsh, "material.ambient",    1.0f, 1.0f, 1.0f);  
    prog_set_uniform_3f(&wallsh, "material.diffuse",    1.0f, 1.0f, 1.0f); 
    prog_set_uniform_3f(&wallsh, "material.specular",   1.0f, 1.0f, 1.0f); 
    prog_set_uniform_float(&wallsh, "material.shininess",   10.0f); 

    mat4_identity(&model);
    mat4_identity(&view);
   
    MAT4 MV; 
    mat4_multiply(&MV, &view,  &model);
    prog_set_uniform_mat4(&wallsh, "modelViewMatrix", &MV);

    MAT3 NormalMatrix;
    NormalMatrix.M[0] = MV.M[0];     NormalMatrix.M[3] = MV.M[4];     NormalMatrix.M[6] = MV.M[8];
    NormalMatrix.M[1] = MV.M[1];     NormalMatrix.M[4] = MV.M[5];     NormalMatrix.M[7] = MV.M[9];
    NormalMatrix.M[2] = MV.M[2];     NormalMatrix.M[5] = MV.M[6];     NormalMatrix.M[8] = MV.M[10];
    prog_set_uniform_mat3(&wallsh,"normalMatrix", &NormalMatrix);

    
    mat4_perspective_projection(&projection, -FRUSTDIM, FRUSTDIM, -FRUSTDIM, FRUSTDIM, FRUSTNEAR, FRUSTFAR);
    prog_set_uniform_mat4(&wallsh, "projectionMatrix", &projection);
    

    glEnable(GL_DEPTH_TEST);
    //glPolygonMode(GL_FRONT, GL_FILL);

    //glCullFace(GL_BACK);

    CHECK_GL_ERROR();
}

Заранее благодарю за осмысленные ответы и помощь!

 , , ,

Gyros
()

Названия для размеров часто используемых буферов

Форум — Development

Приветствую всех!

Сделал так:

#define GIANT_SIZE     1024*32
#define HUGE_SIZE      1024*16 
#define LARGE_SIZE     1024*8 
#define BIG_SIZE       1024 
#define MIDDLE_SIZE    512
#define MEDIUM_SIZE    256
#define SMALL_SIZE     128 
#define LITTLE_SIZE    64 
#define TINY_SIZE      32 

Стильно получилось?

Часто требуется, например, считать строку из файла, и чтобы не плодить магических констант, вместо 512 писать MIDDLE_SIZE

...
while (!feof(fp))
{
    char buff[MIDDLE_SIZE];
    fgets(buff, MIDDLE_SIZE, fp);
    buff[MIDDLE_SIZE-1]='\0';
    char* line = str_dup(buff);
    str_trim(line);
...

Например, загрузка матрицы из файла формата (нарочно зашумленный пробелами и tab-ами):



DIM1=	3
	
  DIM2 = 7


{
   	 0.935    0.674    -1.687    0.468  2.436   -1.743  0.275

   	 0.111    0.346    0.368   0.907    -7.346     -0.235    -0.139  
0.436    -0.134    -1.047    0.879    -1.051  -0.367         -0.196

}
	

выглядит вот так

void matrix_load( MATRIX* A, const char* fileName)
{
    FILE* fp;
    bool b_is_dim1_read=false;
    bool b_is_dim2_read=false;
    unsigned int dim1, dim2;
    bool begin=false;
    bool end = false;
    int row_count = 0;


    if ((fp = fopen(fileName,"r")) == NULL)
    {
      fprintf(stderr,"File '%s' open failed\n", fileName);
      enter_pause();
      exit(EXIT_FAILURE);
    }
    else
    {
        while (!feof(fp))
        {
            char buff[MIDDLE_SIZE];
            fgets(buff, MIDDLE_SIZE, fp);
            buff[MIDDLE_SIZE-1]='\0';
            char* line = str_dup(buff); // 
            str_trim(line);  // обрезаем '\t','\v', '\f', '\n', '\r', ' '      

            if (0==strlen(line)) // если после обрезки строка пустая, то пропускаем обработку
            {
                free(line);
                continue;
            }
            
            if (line[0] == 'D' && line[1] == 'I' && line[2]== 'M') // если встретилось "DIM"
            {
                Tokens* dim  = tokens_new(2);
                string_split(dim, line, "="); // разбиваем строку по '='
                

                if (line[3]== '1' || line[3]== '2') // DIM1 или DIM2
                {
                    errno = 0;
                    char *endptr;
                    unsigned int d = strtoul(dim->array[1]->data, &endptr, 10);
                    
                    if (*endptr != '\0' || errno !=0 || d==0 || d>30) // не более 30x30
                    {
                        fprintf(stderr,"Error: dimension wrong '%s'\n", dim->array[1]->data);
                        tokens_free(dim);
                        free(line);
                        enter_pause();
                        exit(EXIT_FAILURE);
                    }
                    
                    switch (line[3])
                    {
                    case '1':
                        dim1 = d;
                        b_is_dim1_read = true;
                        break;

                    case '2':
                        dim2 = d;
                        b_is_dim2_read = true;
                        break;

                    }
                }
                
                 // если все размерности считаны, то выделяем память для матрицы
                if (b_is_dim1_read && b_is_dim2_read)
                {
                    matrix_create(A, dim1, dim2);
                }

                tokens_clear(dim);
                tokens_free(dim);
            }

            

            if (line[0] =='{') { begin=true; free(line); continue; } // признак начала значений матрицы
            if (line[0] =='}') { end=true;   free(line); continue; }
            if (begin && !end)
            {
                //printf("%s\n", line);
                Tokens* row  = tokens_new(dim2); // по кол-ву элементов в строке
                string_split(row, line, " ");

                // если столбцов недостаточно или строк больше заявленных
                if (dim2 != row->size || row_count >= dim1)
                {
                    fprintf(stderr,"Error: Invalid file format '%s'\n", fileName);
                    enter_pause();
                    exit(EXIT_FAILURE);
                }

                // заполнение строки матрицы
                for (int j=0; j<dim2; ++j)
                {
                    
                    errno = 0;
                    char *endptr;
                    double value = strtod(row->array[j]->data, &endptr);
                    if (*endptr != '\0' || errno != 0 || 10 < strlen(row->array[j]->data) ) //не более 10-значное число
                    {
                        fprintf(stderr,"Error: wrong value '%s'\n", row->array[j]->data);
                        tokens_free(row);
                        free(line);
                        matrix_free(A);
                        enter_pause();
                        exit(EXIT_FAILURE);
                    }
                    matrix_set_elem(A, row_count, j,  value);
                }
                row_count++;
                tokens_clear(row);
                tokens_free(row);
            }


            free(line);
        }
        fclose(fp);

        if (row_count != dim1) // недочитали заявленные dim1 строк
        {
            fprintf(stderr,"Error: Invalid file format '%s'\n", fileName);
            enter_pause();
            exit(EXIT_FAILURE);
        }
    }

}

Функция str_dup:

char *str_dup(char const *in)
{
    if ( !in ) return NULL;
    size_t len = strlen(in);
    char *out = malloc(len+1);
    strncpy(out, in, len+1);
    return out;
}

Буду рад услышать отзывы о стиле.

 , , ,

Gyros
()

Форматирование даты-времени для лога: strftime не работает с mingw?

Форум — Development

Всех приветствую!

Необходимо выводить дату-время в лог-файл.

char* get_datetime_str_alt1(char *str_datetime)
{
    char buff[64]={'\0'};

    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
  
    strftime(buff, sizeof(buff), "%e-%b-%Y %Z %T", localtime(&ts.tv_sec));
    sprintf(str_datetime, "%s", buff);
       
    return str_datetime;
}


char* get_datetime_str_alt2(char *str_datetime)
{
    char buff[64]={'\0'};
       
    time_t t = time(NULL);
    struct tm *local = localtime(&t);
  
    strftime(buff, sizeof(buff), "%e-%b-%Y %Z %H:%M:%S", local);
    sprintf(str_datetime, "%s", buff);
       
    return str_datetime;
}

Эти два варианта работают после gcc

1-Aug-2024 MSK 12:32:45: Start!
1-Aug-2024 MSK 12:32:45: Bla-bla
1-Aug-2024 MSK 12:32:46: End!

, но ничего не выводят после mingw:

: Start!
: Bla-bla
: End!

Работает отлично только

char* get_datetime_str(char *str_datetime)
{
    time_t t = time(NULL);
        
    sprintf(str_datetime, "%s", ctime(&t) );
    char *p = strchr(str_datetime, '\n');
    *p = '\0';
 
    return str_datetime;
}

Но форматирование уже выбираю не я:

Thu Aug 01 12:13:08 2024: Start!
Thu Aug 01 12:13:08 2024: Bla-bla
Thu Aug 01 12:13:09 2024: End!

По идее и так работает. Но все таки какая-то неудовлетворенность остается. Сталкивался кто-нибудь с подобным эффектом?

Подозреваю нужно обновлять mingw, но так не хочется: столько библиотек опять устанавливать (к тому же я уже забыл как это делал).

PS gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0

x86_64-w64-mingw32-gcc (GCC) 9.3-win32 20200320 wincrt

 , , , ,

Gyros
()

printf vs fprintf(stderr)

Форум — Development

Всех приветствую!

Задался таким вопросом: а нужно ли городить

 fprintf(stderr, "Error: bla-bla\n");

вместо простого

printf("Error: bla-bla\n");

Ведь результат один и тот же.

Когда необходимо разделять stderr и stdout? Вообще, когда и как может использоваться stderr?

PS Заранее благодарю за ответы.

 , ,

Gyros
()

Есть ли тема курсора, чтобы при нажатии кнопки мыши была анимация курсора?

Форум — Desktop

Приветствую всех!

Не подскажете существует ли тема курсора (для xfce, xubuntu), чтобы принажатии кнопки мыши производилась какая-нибудь анимация, например маленький фейерверк исходящий от курсора или он как-то бы подсвечивался интересно.

Или, если нет темы, то как сделать подсветку курсора при нажатии.

Заранее благодарю за содержательные ответы.

 , , , ,

Gyros
()

Поле редактирования в Nuklear

Форум — Development

Всех приветствую!

Имеется проблема с работой nk_edit_string, библиотека Nuklear.

Суть: вводим в поле целое число и нажимаем кнопочку рядом, число выводится в консоле (для отладки).

int F=5; // глобальная
...

static char text[64];
static int text_len;
active = nk_edit_string(ctx, NK_EDIT_SIMPLE, text, &text_len, 64, nk_filter_decimal);
            if (nk_button_label(ctx, "->")) // || active & NK_EDIT_COMMITED)
{
   text_len = strlen(text);
   if (text_len !=0 && text_len<8)
   {
       F = atoi(text);
       printf("F=%d\n", F);
       memset(text, '\0', 64);
       text_len=0;
   }
   printf("text=%s\n", text);
}
...

Тест 1: ввели 77, вывод: F=77, text="";

Тест 2: ввели 555, но тут же передумали, стерли и снова набрали 77, вывод: F=775, text="";

Получается буфер text был «555», но был перебит «775», т.е. он не чиститься при каждом новом вводе/редактировании.

Кто-нибудь умеет правильно использовать NK_EDIT_SIMPLE, чтобы не было такого эффекта (вернее сказать, дефекта)?

 , , ,

Gyros
()

Числа с плавающей запятой. Откуда взялся минус и как его убрать?

Форум — Development

Тестовый пример, показывающий суть явления:

#include <stdio.h>
int main()
{
    float right=-2.0f, left=2.0f; 
    float res = (right+left)/(right-left);
    printf("%5.12e\n", res);

    float test = -0.00000000000000424f;
    printf("%3.3f\n", test);
}

Результат:

-0.000000000000e+00
-0.000

Понятно, что после right-left знаковый бит становится 1. Но выглядит (когда выводишь на экран с %3.3f) так как будто есть где-то далеко после нулей числа, например -0.00000000000000424. А на самом деле их нет. Это ноль, только со знаком (IEEE754 это допускает). Но с математической точки зрения и при выводе матрицы нам хотелось бы видеть настоящий ноль (в математике он один) без знака. Кто-нибудь сталкивался с такой «проблемой»? Как красиво сделать в программе, чтобы ноль был единственным, без знака. Есть ли изящные решения? Просто не хочется чтобы в матрице было -0.000, это может сбить с толка того, кто будет смотреть вывод на экран или распечатку, по уже выше описанной причине.

 , , ,

Gyros
()

Imgui и чистый C

Форум — Development

Приветствую всех! Никто не знает как собрать программу, если библиотека Imgui использует C++, а main.c и др. используемые библиотеки написаны на чистом C (C11). Вызовы Imgui происходят только в одном main.c Как быть? Может есть какой-нибудь способ собрать. Или отказываться от Imgui? А есть ли альтернатива пользовательского интерфейса для OpenGL на C?

 , , , ,

Gyros
()

Программирование анимации персонажа. Есть проблема

Форум — Development

Всех приветствую! Хочу двигать персонаж вправо на 10.0f ровно за свое заданное время: 2 сек, 0.5 сек и т.п.

Имеются следующие функции и глобальные переменные (очищенный от несущественного псевдокод):

float personage_X=-5.0f, personage_Y=-5.0f;
float distance_X=10.0, distance_Y=0.0;
float dX, dY;
double DELTA_T = 0.01667; //среднее значение delta_T даваемое программой 
                            //(по сути это 1000/60=16.6(6) мс/кадр)
double last_T_move;
double duration_T;
int duration_tick;
bool bmoveLeft  = false;
bool bmoveRight = false;



moveRight
{
   bmoveRight = true; // начинаю движение
   duration_T = 0.9;   // длительность в сек
   duration_tick = (int) (duration_T/DELTA_T); // кол-во тиков(кадров) для перемещения
   dX = distance_X/duration_tick;                   // шаг перемещения
   last_T_move = get_time();
}

update
{
  printf("update()\n");
  if (bmoveRight)
  {
      personage_X += dX;
      printf("now_T - last_T_move = %5.7f\n", now_T - last_T_move);
      if (now_T - last_T_move >= duration_T )
      {
         bmoveRight = false; // остановить движение
      }
    }
}

idle
{
  const double now_T = get_time();
  const double delta_T = now_T - last_T;
  last_T = now_T;
  printf("delta_T = %5.5f\n", delta_T);

  update(now_T);

  redisplay();
}

display
{
  printf("display()\n");
  render_personage();

  swap_buffers();
}

Вывод консоли работающей программы:

( читать дальше... )

1) Теперь я начинаю движение, например за 2.2 сек вправо на 10:

personage coords: [-5.000, -5.000]
duration_tick = 131 // 131 кадр необходимо для достижения конечной точки перемещения 
dX = 0.07634        // шаг
now_T - last_T_move = 0.0156779
now_T - last_T_move = 0.0324781
now_T - last_T_move = 0.0491800
now_T - last_T_move = 0.0658500
now_T - last_T_move = 0.0825200
...
now_T - last_T_move = 2.1999640
now_T - last_T_move = 2.2166250
personage coords: [5.153, -5.000]  //  в идеале должно быть [5.000, -5.000]
                                   //  еще только маленькая погрешность

2) Движение за 0.9 сек вправо на 10:

personage coords: [-5.000, -5.000]
duration_tick = 53 // 53 кадра необходимо для достижения конечной точки перемещения 
dX = 0.18868       // шаг
now_T - last_T_move = 0.0135901
now_T - last_T_move = 0.0302720
now_T - last_T_move = 0.0469420
now_T - last_T_move = 0.0636110
...
now_T - last_T_move = 0.9139049
personage coords: [5.377, -5.000]  //  в идеале должно быть [5.000, -5.000]
                                   //  уже существенная погрешность

3) Движение за 0.2 сек вправо на 10:

personage coords: [-5.000, -5.000]
duration_tick = 11
dX = 0.90909
now_T - last_T_move = 0.0133729
now_T - last_T_move = 0.0302980
now_T - last_T_move = 0.0469708
now_T - last_T_move = 0.0636489
now_T - last_T_move = 0.0803308
...
now_T - last_T_move = 0.1970379
now_T - last_T_move = 0.2136910
personage coords: [6.818, -5.000]  // в идеале должно быть [5.000, -5.000]
                                   //  бешенейшая погрешность (!)
                                   // Alarm! Что делать?

Из трех экспериментов видно, что чем быстрее я хочу переместиться, то тем дальше перелетаю требуемую конечную точку.

Хотелось бы услышать компетентное мнение по устранению данной проблемы и/или возможного изменения подхода к анимации в принципе. Спасибо за помощь!

 , , , ,

Gyros
()

Не хватает библиотеки при сборке cocos2d-x, а она есть!

Форум — Development
~/cocos2d-x-3.17.2/cmake-build$ make
[  1%] Built target ext_unzip
[  3%] Built target ext_recast
[  3%] Built target ext_tinyxml2
[  3%] Built target ext_xxhash
[  3%] Built target ext_xxtea
[  3%] Built target ext_clipper
[  4%] Built target ext_edtaa3func
[  4%] Built target ext_convertUTF
[  4%] Built target ext_poly2tri
[  5%] Built target ext_md5
[  5%] Built target external
[ 70%] Built target cocos2d
[ 71%] Built target ext_tolua
[ 72%] Built target ext_luasocket
[ 79%] Built target luacocos2d
[ 84%] Built target jscocos2d
[ 84%] Linking CXX executable ../../../bin/cpp-empty-test/cpp-empty-test
/usr/bin/ld: ../../../../external/linux-specific/fmod/prebuilt/64-bit/libfmod.so: .dynsym local symbol at index 2 (>= sh_info of 2)
/usr/bin/ld: ../../../../external/linux-specific/fmod/prebuilt/64-bit/libfmod.so: .dynsym local symbol at index 3 (>= sh_info of 2)
/usr/bin/ld: ../../../../external/linux-specific/fmod/prebuilt/64-bit/libfmod.so: .dynsym local symbol at index 4 (>= sh_info of 2)
/usr/bin/ld: cannot find -lXxf86vm
collect2: error: ld returned 1 exit status
make[2]: *** [engine/tests/cpp-empty-test/CMakeFiles/cpp-empty-test.dir/build.make:153: bin/cpp-empty-test/cpp-empty-test] Error 1
make[1]: *** [CMakeFiles/Makefile2:1292: engine/tests/cpp-empty-test/CMakeFiles/cpp-empty-test.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
~/cocos2d-x-3.17.2/cmake-build$ 

Я так понимаю, что библиотеки собрались, а вот примеры не хотят. Кто знает в чем причина? Заранее благодарен за любые содержательные ответы.

PS. Файлы libXxf86vm.so.1 и libXxf86vm.so.1.0.0 в /usr/lib/x86_64-linux-gnu/ присутствуют.

PS2. sudo apt-get update && sudo apt-get install libxxf86vm-dev пробовал.

 , ,

Gyros
()

RSS подписка на новые темы